納稅服務系統【角色模塊、包含權限】

需求分析

咱們直接來看看原型圖,看看需求是怎麼樣的:java

這裏寫圖片描述

這裏寫圖片描述

咱們看到上圖,就會發現角色模塊主要仍是CRUD,惟一不一樣的就是它再也不是單獨的實體關係。角色與權限是存在關係的。sql

以前在Servlet+JSP+JavaBean的時候其實咱們已經作過了用戶-角色-權限之間的操做【權限管理系統】http://blog.csdn.net/hon_3y/article/details/61926175數據庫

角色與權限應該是多對多的關係的。數組

  • 一個角色擁有多個權限
  • 一個權限能夠被多個角色使用

進一步分析

如今個人權限只有5個,有必要使用數據庫表嗎???沒啥必要吧。權限基本就固定下來了。那多對多的關係怎麼維護???以前咱們使用數據庫表就很好作了呀。設計兩個實體,使用中間表來描述它們之間的關係就作出來了。服務器

那如今怎麼作呢??一個角色對應多個權限markdown

這裏寫圖片描述

咱們在數據庫中的表就能夠這樣設計:即便沒有權限表,可是我使用了中間表維護了它們的數據。同樣能夠作到一個角色對應多個權限這樣的功能。app

這裏寫圖片描述

設計實體類

設計權限常量類

咱們權限是不須要表的,所以咱們把各個權限寫下來,使用一個集合裝載着就好了。固然啦,他們都應該被設計成常量。咱們保存在core模塊中【被整個系統用到的】ide

package zhongfucheng.core.constant;

import java.util.HashMap;
import java.util.Map;

/** * Created by ozc on 2017/5/26. */
public class Constant {

    /*----------------------系統權限集合--------------------------*/
    public static String PRIVILEGE_XZGL = "xzgl";
    public static String PRIVILEGE_HQFW = "hqfw";
    public static String PRIVILEGE_ZXXX = "zxxx";
    public static String PRIVILEGE_NSFW = "nsfw";
    public static String PRIVILEGE_SPACE = "spaces";


    //使用一個Map集合來裝載着這些權限。
    public static Map<String, String> PRIVILEGE_MAP;
    static {
        PRIVILEGE_MAP = new HashMap<String, String>();
        PRIVILEGE_MAP.put(PRIVILEGE_XZGL, "行政管理");
        PRIVILEGE_MAP.put(PRIVILEGE_HQFW, "後勤服務");
        PRIVILEGE_MAP.put(PRIVILEGE_ZXXX, "在線學習");
        PRIVILEGE_MAP.put(PRIVILEGE_NSFW, "納稅服務");
        PRIVILEGE_MAP.put(PRIVILEGE_SPACE, "個人空間");
    }
}

設計角色類

咱們的角色類應該使用一個Set集合來保存對應的權限數據的,那麼Set集合的元素類型是什麼呢???想一下…學習

以前咱們在用的時候,若是有權限表。咱們在角色中Set集合的元素應該是Privilege類。可是如今是沒有權限表的。咱們怎麼經過角色來獲取全部的權限呢??ui

再看回這樣ER圖:咱們在角色Set集合中保存着角色與關係表這個不就好了嗎!!!

這裏寫圖片描述

因而咱們這樣設計:

package zhongfucheng.role.entity;

import java.io.Serializable;
import java.util.Set;

/** * Created by ozc on 2017/5/26. */
public class Role implements Serializable {
    private String roleId;
    private String state;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private Set<RolePrivilege> rolePrivilegeSet;

    public static String USER_STATE_VALID = "1";//有效,
    public static String USER_STATE_INVALID = "0";//無效


    public String getRoleId() {
        return roleId;
    }

    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Set<RolePrivilege> getRolePrivilegeSet() {
        return rolePrivilegeSet;
    }

    public void setRolePrivilegeSet(Set<RolePrivilege> rolePrivilegeSet) {
        this.rolePrivilegeSet = rolePrivilegeSet;
    }

    public static String getUserStateValid() {
        return USER_STATE_VALID;
    }

    public static void setUserStateValid(String userStateValid) {
        USER_STATE_VALID = userStateValid;
    }

    public static String getUserStateInvalid() {
        return USER_STATE_INVALID;
    }

    public static void setUserStateInvalid(String userStateInvalid) {
        USER_STATE_INVALID = userStateInvalid;
    }
}

設計角色與權限關係類

角色與權限關係類只有兩個屬性:角色的id和權限的code….這兩個是外鍵列。一張表中必定是要有主鍵列的,因而咱們採用的是複合主鍵的方式。

