首先說一下權限保存的問題,一個系統中最多有多少權限呢?一個大的系統中可能有成百上千個權限須要管理。怎麼保存這麼多的權限?首先,咱們使用一個數字中的一位保存一種權限,那麼若是如今有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 }