简洁常用权限系统的设计与实现(一):构造权限菜单树的N(N>=4)种方法

权限系统,Web开发常见标准子系统之一。结合自己的一些思考和实践,从本篇开始权限系统的设计与实现之路。

最近,重构了项目的权限菜单构造过程,向前端返回json格式的权限树。

这一篇,只是大致介绍下这个问题,并给出4种方法的整体思路,后续再分别详细介绍这4种方法,再往后介绍完整的权限系统的设计与实现。

权限表的结构:
 acl、parent_acl, 最重要的就是这2个字段,有了这2个字段,就可以构造一棵树了。

前端需要的json格式:

"data":[{

"acl":1,

"children":[{

"acl":11,

"children":[{

"acl":111,

}]

}

方法1:
   在数据库再增加1个level字段,最顶层的level就是1,每增加一级level增加1。

先从数据库按照level升序,获得所有的权限节点。
            List<Map<String, Object>> rootList = new ArrayList<Map<String, Object>>(); 
             Map<String, Map<String, Object>> rootMap = new HashMap<String, Map<String, Object>>(); 
  for (遍历) {

创建节点,加入到根节点map中

if (顶级节点) {

加入到rootList中

} else {

获得父结点,把自己放到父结点的children中

}

}

遍历结束,rootList即为所求。

这种方法是一个同事的思路,关键就是2点,一是维护level(增加和修改的时候都需要),2是要按照level升序排序。

方法2:数据库不需要level字段,用递归来实现。
    List<Map<String, Object>> finalRootList = new ArrayList<Map<String, Object>>();

List<Map<String, Object>> rootList = findRootList(privilegeList);

List<Map<String, Object>> notRootList = findNotRootList(privilegeList);
               //先找出根节点,再为这些根节点构造子结点

for (Map<String, Object> root : rootList) {

// 构造子结点

buildChildList(root, notRootList);

finalRootList.add(root);

}

关键代码buildChildList是个递归函数。
   buildChildList(){
      从所有的非根节点中,找到当前节点的第1级子结点,加入到该节点的children中。
     buildChildList();
  }

好处是,不用维护level字段,增加和修改权限的时候,既不用维护level,也不用维护parent_acl。

方法3:完全按照方法1的思路,唯一不同的是,数据库不维护level字段,而是在查询数据出来之后,手动计算每个节点的level字段,进行排序。后面的步骤,和方法1基本一样。

因此,这种方法的唯一难点就是,如何计算一颗N叉树每一个节点的深度。

方法4: 计算一颗N叉树每一个节点的深度,经过实践,至少有2种方法。

a.按照方法2的递归思路,再维护一个level,向child深入一层,level++,返回level--。及时保存当前节点的level,递归结束,level就都计算完成。

b. 参照网上的一种思路,把“无序的Tree格式的List,转化打印出标准格式Treelist”。
  作者也是按照递归思路实现的,在这个代码的基础上,再维护1个level,就可以了。

a和b的思路相似的地方是,都在递归过程中维护1个level,不同的地方是,a的方法只单纯地计算level,而b不但计算了level,还把节点排序了。当然,a方法也是可以的。

方法5:这种方法不可行,问题是,存在着重复计算的可能。
 所有节点初始level额外i1.
 找到所有的根节点。

遍历每一个节点,如果发现自己有父结点,就把自己的level和所有父节点的level+1。
  
问题:无法保证多个子结点,都有子结点的时候,他们的父结点,重复增加了level,而重复计算的次数很难去统计。

小雷FansUnion-博学的互联网技术工作者,提供付费的IT咨询服务
2014年11月17日

湖北-武汉-循礼门

原文首发:http://fansunion.cn/article/detail/566.html

时间: 2024-10-23 22:24:07

简洁常用权限系统的设计与实现(一):构造权限菜单树的N(N>=4)种方法的相关文章

简洁常用权限系统的设计与实现(七):一种错误的不可行的构造树的方法

前面介绍了4种方法(实质是3种),构造树. 在此,需要特别说明的是,那些都是成功的.漂亮的方法和案例 ,但实际上在解决问题的过程中,有很多其它的尝试.比如本篇介绍的方法,就是不可行的.  想说明一个道理,在走向成功的道路上,会经历很多不算太成功的事情. 我们在前面的例子中,用递归计算子结点的深度level.但实际上,我最开始想到的一种方法正好反过来了. 思路:最底层的节点level为1,如果当前节点有父结点,就把自己的level+1,递归把自己的父结点的level+1. // 计算所有节点的le

Win7系统与它的Virtualbox中安装的Ubuntu14.04共享信息的几种方法

虚拟机是每个程序员必备的工具.本文根据最新版VirtualBox用户手册的提示,通过自己的亲自实践,给出了Win7系统与运行在其中的VirtualBox 5.0.2中的Ubuntu 14.04共享信息的三种方法,而不仅仅是建立二者的共享文件夹. 在学习新的技术时,或者做不同的测试时,为了节省硬件的目的,我们常常安装虚拟机,并在其中安装不同的操作系统.我们把运行在硬件的本来的那个操作系统称为主操作系统 (host OS),而把运行在虚拟机上面的操作系统称为客操作系统 (guest OS).这时,在

简洁常用权限系统的设计与实现(三):维护和利用节点的深度level,迭代实现树的构造

如果在节点的属性中,增加一个level属性,即树的深度,构造树会非常容易.前提是,增加和修改节点的时候,要维护level. 根节点的level为1,下一级为2,以此类推. 构造树的方法,主要有2个: // 按照level排序,根节点在上,子结点在下 public static List<Map<String, Object>> buildTree(List<TreeNode> list) { List<Map<String, Object>> r

简洁常用权限系统的设计与实现(四):不维护level,用递归方式构造树

第三篇中,我们通过维护节点的深度level,通过迭代所有的节点,只需要一次,就构造了树.  本篇,换一种方式. 好处是:不维护节点的深度level,增加和修改节点时,也不用维护.递归实现,代码比较清晰.  坏处是:节点较多的时候,性能可能不够好.不能直接查询到节点的深度level.当然,如果需要level字段,在递归过程中,是可以计算得到的.关于在递归过程中,计算level,后面有介绍这种方法. 关于树的遍历和查找,大家都有基础,上面描述了一些总体思路,代码中有注释,基本就不用再详细介绍了. /

简洁常用权限系统的设计与实现(五):不维护节点的深度level,手动计算level,构造树

这种方式,与第三篇中介绍的类似.不同的是,数据库中不存储节点的深度level,增加和修改时,也不用维护.而是,在程序中,实时去计算的. 至于后面的,按照level升序排序,再迭代所有的节点构造树,与第三篇中的方法,完全一样.因此,本篇和下一篇,只介绍如何计算level,不再介绍后面的具体实现了. 计算level,采用递归方式. // 计算所有节点的level public static List<Map<String, Object>> caculateLevel( List<

电子商务系统的设计与实现(十四):菜单高亮

菜单高亮,几乎是所有Web网站都需要的一个功能. 这个功能,说起来,简单得很,给当前页面的菜单增加一个高亮样式,删除其它菜单的高亮样式. 如果只高亮1个页面的菜单, 太简单了,但是如果菜单和页面比较多,就产生了争议. 第1种方式:每个页面单独高亮. <li id="indexli"><a href="${base}/">首页</a></li> <script type="text/javascript&

权限系统组织管理—具体设计说明书

前言: 上次聚哥让写具体设计文档.自己也写了自己模块的,认为写的挺好的.可是后来娥接手权限.我跟她说权限逻辑的时候,才发现非常多东西在具体设计文档中都没有写出来,所下面一个人接手的话,又要跑来问好多逻辑的问题.每一次都要做非常多反复性的工作.还有上次.做PB中期验收的毕业设计的时候,我没有下载到直接带着数据库的,可是材料中有数据库说明书,写的特别具体.所以我就依照别人的数据库说明书,搭建起来了,系统也成功跑起来了.这个时候认为这些文档特别的实用.所以,我想,别人看了我的具体设计说明书,是不是也可

权限系统概要

前言: 权限往往是一个极其复杂的问题,但也可简单表述为这样的逻辑表达式:判断"Who对What(Which)进行How的操作"的逻辑表达式是否为真.针对不同的应用,需要根据项目的实际情况和具体架构,在维护性.灵活性.完整性等N多个方案之间比较权衡,选择符合的方案. 目标: 直观,因为系统最终会由最终用户来维护,权限分配的直观和容易理解,显得比较重要,系统不辞劳苦的实现了组的继承,除了功能的必须,更主要的就是因为它足够直观. 简单,包括概念数量上的简单和意义上的简单还有功能上的简单.想用

mysqsl--用户-角色-权限表的设计

设计一个灵活.通用.方便的权限管理系统. 在这个系统中,我们需要对系统的所有资源进行权限控制,那么系统中的资源包括哪些呢?我们可以把这些资源简单概括为静态资源(功能操作.数据列)和动态资源(数据),也分别称为对象资源和数据资源,后者是我们在系统设计与实现中的叫法. 系统的目标就是对应用系统的所有对象资源和数据资源进行权限控制,比如应用系统的功能菜单.各个界面的按钮.数据显示的列以及各种行级数据进行权限的操控. 三.相关对象及其关系 大概理清了一下权限系统的相关概念,如下所示: 1.