對於複合主鍵,它是要讓該類維護一個複合主鍵類的:

將主鍵所對應屬性提取出一個類(稱之爲主鍵類),而且主鍵類須要實現Serializable接口,重寫hashCode和equals()方法

public class RolePrivilege implements Serializable { private CompositeKey compositeKey; public CompositeKey getCompositeKey() { return compositeKey; } public void setCompositeKey(CompositeKey compositeKey) { this.compositeKey = compositeKey; } } 

複合主鍵類

按照ER圖,咱們複合主鍵就兩個屬性:role_id和code。。

可是呢,咱們想一下需求:在獲取角色全部權限的時候,Set集合裝載着角色與權限的關係,而角色與權限的關係裝載着role_id和code。而頗有可能:在我查看用戶所擁有角色的時候,想要獲得角色的名稱。這裏僅僅查出來的是角色id,還要經過角色id獲得角色的名稱…這樣就有點麻煩了。因而咱們寫成Role對象。到時候就能直接獲取了。

package zhongfucheng.role.entity;

import java.io.Serializable;

/** * Created by ozc on 2017/5/26. */
public class CompositeKey implements Serializable {


    private String code;
    private Role role;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CompositeKey that = (CompositeKey) o;

        if (code != null ? !code.equals(that.code) : that.code != null) return false;
        return role != null ? role.equals(that.role) : that.role == null;

    }

    @Override
    public int hashCode() {
        int result = code != null ? code.hashCode() : 0;
        result = 31 * result + (role != null ? role.hashCode() : 0);
        return result;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }
}

角色映射表配置

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="zhongfucheng.role.entity.Role" table="role">
        <id name="roleId" type="java.lang.String">
            <column name="roleId" length="32" />
            <generator class="uuid.hex" />
        </id>
        <property name="state" type="java.lang.String">
            <column name="state" length="1" />
        </property>
        <property name="name" type="java.lang.String">
            <column name="name" length="20" not-null="true" />
        </property>
        <!-- 一方維護多方的數據,inverse設置爲true,沒有控制權限 設置級聯保存更新,在保存角色的時候,將權限也保存起來了。 不設置懶加載,直接獲取到權限的數據 -->
        <set name="rolePrivilegeSet" lazy="false" inverse="true" cascade="save-update" >
            <key>
                <column name="role_id"></column>
            </key>
            <one-to-many class="zhongfucheng.role.entity.RolePrivilege" ></one-to-many>
        </set>
    </class>

</hibernate-mapping>

角色與權限映射表配置

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="zhongfucheng.role.entity.RolePrivilege" table="role_privilege">
        <composite-id name="id" class="zhongfucheng.role.entity.CompositeKey">
            <key-many-to-one name="role" class="zhongfucheng.role.entity.Role" lazy="false">
                <column name="role_id "></column>
            </key-many-to-one>
            <key-property name="code" type="java.lang.String">
                <column name="code"></column>
            </key-property>
        </composite-id>
    </class>
</hibernate-mapping>

Role模塊的CRUD

沒啥好說的,咱們在User模塊中已經寫過了。咱們能夠直接複製過來,而後將不要的功能去掉。

  • 將所有的User改爲Role
  • 將所有的user改爲role

dao–>service—>action這樣改完,就有了Role模塊的CRUD了。

最後:

  • Spring總配置文件中加載role模塊實體映射文件,加載role模塊的bean文件。
  • Struts總配置文件中加載role模塊的Struts配置文件。

添加模塊

把權限的集合帶過去給JSP頁面顯示出來,JSP使用Struts的checkbox進行遍歷【很好用】

public String addUI() {

        ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
        return "addUI";
    }

使用checkbox標籤遍歷

<tr>
            <td class="tdBg" width="200px">角色權限:</td>
            <td>

                <%-- checkboxlist:自動把Map集合遍歷出來,生成對應的key value,Map集合的key做爲checkbox的key,value做爲checkbox的value list:集合 name:把數據帶過去給服務器 --%>
                    <s:checkboxlist list="#privilegeMap" name="privilegeIds"/>
            </td>
        </tr>

這裏寫圖片描述

這裏寫圖片描述


/************數據自動封裝權限的id*************************/
    private String[] privilegeIds;

    public String[] getPrivilegeIds() {
        return privilegeIds;
    }

    public void setPrivilegeIds(String[] privilegeIds) {
        this.privilegeIds = privilegeIds;
    }

處理角色與權限的關係。在配置中使用了級聯保存,所以能夠直接保存數據

