SpringMVC+ZTree实现树形菜单权限配置

只谈情不闲聊 提交于 2020-08-17 17:32:29

计划在开源项目里加入权限配置的功能,打算加入zTree实现树形结构。

Team的Github开源项目链接:https://github.com/u014427391/jeeplatform
欢迎star(收藏)

zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。

zTree下载链接:http://www.treejs.cn/v3/main.php#_zTreeInfo

20200801001615\_1.png

角色信息实体类:

    package org.muses.jeeplatform.core.entity.admin;

    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;

    /**
     * @description 角色信息实体类
     * @author Nicky
     * @date 2017年3月16日
     */
    @Table(name="sys_role")
    @Entity
    public class Role implements Serializable{

        /** 角色Id**/
        private int roleId;

        /** 角色描述**/
        private String roleDesc;

        /** 角色名称**/
        private String roleName;

        /** 角色标志**/
        private String role;

        private Set<Permission> permissions = new HashSet<Permission>();

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        public int getRoleId() {
            return roleId;
        }

        public void setRoleId(int roleId) {
            this.roleId = roleId;
        }

        @Column(length=100)
        public String getRoleDesc() {
            return roleDesc;
        }

        public void setRoleDesc(String roleDesc) {
            this.roleDesc = roleDesc;
        }

        @Column(length=100)
        public String getRoleName() {
            return roleName;
        }

        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }

        @Column(length=100)
        public String getRole() {
            return role;
        }

        public void setRole(String role) {
            this.role = role;
        }

        //修改cascade策略为级联关系
        @OneToMany(targetEntity=Permission.class,cascade=CascadeType.MERGE,fetch=FetchType.EAGER)
        @JoinTable(name="sys_role_permission", joinColumns=@JoinColumn(name="roleId",referencedColumnName="roleId"), inverseJoinColumns=@JoinColumn(name="permissionId",referencedColumnName="id",unique=true))
        public Set<Permission> getPermissions() {
            return permissions;
        }

        public void setPermissions(Set<Permission> permissions) {
            this.permissions = permissions;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Role) {
                Role role = (Role) obj;
                return this.roleId==(role.getRoleId())
                        && this.roleName.equals(role.getRoleName())
                        && this.roleDesc.equals(role.getRoleDesc())
                        && this.role.equals(role.getRole());
            }
            return super.equals(obj);
        }
    }

权限信息实体类:

    package org.muses.jeeplatform.core.entity.admin;

    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;

    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.OneToOne;
    import javax.persistence.Table;

    /**
     * @description 权限操作的Vo类
     * @author Nicky
     * @date 2017年3月6日
     */
    @Table(name="sys_permission")
    @Entity
    public class Permission implements Serializable {

        private int id;
        private String pdesc;
        private String name;
        private static final long serialVersionUID = 1L;

        private Menu menu;

        private Set<Operation> operations = new HashSet<Operation>();

        public Permission() {
            super();
        }

        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        public int getId() {
            return this.id;
        }

        public void setId(int id) {
            this.id = id;
        }

        @Column(length=100)
        public String getPdesc() {
            return this.pdesc;
        }

        public void setPdesc(String pdesc) {
            this.pdesc = pdesc;
        }

        @Column(length=100)
        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @OneToOne(targetEntity=Menu.class,cascade=CascadeType.REFRESH,fetch=FetchType.EAGER)
        @JoinColumn(name="menuId",referencedColumnName="menuId")
        public Menu getMenu() {
            return menu;
        }

        public void setMenu(Menu menu) {
            this.menu = menu;
        }

        @ManyToMany(targetEntity=Operation.class,cascade=CascadeType.MERGE,fetch=FetchType.EAGER)
        @JoinTable(name="sys_permission_operation",joinColumns=@JoinColumn(name="permissionId",referencedColumnName="id"),inverseJoinColumns=@JoinColumn(name="operationId",referencedColumnName="id"))
        public Set<Operation> getOperations() {
            return operations;
        }

        public void setOperations(Set<Operation> operations) {
            this.operations = operations;
        }
    }

