1. 程式人生 > 實用技巧 >許可權管理系統 - 1 連線:使用者&角色&模組

許可權管理系統 - 1 連線:使用者&角色&模組

許可權管理系統

作用:對不同使用者的許可權進行限定,管理對應的模組

涉及模組:使用者User、角色Role、模組Module(或許可權Permission)

目錄

0 基本步驟

  • 1 三個模組的基本CRUD

    • 使用者User + 角色Role + 模組Module

      • domian 實體類User 、Role 、Module

      • dao 介面

      • xxxDao.xml

      • service 介面+實現類

      • BaseServlet service靜態成員變數 * 3

      • UserServlet、RoleServlet、ModuleServlet

  • 2 動態載入授權資料(樹形頁面元件)

    • /WEB-INF/pages/子系統/role/list.jsp

      • 授權按鈕 傳遞id
        • /system/role?operation=author&id=${o.id}
    • servlet

      • RoleServlet新增author方法
        • 將樹形的動態資料以json方式放入域
    • author.jsp

      • 定義頁面樹形元件

      • 使用靜態資料確認樹形結構功能是否完備

    • ModuleService + ModuleServiceImpl

      • findAuthorDataByRoleId方法
    • ModuleDao

      • findAuthorDataByRoleId方法
    • ModuleDao.xml

      • findAuthorDataByRoleId對應SQL語句

      • 按照頁面資料結構(JSON)拼寫SQL

  • 3 繫結角色與模組關係

    • WEB-INF\pages\子系統\role\author.jsp

      • 實現許可權分配:選中複選框,授予對應許可權
    • RoleServlet

      • 新增方法updateRoleModule
    • RoleService + RoleServiceImpl

      • updateRoleModule方法
    • RoleDao

      • deleteRoleModule方法

      • saveRoleModule方法

    • RoleDao.xml

      • deleteRoleModule

      • saveRoleModule

  • 4 繫結使用者與角色關係 - 資料回顯

    • \WEB-INF\pages\system\user\list.jsp

      • 角色 按鈕 href
        • 子系統/user?operation=userRoleList&id="+id
    • UserServlet - userRoleList方法

      • 將資料傳遞到 角色 頁面
    • RoleService + RoleServiceImpl - findAllRoleByUserId方法

      • 根據使用者id查詢角色列表
    • RoleDao - findAllRoleByUserId方法

    • RoleDao.xml - 新增對應的查詢

    • /WEB-INF/pages/system/user/role.jsp

      • 新增checked
  • 5 繫結使用者與角色關係 - 修改(許可權資料)

    • user/role.jsp

      • 表單action
        • /system/user?operation=updateRole
    • UserServlet - updateRole方法

    • UserService + UserServiceImpl - updateRole方法

    • UserDao

      • deleteRole

      • updateRole

    • UserDao.xml

      • deleteRole

      • updateRole

1 角色Role + 模組Module :基本CRUD

2 動態載入授權資料(樹形頁面元件)

相當與 許可權資料 回顯

2.1 /WEB-INF/pages/子系統/role/list.jsp

<button type="button" class="btn bg-olive btn-xs" 
        onclick='location.href="${pageContext.request.contextPath}
                 /system/role?operation=author&id=${o.id}"'>授權</button>

2.2 RoleServlet新增author方法

private void author(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        //獲取要授權的角色id
        String roleId = request.getParameter("id");
        //使用id查詢對應的資料(角色id對應的模組資訊)
        Role role = roleService.findById(roleId);
        request.setAttribute("role",role);
        //根據當前的角色id獲取所有的模組資料,並載入關係資料
        List<Map> map = moduleService.findAuthorDataByRoleId(roleId);
        //map轉成json資料
        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(map);
        request.setAttribute("roleModuleJson",json);
        // TODO 資料未查詢
        //跳轉到樹頁面中
        request.getRequestDispatcher("/WEB-INF/pages/system/role/author.jsp")
            .forward(request,response);
    }