public String add() throws IOException {
        if (role != null) {
            //處理角色與權限的關係
            if (privilegeIds != null) {
                HashSet<RolePrivilege> set = new HashSet<>();
                //獲得每個權限的值--->entity給出對應的構造方法...
                for (int i = 0; i < privilegeIds.length; i++) {
                    set.add(new RolePrivilege(new CompositeKey(role, privilegeIds[i])));
                }
                role.setRolePrivilegeSet(set);
            }
            roleServiceImpl.save(role);
            //跳轉到列表顯示頁面
            return "list";
        }
        return null;
    }

這裏寫圖片描述

這裏寫圖片描述

顯示模塊

在顯示模塊中,主要是顯示角色的權限中有點繞…..

角色的權限用set集合保存起來,set集合元素是角色與權限的關係,角色與權限是一個類,該類保存着主鍵類,主鍵類存儲的是角色和權限code。

咱們的目的是:獲得角色含有的權限。而目前爲止,咱們最多隻能獲得每一個權限code值:

這裏寫圖片描述

而咱們想要顯示的是權限的名稱,因而咱們得把權限集合傳過去,根據code獲得權限的名稱

public String listUI()   {

        roleList = roleServiceImpl.findObjects();

        ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
        return "listUI";
    }

JSP頁面取值:注意懶加載的問題,設定不要懶加載。否則會出現: java.io.IOException: Stream closed

<s:iterator value="rolePrivilegeSet">
       <s:property value="#privilegeMap[compositeKey.code]"/>
    </s:iterator>

這裏寫圖片描述


單個刪除功能

跳轉到Action中處理,把id傳遞過去…

function doDelete(id) {
        document.forms[0].action = "${basePath}role/role_delete.action?role.roleId="+id;
        document.forms[0].submit();
    }

判斷是否爲空,不爲空就刪除。返回到列表頁面

2017/5/31 12:59:27     //刪除
    public String delete() {
        if (role != null && role.getRoleId() != null) {
            roleServiceImpl.delete(role.getRoleId());
        }
        return "list";
    }

修改模塊

數據回顯頁面,主要就是角色的權限那裏怎麼回顯。咱們把全部的權限帶過去,用字符串數組記錄當前角色有什麼權限

//獲得全部的權限
        ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);

        //外邊已經傳了id過來了,咱們要找到id對應的Role
        if (role != null && role.getRoleId() != null) {
            //直接獲取出來,後面JSP會根據Role有getter就能讀取對應的信息!
            role = roleServiceImpl.findObjectById(role.getRoleId());

            //獲得角色全部的權限,把它封裝到privilegeIds字符數組中。
            //處理權限回顯
            if (role.getRolePrivilegeSet() != null) {
                privilegeIds = new String[role.getRolePrivilegeSet().size()];

                int i = 0;
                for (RolePrivilege rp : role.getRolePrivilegeSet()) {
                    privilegeIds[i++] = rp.getCompositeKey().getCode();
                }
            }

        }
        return "editUI";

在JSP頁面,使用checkboxlist標籤進行遍歷。

<s:checkboxlist list="#privilegeMap" name="privilegeIds" ></s:checkboxlist>

這裏寫圖片描述


獲得JSP傳遞過來的ids,封裝成一個set集合。將set集合賦值給role對象。

public String edit() throws IOException {
        //Struts2會自動把JSP帶過來的數據封裝到Role對象上
        if (role.getRoleId() != null && role != null) {

            Set<RolePrivilege> set = new HashSet<>();
            //獲得修改的權限id,封裝到set集合中。
            for (String privilegeId : privilegeIds) {
                set.add(new RolePrivilege(new CompositeKey(role, privilegeId)));
            }
            role.setRolePrivilegeSet(set);

            roleServiceImpl.update(role);
        }
        return "list";
    }

僅僅是使用update(role)方法是不夠的,所以Hibernate在更新操做的時候,會先把數據查詢出來。當咱們更改角色權限的時候,它會將咱們已有的權限保留下來,若是有新的就繼續添加。它不會把咱們沒勾選的剔除的

所以,咱們須要在更新的以前,把當前角色全部的權限給刪了

//在修改以前,把角色的全部權限給刪除了。否則會遺留以前的權限下來。
        roleDaoImpl.deleteRolePrivilegeByRoleId(role.getRoleId());
/*** * 根據角色id刪除全部的權限 * */
    @Override
    public void deleteRolePrivilegeByRoleId(String roleId) {

        String sql = "DELETE FROM RolePrivilege WHERE compositeKey.role.roleId= ?";

        Query query = getSession().createQuery(sql);
        query.setParameter(0, roleId);
        query.executeUpdate();
    }

效果:

這裏寫圖片描述

相關文章
相關標籤/搜索