首先说一下权限保存的问题,一个系统中最多有多少权限呢?一个大的系统中可能有成百上千个权限须要管理。怎么保存这么多的权限?首先,咱们使用一个数字中的一位保存一种权限,那么若是如今有3600种权限须要保存,咱们就须要一个3600位的数字来保存该权限,首先咱们若是不考虑大数的话其它数据类型是没有办法保存这么长的数字的。因此咱们为了可以保存这么多的权限,就引入了一个“权限组”的概念,这个权限组只是一个标识权限的容器,咱们使用long类型的数字来保存63个权限,假设咱们使用long类型的数字来保存权限组,那么很轻松的就能保存住几乎近天文数字个权限。数组
若是有一个添加新权限的界面,该怎么添加权限呢?首先,能够给出权限名称和权限指向的url地址以及权限描述,可是不能提供权限位和权限码的编辑,权限位和权限码的计算须要系统自动计算出来。this
保存权限的流程图以下:url
咱们给给权限一个“public”的属性,咱们使用该属性标识该资源是否须要有相关权限才可以访问,若是该属性为true,表示该资源是公共资源,不须要任何权限就能访问。每个权限都惟一的标志了一个url,所谓的是否有权限实际上就是是否有权限访问该url。spa
使用|运算,公式:rightSum[right.pos]=right.pos|rightSum[right.pos];code
角色直接和用户实体挂钩,用户实体再也不直接和权限实体关联,而是经过角色实体和权限关联。对象
一个用户能够有多个角色,一个角色可以属于多个用户;一个角色可以有多个权限,一个权限可以属于多个角色,因此用户和角色之间是多对多的关系,角色和权限之间也是多对多的关系。ER图以下图所示:blog
在权限管理模块,权限实体是不可再分割的最小实体。资源
(1)首先权限实体须要有一个权限名rightName,名字只是为了方便理解权限的做用;get
(2)url,该url其实是ActionName,若是带有get类型的参数必须将参数拿掉,好比LoginAction_login.action?username=zhangsan&password=lisi,将其处理以后就变成了LoginAction_login.action权限控制
(3)权限码rightCodes,一个表中rightCodes并非惟一的,它只在对应的权限组中惟一,它使用long类型的数据类型进行保存,形式如1,2,4,8,16,....261
为了不临界值的麻烦,权限码最大为261
(4)权限位,rightPos,也叫作权限组,这里使用一个整数保存便可,用于标识权限位所在的组,虽然只是起到标识做用,可是实际上倒是权限码的容器。
(5)是不是公共资源标识common
(6)权限描述,没什么说的,加上便可。
public class Right implements Serializable{ private static final long serialVersionUID = 7690933329658416384L; private Integer rightId; //权限惟一标识id private String rightName="未命名"; //权限名称 private String rightUrl; //将要过滤的URL private String rightDesc="默认描述"; //权限描述 private Long rightCodes; //权限码 private int rightPos; //权限位,实际上就是权限组的类别 private Boolean common=true; //标识是否为公共资源的标识字段 ...... }
权限实体和角色实体之间是多对多的关系,需不须要在权限映射文件中创建关联关系?咱们从不会根据权限获取该权限属于哪一种角色,因此不要创建权限到角色的关联关系,无用的关联只会给系统带来隐藏的负担。
角色实体须要创建到权限实体的多对多关联关系,可是不该该创建到User实体的关联关系,缘由同上。另外增长一个roleValue,使用该值标识是否有超级管理员权限。若是该标识为“-1”,那么将会覆盖其他的全部权限,称为最高权限,能够访问一切资源。
1 public class Role implements Serializable{ 2 private static final long serialVersionUID = -1585936238538771703L; 3 private Integer roleId; //Role对象标识id 4 private String roleName="未命名角色"; //Role对象名称 5 private String roleValue="0"; //Role对象值,只是在断定是超级管理员的时候有用 6 private String roleDesc="默认角色描述"; //Role对象描述 7 //创建Role到Right之间的单向多多对关系 8 private Set<Right>rights=new HashSet<Right>();//这里必须初始化一下,不然在重用保存/修改页的时候会报错 9 ...... 10 }
只须要增长一个Set集合并创建到角色实体的多对多关系映射便可。
流程:导航栏上单击“权限管理”超连接跳转到权限管理界面->在权限管理界面上单击“增长权限”超连接->跳转到增长权限页面上->填写表单成功以后,单击提交,交给RightAction_saveOrUpdateRightPage.action处理,期间调用Service方法保存权限->返回权限管理界面。
固然,最核心的仍是Service中的方法:
1 //添加新权限的过程 2 public void saveOrUpateRight(Right right){ 3 Integer rightPos; 4 Long rightCodes; 5 //首先是针对新建立的状况 6 if(right.getRightId()==null){ 7 //第一步查找最大权限位和最大权限码 8 String hql="select max(r.rightPos),max(r.rightCodes) from Right r where r.rightPos=(select max(rr.rightPos) from Right rr)"; 9 Object[] arr=(Object[]) this.rightDao.findUniqueResult(hql); 10 Integer topRightPos=(Integer) arr[0]; 11 Long topRightCodes=(Long) arr[1]; 12 if(topRightPos==null){ 13 rightPos=0; 14 rightCodes=1L; 15 }else{ 16 if(topRightCodes>=(1L<<60)){ 17 rightPos=topRightPos+1; 18 rightCodes=1L; 19 }else{ 20 rightPos=topRightPos; 21 rightCodes=topRightCodes<<1; 22 } 23 } 24 right.setRightPos(rightPos); 25 right.setRightCodes(rightCodes); 26 } 27 this.rightDao.saveOrUpdateEntity(right); 28 }