2.3 author.jsp 定義頁面樹形元件

<SCRIPT type="text/javascript">
        // 定義頁面對應的樹形元件
        var zTreeObj;
        var setting = {check: {enable: true},data: {simpleData: {enable: true}}};

        var zNodes =${roleModuleJson}
        /*
        [
            {id:1,pId:0,name:'平臺系統管理',checked:false},
            {id:101,pId:1,name:'企業管理',checked:false},
            {id:102,pId:1,name:'部門管理',checked:false},
            {id:103,pId:1,name:'使用者管理',checked:false},
            {id:104,pId:1,name:'角色管理',checked:false},
            {id:105,pId:1,name:'模組管理',checked:false},
            {id:106,pId:1,name:'系統日誌管理',checked:false},
            {id:2,pId:0,name:'題庫管理',checked:false},
            {id:201,pId:2,name:'題目學科管理',checked:false},
            {id:202,pId:2,name:'題目型別管理',checked:false},
            {id:203,pId:2,name:'題目管理',checked:false},
            {id:204,pId:2,name:'題目稽核日誌',checked:false},
            {id:3,pId:0,name:'會員管理',checked:false},
            {id:301,pId:3,name:'會員賬號管理',checked:false},
            {id:302,pId:3,name:'會員答題管理',checked:false}
        ]
        */
        $(document).ready(function(){
            /*
            $.get("${ctx}/system/role?operation=getModuleByRoleId&id=${role.id}",function(data) {
                var json = eval('(' + data + ')');
                initZtree(json);
            });
            */
            zTreeObj = $.fn.zTree.init($("#treeDemo"), setting, zNodes)
            var zTree = $.fn.zTree.getZTreeObj("treeDemo")
            zTree.setting.check.chkboxType = { "Y" : "ps", "N" : "ps" }
            zTreeObj.expandAll(true);//true:展開所有
        });

</SCRIPT>

2.4 ModuleService + ModuleServiceImpl - findAuthorDataByRoleId方法

