1.数据回现:
  不论什么回显只需在跳转页面时,传递属性值即可

2.设置级联操作:如:删除顶级部门时,删除所有子部门
  casecade:根据需要设置

3.查找顶级部门,查找子部门
   1)("from Department d where d.parent is NULL").list
   2)("from Department d where d.parent.id=?").setParameter(0,parentId).list

4.OGNL表达式
   1)判断:userAction_%{id==null? 'add':'edit'}
   2)获取数组某个值如:%{#departmentList[0].parent.id}

5.树状结构
  1)工具类:
-------------------------------------------------------------------------------

/**
     * 遍历部门树,得到所有的部门列表,并修改了名称以表示层次。
     *
     * @param topList
     * @return
     */
    public static List<Department> getAllDepartments(List<Department> topList) {
        List<Department> list = new ArrayList<Department>();
        walkDepartmentTrees(topList, "┣", list);
        return list;
    }

    /*
     * 遍历部门树,把遍历出来的部门都放到指定的集合中
     */
    private static void walkDepartmentTrees(Collection<Department> topList, String prefix, List<Department> list) {
        for (Department top : topList) {
            // 顶点
            Department copy = new Department(); // 原对象是在Session中的对象,是持久化状态,所以要使用副本。
            copy.setId(top.getId());
            copy.setName(prefix + top.getName());
            list.add(copy);
            // 子树
            walkDepartmentTrees(top.getChildren(), " " + prefix, list); // 使用的是全角的空格
        }
    }



-------------------------------------------------------------------------------------


   2)配置子部门排序:

<set name="children" sort="unsorted" cascade="delete" order-by="id"> 

 ========================================================================================================


6.登陆权限的实现:

   思路:

     1)创建监听器继承ServletContextListener接口,监听服务器容器的创建销毁
     2)在init中获取所有的权限信息,放入application作用域

     3)在页面进行权限的判断显示(主菜单)

   1.建立用户===角色===权限的多对多关系,创建表,映射


   2.初始化权限数据,初始化超级管理员      MD5加密的使用:DigestUtils.md5Hex("admin")


   3.设置权限树(权限管理)的显示及效果      roleAction/setPrivilegeUI.jsp


   4.     1)创建监听器继承ServletContextListener接口,监听服务器容器的创建销毁


          2)在init中获取所有的权限信息,放入application作用域


          ----------------------------------------------------------------------


                    

public void contextInitialized(ServletContextEvent sce) {
                                ServletContext application=sce.getServletContext();
                                
                                //得到service的对象实例
                                ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(application);
                                PrivilegeService privilegeService=(PrivilegeService) ac.getBean("privilegeServiceImpl");
                                
                                
                                //准备所有顶级权限的集合(顶级菜单)
                                List<Privilege> topPrivilegeList=privilegeService.findTopList();
                                application.setAttribute("topPrivilegeList", topPrivilegeList);
                                System.out.println("------已准备好顶级权限的数据----------");
                                
                                //准备所有权限的url集合(用于拦截器中权限的判断,防止用户手工输入地址)
                                 List<String> allPrivilegeUrls=privilegeService.getAllPrivilegeUrls();
                                 application.setAttribute("allPrivilegeUrls",allPrivilegeUrls);
                                    System.out.println("------已准备好所有权限的url数据");
                            }



          ----------------------------------------------------------------------


           3)在页面进行权限的判断显示(主菜单)


                ①懒加载异常的处理


                                        将所有相关联的数据(role,user,privilege):lazy="false"


                ①核心代码:


                                         页面:    homeAction/left.jsp


          -----------------------------------------------------------------------


                           

<ul id="MenuUl">
                                <%-- 顶级菜单 --%>
                                <s:iterator value="#application.topPrivilegeList">
                    ☆            <s:if test="#session.user.hasPrivilegeByName(name)">
                                    <li class="level1">
                                        <div onClick="menuClick(this);" class="level1Style">
                                            <img src="style/images/MenuIcon/${icon}" class="Icon" />
                                            ${name}
                                        </div>
                                        <%-- 二级菜单 display: none; --%>
                                        <ul style="" class="MenuLevel2">
                                            <s:iterator value="children">
                                            <s:if test="#session.user.hasPrivilegeByName(name)">
                                                <li class="level2">
                                                    <div class="level2Style">
                                                        <img src="style/images/MenuIcon/menu_arrow_single.gif" />
                                                        <a target="right" href="${pageContext.request.contextPath}/${url}.action"> ${name}</a>
                                                     </div>
                                                </li>
                                            </s:if>
                                            </s:iterator>
                                        </ul>
                                    </li>
                                </s:if>
                                </s:iterator>        
                            </ul>



    -------------------------------------------------------------------------------------------------------


                                          后台: domian/user.hasPrivilegeByName


                                        