实现菜单信息实体类,用JPA来实现

    package org.muses.jeeplatform.core.entity.admin;

    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.List;

    /**
     * @description 菜单信息实体
     * @author Nicky
     * @date 2017年3月17日
     */
    @Table(name="sys_menu")
    @Entity
    public class Menu implements Serializable {

        /** 菜单Id**/
        private int menuId;

        /** 上级Id**/
        private int parentId;

        /** 菜单名称**/
        private String menuName;

        /** 菜单图标**/
        private String menuIcon;

        /** 菜单URL**/
        private String menuUrl;

        /** 菜单类型**/
        private String menuType;

        /** 菜单排序**/
        private String menuOrder;

        /**菜单状态**/
        private String menuStatus;

        private List<Menu> subMenu;

        private String target;

        private boolean hasSubMenu = false;

        public Menu() {
            super();
        }   

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        public int getMenuId() {
            return this.menuId;
        }

        public void setMenuId(int menuId) {
            this.menuId = menuId;
        }

        @Column(length=100)
        public int getParentId() {
            return parentId;
        }

        public void setParentId(int parentId) {
            this.parentId = parentId;
        }

        @Column(length=100)
        public String getMenuName() {
            return this.menuName;
        }

        public void setMenuName(String menuName) {
            this.menuName = menuName;
        }   

        @Column(length=30)
        public String getMenuIcon() {
            return this.menuIcon;
        }

        public void setMenuIcon(String menuIcon) {
            this.menuIcon = menuIcon;
        }   

        @Column(length=100)
        public String getMenuUrl() {
            return this.menuUrl;
        }

        public void setMenuUrl(String menuUrl) {
            this.menuUrl = menuUrl;
        }   

        @Column(length=100)
        public String getMenuType() {
            return this.menuType;
        }

        public void setMenuType(String menuType) {
            this.menuType = menuType;
        }

        @Column(length=10)
        public String getMenuOrder() {
            return menuOrder;
        }

        public void setMenuOrder(String menuOrder) {
            this.menuOrder = menuOrder;
        }

        @Column(length=10)
        public String getMenuStatus(){
            return menuStatus;
        }

        public void setMenuStatus(String menuStatus){
            this.menuStatus = menuStatus;
        }

        @Transient
        public List<Menu> getSubMenu() {
            return subMenu;
        }

        public void setSubMenu(List<Menu> subMenu) {
            this.subMenu = subMenu;
        }

        public void setTarget(String target){
            this.target = target;
        }

        @Transient
        public String getTarget(){
            return target;
        }

        public void setHasSubMenu(boolean hasSubMenu){
            this.hasSubMenu = hasSubMenu;
        }

        @Transient
        public boolean getHasSubMenu(){
            return hasSubMenu;
        }

    }

实现JpaRepository接口

    package org.muses.jeeplatform.core.dao.repository.admin;

    import org.muses.jeeplatform.core.entity.admin.Role;
    import org.springframework.data.jpa.repository.JpaRepository;

    /**
     * Created by Nicky on 2017/12/2.
     */
    public interface RoleRepository extends JpaRepository<Role,Integer> {

    }

实现JpaRepository接口

    package org.muses.jeeplatform.core.dao.repository.admin;

    import org.muses.jeeplatform.core.entity.admin.Menu;
    import org.springframework.data.jpa.repository.JpaRepository;

    /**
     * Created by Nicky on 2017/6/17.
     */
    public interface MenuTreeRepository extends JpaRepository<Menu,Integer>{

    }

角色Service类:

    package org.muses.jeeplatform.service;

    import com.google.common.collect.Lists;
    import org.muses.jeeplatform.core.dao.repository.admin.RolePageRepository;
    import org.muses.jeeplatform.core.entity.admin.Role;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.stereotype.Service;

    import java.util.List;

    /**
     * Created by Nicky on 2017/7/30.
     */
    @Service
    public class RolePageService {

        @Autowired
        RolePageRepository roleRepository;

        /**
         * 构建PageRequest对象
         * @param num
         * @param size
         * @param asc
         * @param string
         * @return
         */
        private PageRequest buildPageRequest(int num, int size, Sort.Direction asc,
                                             String string) {
            return new PageRequest(num-1, size,null,string);
        }

        /**
         * 获取所有的菜单信息并分页显示
         * @param pageNo
         *          当前页面数
         * @param pageSize
         *          每一页面的页数
         * @return
         */
        public Page<Role> findAll(int pageNo, int pageSize, Sort.Direction dir, String str){
            PageRequest pageRequest = buildPageRequest(pageNo, pageSize, dir, str);
            Page<Role> roles = roleRepository.findAll(pageRequest);
            return roles;
        }

        public List<Role> findAllRole(){
            Iterable<Role> roles = roleRepository.findAll();
            List<Role> myList = Lists.newArrayList(roles);
            return myList;
        }

        /**
         * 根据角色id查找角色信息
         * @param roleId
         * @return
         */
        public Role findByRoleId(String roleId){
            return roleRepository.findOne(Integer.parseInt(roleId));
        }

        /**
         * 保存角色信息
         * @param role
         */
        public void doSave(Role role){
            roleRepository.save(role);
        }

    }

菜单Service类:

    package org.muses.jeeplatform.service;

    import org.muses.jeeplatform.annotation.RedisCache;
    import org.muses.jeeplatform.common.RedisCacheNamespace;
    import org.muses.jeeplatform.core.dao.repository.admin.MenuTreeRepository;
    import org.muses.jeeplatform.core.entity.admin.Menu;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.List;

    /**
     * Created by Nicky on 2017/6/17.
     */
    @Service
    public class MenuTreeService {

        @Autowired
        MenuTreeRepository menuTreeRepository;

        /**
         * 查询所有的菜单
         * @return
         */
        @Transactional
        //@RedisCache
        public List<Menu> findAll(){
            return menuTreeRepository.findAll();
        }

    }

