SpringMVC+Ztree 实现权限菜单配置 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
javahih
V2EX    Java

SpringMVC+Ztree 实现权限菜单配置

  •  
  •   javahih Dec 24, 2017 3603 views
    This topic created in 3048 days ago, the information mentioned may be changed or developed.

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

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

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

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

    这里写图片描述

    角色信息实体类:

    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 y 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=" 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> &nbsp;&nbsp; <input type="button" OnClick="doSave()" value="保存" class="buttonStyle" /> <input OnClick="dialogClose();" class="buttonStyle" type="button" value="关闭" /> </body> </html> 

    这里写图片描述

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

    1 replies    2017-12-24 15:26:10 +08:00
    miao1007
        1
    miao1007  
       Dec 24, 2017
    嗯...DOM 操作看的好累
    About     Help     Advertise     Blog     API     FAQ     Solana     3249 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 13:21 PVG 21:21 LAX 06:21 JFK 09:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86