public boolean hasPrivilegeByName(String privilegeName){
                                            //超级管理员有所有的权限
                                            if(isAdmin()){
                                                return true;
                                            }
                                            
                                            //一般用户有权限才返回true
                                            for(Role role:roles){
                                                for(Privilege privilege:role.getPrivileges()){
                                                    if(privilege.getName().equals(privilegeName)){
                                                        return true;
                                                    }
                                                }
                                            }
                                            return false;
                                        }




    ---------------------------------------------------------------------------------------------------------


           


         5.进行三级菜单的判断显示(方案:重写<s:a>的doendTag方法)


                  1)重写类  org/apache/struts2/views/jsp/ui/AnchorTag.java


                  2)重写方法


           --------------------------------------------------------------------------------------------------


                            

public int doEndTag() throws JspException {
                                    //获取当前用户
                                    User user= (User) pageContext.getSession().getAttribute("user");
                                    
                                    //获取当前url  如果有参数就要去掉后面的参数字符串
                                    String privilegeUrl=action;
                                    System.out.println(action+"----------------------------");
                                    int pos=privilegeUrl.indexOf("?");
                                    if(pos>-1){
                                        privilegeUrl=privilegeUrl.substring(0,pos);
                                    }
                                    
                                    if(user.hasPrivilegeByUrl(privilegeUrl)){
                                        //如果有权限则正常的生成与输出a标签
                                        return super.doEndTag();
                                    }else{
                                        //没有权限不显示任何东西,继续执行页面中后面的代码
                                        return EVAL_PAGE;
                                    }
                                }



           


           ---------------------------------------------------------------------------------------------------


          6.配建登陆拦截器实现intercepter接口,进行登陆拦截判断(判断用户是否登陆,防止用户直接输入地址)


              1)在监听器中,将所有的权限url放入application中(不包含null(主菜单)和重复的)


              2)在拦截器中判断用户:                       类:CheckPrivilegeInterceptor


                     1.是否已经登陆,及是否正要去登陆                                


                     2.判断已登陆用户的权限(从url集合中排除公共权限,如:注销,登陆)      方法:user.hasPrivilegeByUrl();


           ---------------------------------------------------------------------------------------------------------------


 

public class CheckPrivilegeInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        //获取当前用户
        User user=(User) ActionContext.getContext().getSession().get("user");
        //获取当前访问的url,并去掉当前应用 的前缀(也就是nameSpace+actionName)
        String privilegeUrl=null;
        String namespace=invocation.getProxy().getNamespace();
        String actionName=invocation.getProxy().getActionName();
        
        if(namespace.endsWith("/")){
            privilegeUrl=namespace+actionName;
        }else{
            privilegeUrl=namespace+"/"+actionName;
        }
        
        //去掉开头的‘/’
        if(privilegeUrl.startsWith("/")){
            privilegeUrl=privilegeUrl.substring(1);
        }
        
        //如果未登陆用户
        if(user==null){
            if(privilegeUrl.startsWith("userAction_login")){
                //如果是去登陆,则放行
                return invocation.invoke();
            }else{
                //如果不是去登陆,就转到登陆界面
                return "loginUI";
            }
        }else{
            //如果已经登陆,则判断权限
            if(user.hasPrivilegeByUrl(privilegeUrl)){
                //如果有权限就放行
                return invocation.invoke();
            }else{
                //如果没有就转到提示页面
                return "noPrivilegeError";
            }
        }
        
    }

}
               --------------------------------------------------------------------------------------------------------
public boolean hasPrivilegeByUrl(String privilegeUrl) {
        // 超级管理员有所有的权限
        if (isAdmin()) {
            return true;
        }

        // 如果以UI后缀结尾,就去掉UI后缀,以得到对应的权限(例如:addUI与add是同一个权限)
        if (privilegeUrl.endsWith("UI")) {
            privilegeUrl = privilegeUrl.substring(0, privilegeUrl.length() - 2);
        }
        
        //取出数据库中所有的权限url
        List<String> allPrivilegeUrls=(List<String>) ActionContext.getContext().getApplication().get("allPrivilegeUrls");
        
        if(!allPrivilegeUrls.contains(privilegeUrl)){
            //设置不需要控制的功能,权限 如:userAction_loginUI/login/homeAction_index
            return true;
        }else{
            //要控制的功能
            // 其他用户要是有权限才返回true
            for (Role role : roles) {
                for (Privilege privilege : role.getPrivileges()) {
                    if (privilegeUrl.equals(privilege.getUrl())) {
                        return true;
                    }
                }
            }
        }
        
            return false;
    }




           ================================================================================================================


          7.细节处理:


             1) 解决服务器重启session失效问题           :     序列化  implements Serializable  


             2)session过期导致登陆页面层叠嵌套问题          :   刷新上级窗口


                     if (window.parent != window) {


                           window.parent.location.reload(true);     


                      }