设为首页 加入收藏

TOP

通向架构师的道路(第六天)之漫谈基于数据库的权限系统的设计(二)
2018-02-06 13:13:04 】 浏览:512
Tags:通向 架构 师的 道路 漫谈 基于 数据库 权限 系统 设计
m.menu_id, m.menu_descr, m.menu_url, m.menu_pidfrom t_menu_privilege mp, t_sys_menu m, t_privilege p, t_user_role r where mp.privilege_id=p.privilege_id and mp.role_id=r.role_id and mp.menu_id=m.menu_id and r.user_id='Danzel' STARTWITH MENU_PID='0' CONNECTBYPRIOR M.MENU_ID=M.MENU_PID orderby M.MENU_ID

 

将该结果直接给于index.jsp页面上的dtree.js组件,一个循环,所有菜单曾树形显示。

知道用户登录后能够对哪些菜单,并且在相关界面操作时有哪些子权限如:增、删、改、查、打印、报表的设计:

  • 在登录时得到用户名等信息,然后将该用户名作为参数input进入如下的sql语句:
selectdistinct m.menu_id,m.menu_descr,m.menu_url,m.menu_pid,p.privilege_id,p.privilege_type from

t_menu_privilege mp,

t_sys_menu m,

t_privilege p,

t_user_role r

where

mp.privilege_id=p.privilege_id

and mp.role_id=r.role_id

and mp.menu_id=m.menu_id

and r.user_id='Danzel'

orderby m.menu_id;

 

  • 得到上述结果后,使用:Haspmap<String menuId, List menuList>这样的结构将该用户所属的角色分对每个菜单有哪些操作(增、删、改、查、打印、报表)进行存储,放入用户的session中,在以后用户在每个界面进行点击动作时进行判断,或者可以写个filter来进行判断,是不是就可以作到:

知道该登录用户在登录后可以对哪些菜单进行操作,并且拥有什么操作权限啦?

相应的我们还需要制作如下的界面:

  • 用户的管理界面
  • 角色的管理界面
  • 用户与角色的分配界面
  • 系统菜单的管理界面
  • 具体权限项的管理界面
  • 系统菜单与角色间具体的权限分配界面

好了,有了这些界面,一个完整的基于数据库引擎的权限系统算是完成了。

严重注意:

在制作“系统菜单与角色间具体的权限分配界面”时,如果在界面上把某个角色对该条菜单的“查看”这个选项disable后,那么该角色将不拥有任何该菜单的所有权限,举例:

某角色对菜单A拥有如下权限:

增、删、改、打印

但是这个“查看”权限没有,也有可能是管理员误操作,但是从真实情况我们来说,这个角色连“查看”的权限都没有,连菜单都进不了,他能做什么“增、删、改。。。”等其它的操作啊?操作个头啊!是吧?

所以一旦界面上该角色对某个系统菜单没有了查看权限后,它对这个菜单的其它权限也必须从T_MENU_PRIVILEGE这个表中删除。

四、改进T_SYSTEM_MENU表的设计

前面我们用的是Oracle特有的递归SQL将树形菜单在从数据库中选取出来时就已经是一颗树的结构了,但是像MYSQL,SQL SERVER, DB2等可能不带有这样的特SQL,那就需我们自己动手去写递归,还有就是很多工程用的是jquery的tree或者是其它相关的ajax tree,这些tree都需要用到一个字段叫level(此处指深度、层次的意思),如果按照原来的表结构,要取得这个level,恐怕是要写递归算法了。就算有些数据库有类似的语句,那也需要你去修改你的SQL语句从未影响了性能与通用性。

我们在这边说,我们无论什么数据库,如果都用相同的SQL就能把我们需要的东西在数据库中就排好树形结构然后一次性选取出来,那应该有多好啊。答案是有的,在原来的T_SYSTEM_MENU表中改动也不大,只需要增加两个字段即可,即:lft与rgt(left, right),这种设计其实已经有了,我在此只不过结合实际例子把它应用到实际上,并且进一步详细描述如果来实现它,它就是被称为:

左右值无限分类实现算法也称为预排序遍历树算法,对于这种层次型数据(Hierarchical Data)一般我们有两种设计方法:

  •  毗邻目录模式(adjacencylist model)
  • 预排序遍历树算法(modifiedpreorder tree traversal algorithm)

4.1 基于lft, rgt的无限分类算法

我们来看一个图,下面我们把我们原有的菜单画成下面这样的层次关系:

 

我们把原有的系统菜单画成了一个个的椭圆,最外层的就是我们的菜单,然后在每个椭园的两个端点即left与right,按照从左->右,开始用数字来标号,上面这个图中可以看到最外层这个大椭园的lft(左)为1,它的rgt(右)为24。

那么我们可以用一条标准的SQL,而非什么数据库自带的特有的、特殊的SQL来显示出这个树形菜单,来看下面的SQL:

SELECT

       node.menu_id menuId,

       node.menu_descr menuDescr,

       node.lft,

       node.rgt,

       node.menu_url menuUrl,

       (COUNT(parent.menu_id)-1) menuLevel,

       node.menu_pid pid

FROM t_sys_menu node,

       t_sys_menu parent

WHERE

        node.lftBETWEEN parent.lftAND parent.rgt

        AND node.menu_descr!='菜单'

GROUPBY node.menu_id,node.menu_descr,node.lft,node.rgt,node.menu_url,node.menu_pid

ORDERBY node.lft

来看显示的结果

看看上面这个结果,怎么样?

  • 树形结构也有了(可以用于dtree来显示);
  • 层次level也有了(可以用于ajax的一些tree);
  • 我们用的SQL又是最标准的所有的数据库都能用到的SQL;

尝到甜头了是吧?那我们下面来看如何对这样的基于t, rgt的数据结构来作插入操作?

4.2 如何在现有节点中插入新的子节点

如果现在我们要在“报表查询”这个圆里加入一个菜单,假设我们就叫“周报”,那么再来看这个原有的图发生了什么样的改变,来看:

 

看到么,原有的最外层椭园的rgt+2,原有的报表查询这个园的右边界呢?是不是也加了2啊?而原有的“月报”这个圆的lft加了多少?也是+2!

那么来看“周报”这个圆的lft与rgt关系:

“周报”的lft= “报表查询”这个圆的lft+1

“周报”的rgt=“报表查询”这个圆的l

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇记一次 MySQL 删库的数据恢复 下一篇Java8 函数式编程探秘

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目