在Controller类里通过角色id获取该角色可以查看的菜单:

    /**
         * 跳转到角色授权页面
         * @param roleId
         * @param model
         * @return
         */
        @RequestMapping(value = "/goAuthorise" )
        public String goAuth(@RequestParam String roleId, Model model){

            List<Menu> menuList = menuTreeService.findAll();

            Role role = roleService.findByRoleId(roleId);

            Set<Permission> hasPermissions = null;

            if(role != null){
                hasPermissions = role.getPermissions();
            }

            for (Menu m : menuList) {
                for(Permission p : hasPermissions){
                    if(p.getMenu().getMenuId()==m.getMenuId()){
                        m.setHasSubMenu(true);
                    }
                }
            }

            model.addAttribute("roleId" , roleId);

            JSONArray jsonArray = JSONArray.fromObject(menuList);
            String json = jsonArray.toString();

            json = json.replaceAll("menuId","id").replaceAll("parentId","pId").
                    replaceAll("menuName","name").replaceAll("hasSubMenu","checked");

            model.addAttribute("menus",json);

            return "admin/role/role_auth";
        }

在前端通过zTree实现树形菜单展示,通过勾选然后实现角色授权:

    <%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
    <%
        String path = request.getContextPath();
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <base href="<%=basePath %>">
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <title>Insert title here</title>
        <!-- 引入JQuery库 start -->
        <script type="text/javascript" src="${basePath}static/js/jquery-1.8.3.js"></script>
        <!-- 引入JQuery库 end -->
        <script type="text/javascript" src="<%=basePath%>plugins/zDialog/zDialog.js"></script>
        <script type="text/javascript" src="<%=basePath%>plugins/zDialog/zDrag.js"></script>
        <script type="text/javascript" src="<%=basePath%>plugins/zDialog/zProgress.js"></script>
        <link rel="stylesheet" href="<%=basePath%>plugins/zTree/3.5/zTreeStyle.css" type="text/css">
        <script type="text/javascript" src="<%=basePath%>plugins/zTree/3.5/jquery-1.4.4.min.js"></script>
        <script type="text/javascript" src="<%=basePath%>plugins/zTree/3.5/jquery.ztree.core.js"></script>
        <script type="text/javascript" src="<%=basePath%>plugins/zTree/3.5/jquery.ztree.excheck.js"></script>
        <script type="text/javascript">
            <!--
            var setting = {
                check: {
                    enable: true
                },
                data: {
                    simpleData: {
                        enable: true
                    }
                },
                callback:{
                    onClick: {

                    }
                }
            };

            /*[
             { id:1, pId:0, name:"随意勾选 1", open:true},
             { id:11, pId:1, name:"随意勾选 1-1", open:true},
             { id:12, pId:1, name:"随意勾选 1-2", open:true}
             ];*/

            var json = ${menus};
            var zNodes = eval(json);

            var code;

            function setCheck() {
                var zTree = $.fn.zTree.getZTreeObj("treeDemo"),
                    py = $("#py").attr("checked")? "p":"",
                    sy = $("#sy").attr("checked")? "s":"",
                    pn = $("#pn").attr("checked")? "p":"",
                    sn = $("#sn").attr("checked")? "s":"",
                    type = { "Y":py + sy, "N":pn + sn};
                zTree.setting.check.chkboxType = type;
                showCode('setting.check.chkboxType = { "Y" : "' + type.Y + '", "N" : "' + type.N + '" };');
            }
            function showCode(str) {
                if (!code) code = $("#code");
                code.empty();
                code.append("<li>"+str+"</li>");
            }

            $(document).ready(function(){
                $.fn.zTree.init($("#treeDemo"), setting, zNodes);
                setCheck();
                $("#py").bind("change", setCheck);
                $("#sy").bind("change", setCheck);
                $("#pn").bind("change", setCheck);
                $("#sn").bind("change", setCheck);
            });
            //-->

            function dialogClose()
            {
                parentDialog.close();
            }

            function doSave() {
                var zTree = $.fn.zTree.getZTreeObj("treeDemo");
                var nodes = zTree.getCheckedNodes();
                var tmpNode;
                var ids = "";
                for(var i=0; i<nodes.length; i++){
                    tmpNode = nodes[i];
                    if(i!=nodes.length-1){
                        ids += tmpNode.id+",";
                    }else{
                        ids += tmpNode.id;
                    }
                }
                var roleId = ${roleId};
                var params = roleId +";"+ids;
                alert(ids);
                $.ajax({
                    type: "POST",
                    url: 'role/authorise.do',
                    data: {params:params,tm:new Date().getTime()},
                    dataType:'json',
                    cache: false,
                    success: function(data){
                        if("success" == data.result){
                            alert('授权成功!请重新登录!');
                            parent.location.reload();
                            doDialogClose();
                        }else{
                            alert("授权失败!");
                        }
                    }
                });
            }

        </script>
    </head>
    <body >
    <div class="content_wrap">
        <div class="zTreeDemoBackground left">
            <ul id="treeDemo" class="ztree"></ul>
        </div>
    </div>
      
    <input type="button" onClick="doSave()" value="保存" class="buttonStyle" />
    <input onClick="dialogClose();" class="buttonStyle" type="button" value="关闭" />
    </body>
    </html>

2020080100166\_2.png

Team的Github开源项目链接:https://github.com/u014427391/jeeplatform
欢迎star(收藏)


来源:https://www.cnblogs.com/mzq123

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!