权限系统,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

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

  1. 简洁经常使用权限系统的设计与实现(一):构造权限菜单树的N(N&gt;=4)种方法

    权限系统.Web开发常见标准子系统之中的一个.结合自己的一些思考和实践,从本篇開始权限系统的设计与实现之路. 近期,重构了项目的权限菜单构造过程,向前端返回json格式的权限树. 这一篇.仅仅是大致介 ...

  2. 基于资源的权限系统-API设计

    概述 权限系统需要和别的系统集成,因此,良好的API是易用性的保证. 这里只设计一些权限相关的核心 API,关于用户,组织,导入导出之类的后续再逐步补充 API 设计 围绕权限有以下 4 类 API: ...

  3. python 全栈开发,Day107(CRM初始,权限组件之权限控制,权限系统表设计)

    一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...

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

    虚拟机是每一个程序猿必备的工具.本文依据最新版VirtualBox用户手冊的提示,通过自己的亲自实践,给出了Win7系统与执行在当中的VirtualBox 5.0.2中的Ubuntu 14.04共享信 ...

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

    第三篇中,我们通过维护节点的深度level,通过迭代所有的节点,只需要一次,就构造了树.  本篇,换一种方式. 好处是:不维护节点的深度level,增加和修改节点时,也不用维护.递归实现,代码比较清晰 ...

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

    如果在节点的属性中,增加一个level属性,即树的深度,构造树会非常容易.前提是,增加和修改节点的时候,要维护level. 根节点的level为1,下一级为2,以此类推. 构造树的方法,主要有2个: ...

  7. 简洁常用权限系统的设计与实现(六):不维护节点的深度level,手动计算level,构造树 (把一颗无序的树,变成有序的)

     本篇介绍的方法,参考了网上的代码.在递归过程中,计算level,是受到了这种方法的启发. CSDN上有篇关于树的算法,目标是把一个无序的树,变成有序的. 我看了下代码,并运行了下,感觉是可行的. 我 ...

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

     这种方式,与第三篇中介绍的类似.不同的是,数据库中不存储节点的深度level,增加和修改时,也不用维护.而是,在程序中,实时去计算的. 至于后面的,按照level升序排序,再迭代所有的节点构造树,与 ...

  9. 设置Linux系统的空闲等待时间TMOUT的方法和Linux反空闲设置的两种方法

    为了增强linux系统的安全性,我们需要在用户输入空闲一段时间后自动断开,这个操作可以由设置TMOUT值来实现.将以下字段加入到/etc/profile 中即可(对所有用户生效). export TM ...

随机推荐

  1. APM2.8 Rover 自己主动巡航车设计(固件安装和设置)

    1.2 APM2.8软件安装与固件下载 下载Mission Planner这个地面基站软件,这里介绍的是windoews平台下的,在MAC或者linux下能够使用QGroundCont基于QT编写的地 ...

  2. ontouch、dispatchtouchevent、interceptouchevent-相关事件

    这几天一直在研究onTouch的相关方法,今天我们就来看看onTouchEvent.dispatchTouchEvent.onIntercepTouchEvent这三个方法在控件之间的传递顺序 pub ...

  3. js进阶 14-8 表单序列化函数serializeArray()和serialize()的区别是什么

    js进阶 14-8 表单序列化函数serializeArray()和serialize()的区别是什么 一.总结 一句话总结:两者都是对表单进行序列化,serializeArray()返回的是json ...

  4. Nginx详细编译参数

    本参数基于Nginx-1.15.2安装包 一 路径参数 1.1.1 指定Nginx安装路径 --prefix=/usr/local/nginx- 1.1.2 设置Nginx可执行文件路径默认路径在 - ...

  5. Python 极简教程(六)运算符

    运算符,我们日常生活中使用的加减乘除,都是运算符的一种.当然这种一般我们称为算术运算符,用于处理数字运算的. 但是在计算机语言中,还有很多的运算符.用于处理不用的情况. 主要有以下几类: 算术运算符 ...

  6. SpringMVC学习总结(2)——SpringMVC返回json配置

    <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <bean id="mappingJacksonHttpMessageConverter" c ...

  7. PatentTips - Method and Apparatus to Support Virtualization with Code Patches

    BACKGROUND As recognized in Revision 2.0 of the Intel® Virtualization Technology Specification for t ...

  8. 洛谷 P3131 [USACO16JAN]子共七Subsequences Summing to Sevens

    P3131 [USACO16JAN]子共七Subsequences Summing to Sevens 题目描述 Farmer John's NN cows are standing in a row ...

  9. 边缘独立(marginal independent)的理解及举例

    1. 定义 ∀xi∈dom(X),yj∈dom(Y),yk∈dom(Y),如果满足, P(X=xi|Y=yj)==P(X=xi|Y=yk)P(X=Xi) 则称随机变量 X 边缘独立于随机变量 Y. 理 ...

  10. php课程 2-7 php中常量如何定义

    php课程 2-7 php中常量如何定义 一.总结 一句话总结:函数方式定义和普通变量方式定义    define('PI','3.14').键值对,和session一样.    const PI=3 ...