一. RBAC权限
1 概念
-
RBAC: Role-Based Access Control,基于角色的访问控制。也就是用户通过角色与权限进行关联,简单来讲,一个用户拥有若干用户,每一个角色拥有若干权限。
-
简单模型:在这种模型中,用户与角色之间,角色与权限之间,一般都是多对多的关系
- 扩展模型
2.级别
- RBAC 0 :核心模型,其他的级别都是建立在该级别的基础上
- RBAC 1 :基于RBAC0模型的基础上进行角色分层,也就是角色有了上下级的区别
- RBCA 2:基于RBAC0模型的基础上,进行了角色的访问控制
- RBCA 3:最全面级的权限管理,它是基于RBAC2的基础上,将RBAC1和RBAC2进行整合了,最全面,也最复杂的
3. 总结
任何系统中都会涉及到权限管理的模块,无论复杂简单,我们都可以通过以RBAC模型为基础,进行相关灵活运用来解决我们的问题
二. 许可维护树 — zTree
1.许可树原理:多层UL嵌套
2. 使用
- 导入相应jar包
- 源代码
3. 异步实现
-
jsp代码
var setting = { }; $.ajax({ url:"${APP_PATH}/permission/loadData.do", type:"post", success:function(result){ if(result.success){ var zNodes = result.data ; $.fn.zTree.init($("#treeDemo"), setting, zNodes); }else{ alert("加载数据失败..."); } } });
2.Controller:总共有5种方式,优先第五种方法,依次往后推
//Demo5 - 用Map集合来查找父,来组合父子关系.减少循环的次数 ,提高性能. @ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); List<Permission> childredPermissons = permissionService.queryAllPermission(); Map<Integer,Permission> map = new HashMap<Integer,Permission>();//100 for (Permission innerpermission : childredPermissons) { map.put(innerpermission.getId(), innerpermission); } for (Permission permission : childredPermissons) { //100 //通过子查找父 //子菜单 Permission child = permission ; //假设为子菜单 if(child.getPid() == null ){ root.add(permission); }else{ //父节点 Permission parent = map.get(child.getPid()); parent.getChildren().add(child); } } result.setSuccess(true); result.setData(root); } catch (Exception e) { result.setSuccess(false); result.setMessage("加载许可树数据失败!"); } return result ; } //Demo4 - 采用一次性加载所有permission数据;减少与数据的交互次数. /*@ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { //Demo 4 一次查询所有数据 List<Permission> root = new ArrayList<Permission>(); List<Permission> childredPermissons = permissionService.queryAllPermission(); for (Permission permission : childredPermissons) { //通过子查找父 //子菜单 Permission child = permission ; //假设为子菜单 if(child.getPid() == null ){ root.add(permission); }else{ //父节点 for (Permission innerpermission : childredPermissons) { if(child.getPid() == innerpermission.getId()){ Permission parent = innerpermission; parent.getChildren().add(child); break ; //跳出内层循环,如果跳出外层循环,需要使用标签跳出 } } } } result.setSuccess(true); result.setData(root); } catch (Exception e) { result.setSuccess(false); result.setMessage("加载许可树数据失败!"); } return result ; } */ //Demo3 - 采用递归调用来解决,许可树多个层次的问题. /*@ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); //父 Permission permission = permissionService.getRootPermission(); root.add(permission); queryChildPermissions(permission); result.setSuccess(true); result.setData(root); } catch (Exception e) { result.setSuccess(false); result.setMessage("加载许可树数据失败!"); } return result ; }*/ /** * 递归使用条件: * 1.调用自身方法 * 2.不断调用自身方法时,操作范围一定要缩小. * 3.一定要存在跳出条件. * @param permission */ private void queryChildPermissions(Permission permission){ List<Permission> children = permissionService.getChildrenPermissionByPid(permission.getId()); //组合父子关系 permission.setChildren(children); for (Permission innerChildren : children) { queryChildPermissions(innerChildren); } } //Demo2-从数据表t_permission查询数据,显示许可树. /*@ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); //父 Permission permission = permissionService.getRootPermission(); root.add(permission); //子 List<Permission> children = permissionService.getChildrenPermissionByPid(permission.getId()); //设置父子关系 permission.setChildren(children); for (Permission child : children) { child.setOpen(true); //根据父查找子 List<Permission> innerChildren = permissionService.getChildrenPermissionByPid(child.getId()); //设置父子关系 child.setChildren(innerChildren); } result.setSuccess(true); result.setData(root); } catch (Exception e) { result.setSuccess(false); result.setMessage("加载许可树数据失败!"); } return result ; }*/ //Demo1 - 模拟数据生成树 /*@ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); //父 Permission permission = new Permission(); permission.setName("系统权限菜单"); permission.setOpen(true); root.add(permission); //子 List<Permission> children = new ArrayList<Permission>(); Permission permission1 = new Permission(); permission1.setName("控制面板"); Permission permission2 = new Permission(); permission2.setName("权限管理"); children.add(permission1); children.add(permission2); //设置父子关系 permission.setChildren(children); result.setSuccess(true); result.setData(root); } catch (Exception e) { result.setSuccess(false); result.setMessage("加载许可树数据失败!"); } * {"success":true,"message":null,"page":null, * "data":[{"id":null,"pid":null,"name":"系统权限菜单","icon":null,"url":null,"open":true, * "children":[{"id":null,"pid":null,"name":"控制面板","icon":null,"url":null,"open":false,"children":null}, * {"id":null,"pid":null,"name":"权限管理","icon":null,"url":null,"open":false,"children":null}]}]} return result ; }*/
4. 字体图标
增加icon字段,用于显示许可树的字体图标
5. 鼠标悬停
鼠标放在连接上会出现编辑和删除按钮:
通过鼠标悬停事件实现该功能
查看ztree的API文档:查看addHoverDom事件
代码原理分析
6. 总结
-
树形结构的原理
(1) 关联数据形成上下级(父子)关系
(2) 通过查找父节点可以找到其中对应的子节点
(3) 树形结构的根节点只有一个,但是分支节点,叶子节点可以存在多个
-
树形结构的组件操作(ztree, jquery的插件)
-
Ztree配置对象setting含义
对树形结构进行相应的配置,如事件,复选框,异步加载等
-
ztree节点对象node属性含义
-
ztree树形数据操作
-
setting解释
-
ztree树形数据操作