@Override
    public void updateRoleModule(String roleId, String moduleIds) {
        SqlSession sqlSession = null;
        try{
            //1.獲取SqlSession
            sqlSession = MapperFactory.getSqlSession();
            //2.獲取Dao
            RoleDao roleDao = MapperFactory.getMapper(sqlSession,RoleDao.class);
            //3.呼叫Dao層操作
            //修改role_module
            //3.1現有的關係全部取消掉
            roleDao.deleteRoleModule(roleId);
            //3.2建立新的關係(多個)
            String[] moduleArray = moduleIds.split(",");
            for(String moduleId:moduleArray){
                roleDao.saveRoleModule(roleId,moduleId);
            }
            //4.提交事務
            TransactionUtil.commit(sqlSession);
        }catch (Exception e){
            TransactionUtil.rollback(sqlSession);
            throw new RuntimeException(e);
            //記錄日誌
        }finally {
            try {
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

2.5 ModuleDao - findAuthorDataByRoleId方法

List<Map> findAuthorDataByRoleId(String roleId);

2.6 ModuleDao.xml - 內容名稱與JSON對應

<select id="findAuthorDataByRoleId" parameterType="string" resultType="java.util.Map">
        select
            module_id as id,
            parent_id as pId,
            name as name,
            case
                when module_id in (select module_id from ss_role_module where role_id = #{roleId})
                    then 'true'
                    else 'false'
                end
            as checked
        from
            ss_module
    </select>

3 繫結角色與模組關係

3.1 WEB-INF\pages\子系統\role\author.jsp

實現許可權分配:選中複選框,授予對應許可權

<SCRIPT type="text/javascript">
    //實現許可權分配
    function submitCheckedNodes() {
        //1.獲取所有的勾選許可權節點
        var nodes = zTreeObj.getCheckedNodes(true);//true:被勾選,false:未被勾選
        //2.迴圈nodes,獲取每個節點的id,並將資料加入陣列
        //1,2,3,4,5     1+","+2+","+3.....
        //資料的臨時儲存陣列,為了方便內容連線成為一個由逗號分隔的字串
        var moduleArrays = [];
        for(var i=0;i<nodes.length;i++) {
            moduleArrays.push(nodes[i].id);
        }
        //3.將陣列中的資料使用,連線後,賦值給表單,傳入後臺
        $("#moduleIds").val(moduleArrays.join(','));    //1,2,3,4,5
        $("#icform").submit();
    }
</SCRIPT>
<form id="icform" method="post" action="${ctx}/system/role?operation=updateRoleModule">
    <input type="hidden" name="roleId" value="${role.id}"/>
        <input type="hidden" id="moduleIds" name="moduleIds" value=""/>
            <ul id="treeDemo" class="ztree"></ul>
</form>
<!--工具欄-->
</form>

3.2 RoleServlet - updateRoleModule 方法

private void updateRoleModule(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String roleId = request.getParameter("roleId");
        String moduleIds = request.getParameter("moduleIds");
        roleService.updateRoleModule(roleId,moduleIds);
        //跳轉回到頁面list
        response.sendRedirect(request.getContextPath()+"/system/role?operation=list");
    }

3.3 RoleService + RoleServiceImpl - updateRoleModule方法

/**
     * 建立角色與模組之間的關聯
     * @param roleId 角色id
     * @param moduleIds 模組id(多個)
     */
void updateRoleModule(String roleId, String moduleIds);




@Override
public void updateRoleModule(String roleId, String moduleIds) {
    SqlSession sqlSession = null;
    try{
        //1.獲取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.獲取Dao
        RoleDao roleDao = MapperFactory.getMapper(sqlSession,RoleDao.class);
        //3.呼叫Dao層操作
        //修改role_module
        //3.1現有的關係全部取消掉
        roleDao.deleteRoleModule(roleId);
        //3.2建立新的關係(多個)
        String[] moduleArray = moduleIds.split(",");
        for(String moduleId:moduleArray){
            roleDao.saveRoleModule(roleId,moduleId);
        }
        //4.提交事務
        TransactionUtil.commit(sqlSession);
    }catch (Exception e){
        TransactionUtil.rollback(sqlSession);
        throw new RuntimeException(e);
        //記錄日誌
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3.4 在RoleDao中新增方法deleteRoleModulesaveRoleModule

    void deleteRoleModule(String roleId);

    void saveRoleModule(@Param("roleId") String roleId, @Param("moduleId") String moduleId);

3.5 在對應的對映配置檔案中新增對應的操作

<!--配置根據roleId刪除關係表資料-->
<delete id="deleteRoleModule" parameterType="java.lang.String">
    delete from ss_role_module
    where role_id = #{roleId,jdbcType=VARCHAR}
</delete>

<!--配置全欄位插入,當某個欄位沒有值時,插入null-->
<insert id="saveRoleModule" parameterType="map">
    insert into ss_role_module (role_id, module_id)
    values (#{roleId,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR})
</insert>

4 繫結使用者與角色關係 - 資料(許可權)回顯

4.1 \WEB-INF\pages\子系統\user\list.jsp

  • 角色 按鈕 href
    • 子系統/user?operation=userRoleList&id="+id

4.2 UserServlet - userRoleList方法 - 將資料傳遞到 角色 頁面

private void userRoleList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userId = request.getParameter("id");
        User user = userService.findById(userId);
        //將資料載入到指定區域,供頁面獲取
        request.setAttribute("user",user);
        //獲取所有的角色列表
        List<Role> all = roleService.findAllRoleByUserId(userId);
        request.setAttribute("roleList",all);

        //跳轉頁面
        request.getRequestDispatcher("/WEB-INF/pages/system/user/role.jsp")
            .forward(request,response);
    }

4.3 RoleService + RoleServiceImpl - findAllRoleByUserId方法 - 根據使用者id查詢角色列表

List<Role> findAllRoleByUserId(String userId);



@Override
public List<Role> findAllRoleByUserId(String userId) {
    SqlSession sqlSession = null;
    try{
        //1.獲取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.獲取Dao
        RoleDao roleDao = MapperFactory.getMapper(sqlSession,RoleDao.class);
        //3.呼叫Dao層操作
        return roleDao.findAllRoleByUserId(userId);
    }catch (Exception e){
        throw new RuntimeException(e);
        //記錄日誌
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

4.4 在dao介面RoleDao中新增查詢方法findAllRoleByUserId

List<Role> findAllRoleByUserId(String userId);

4.5 在對映配置檔案RoleDao.xml中新增對應的查詢

    <!--配置根據ID查詢-->
<select id="findAllRoleByUserId" parameterType="java.lang.String" resultMap="BaseResultMap">
	SELECT
		role_id,
		NAME,
		CASE
			WHEN role_id IN (SELECT role_id FROM ss_role_user WHERE user_id = #{'userId'})
			THEN 'checked'
			ELSE ''
		END
		AS remark
	FROM
		ss_role
</select>

4.6 修改頁面/WEB-INF/pages/system/user/role.jsp,新增checked

<form id="urform" action="${ctx}/system/user?operation=updateRole" method="post">
    <input type="hidden" name="userId" value="${user.id}"/>
    <div class="textbox" id="centerTextbox">
        <div style="text-align:left">
            <c:forEach items="${roleList}" var="role" varStatus="vs">
                <span style="padding:3px;margin-right:30px;width: 160px;display: inline-block">
        <input type="checkbox" name="roleIds" value="${role.id}" ${role.remark}/>${role.name}
                </span>
            </c:forEach>
        </div>
    </div>
</form>

5 繫結使用者與角色關係 - 修改(許可權)資料

現在要真正去繫結使用者與角色的關係,前臺頁面提交表單後會將使用者的id和選擇的角色的id傳遞到後臺servlet

5.1 在UserServlet中新增新的方法

private void updateRole(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String userId = request.getParameter("userId");
    String[] roleIds = request.getParameterValues("roleIds");
    userService.updateRole(userId,roleIds);
    //跳轉回到頁面list
    response.sendRedirect(request.getContextPath()+"/system/user?operation=list");
}

5.2 在UserService介面中新增一個新的方法updateRole

void updateRole(String userId, String[] roleIds);

5.3 在對應的實現類 UserServiceImpl 中去實現

@Override
public void updateRole(String userId, String[] roleIds) {
    SqlSession sqlSession = null;
    try{
        //1.獲取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.獲取Dao
        UserDao userDao = MapperFactory.getMapper(sqlSession,UserDao.class);
        userDao.deleteRole(userId);
        for(String roleId : roleIds){
            userDao.updateRole(userId,roleId);
        }
        //4.提交事務
        TransactionUtil.commit(sqlSession);
    }catch (Exception e){
        TransactionUtil.rollback(sqlSession);
        throw new RuntimeException(e);
        //記錄日誌
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

5.4 在dao介面UserDao中新增兩個方法

void deleteRole(String userId);

void updateRole(@Param("userId") String userId, @Param("roleId")String roleId);

5.5 在該介面對應的對映配置檔案中新增兩個操作

<!--配置根據roleId刪除關係表資料-->
<delete id="deleteRole" parameterType="java.lang.String">
    delete from ss_role_user
    where user_id = #{userId,jdbcType=VARCHAR}
</delete>

<!--配置全欄位插入,當某個欄位沒有值時,插入null-->
<insert id="updateRole" parameterType="map">
    insert into ss_role_user (role_id, user_id)
    values (#{roleId,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR})
</insert>