权限管理系统实现思路(SpringCloud+Thymeleaf)(二)

权限分配

   下面主要来说说Thymeleaf模板使用和权限分配的实现思路。
   先看效果图:
在这里插入图片描述
在这里插入图片描述
   实现该功能的思路是:传往前端的数据为Map,该Map以columnName(权限分栏名)为key,以该分栏下的所有权限为value。因为要回显权限是否选中,这里为权限实体类(Perm)定义了一个属性checkedFlag(默认为false)

private boolean checkedFlag = false;

   角色管理功能中,首先将得到columnList,遍历columnList,然后以columnId查询属于该分栏下的所有权限得到permList,根据roleId查询权限映射表(permmapping)得到mappingList,如果某个permId既在permList中又在mappingList中,说明该权限为选中状态。

@GetMapping("/assignPerm")
    public ModelAndView assignPerm(@RequestParam int roleId,@RequestParam String roleName){
        //权限分栏集合
        List<Column> columnList = columnService.findColumnList();
        Role role = roleService.findRoleById(roleId);
        ResultEntity resultEntity = new ResultEntity();
        //获取当前的方法名
        String methodName = new Exception().getStackTrace()[0].getMethodName();
        resultEntity.setResultCode("200");
        resultEntity.setOperMessage(CLASS_NAME+"---"+methodName);
        resultEntity.setResultObject(role);
        resultEntity.setResultList(columnList);
        HashMap<String, List<?>> map = new HashMap<>();
        List<PermMapping> mappingList = permMappingService.findMappingListByRole(roleId);
        for(Column column:columnList){
            //获取该分栏下的所有权限(permList)
            List<Perm> permList= permService.findPermByColumn(column.getColumnId());

            //遍历permList
            for(Perm perm:permList){
                for(PermMapping permMapping:mappingList){
                    if(permMapping.getPermId()==perm.getPermId()){
                        //当映射关系集合mappingList中对象的permId与permList中对象permId相同时,将permChecked的状态设置为true
                        perm.setCheckedFlag(true);
                    }
                }
            }

            //以权限所属的columnName(分栏名)为key,以该columnName下的permList(权限勾选对象集合)为value
            map.put(column.getColumnName(),permList);
        }
        resultEntity.setResultListMap(map);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("resultEntity",resultEntity);
        modelAndView.setViewName("/roleOper");
        return modelAndView;
    }

   看这部分对应的前端:

<div class="step clearfix" th:each="column:${resultEntity.resultList}">
                <div class="classify">
                    <div class="checkbox_item">
                        <input type="checkbox" name="checkGroup" th:name="'checkGroup_'+${column.columnId}" value="checkbox" th:value="${column.columnName}" class="ui-checkbox" id="user" th:id="${column.columnName}">
                        <label for="user" th:for="${column.columnName}" class="ui-label blod" th:text="${column.columnName}">文章管理</label>
                    </div>
                </div>
                <div class="qx_item">
                    <div class="checkbox_item" th:each="perm:${resultEntity.resultListMap['__${column.columnName}__']}">
                        <input type="checkbox" value="ckeck_item" id="ckeck_item" th:checked="${perm.checkedFlag}" name="ckeck_item" th:name="'checkItem_'+${perm.columnId}" th:value="${perm.permId}" th:id="${perm.permId}" class="ui-checkbox" date="cms_manage" th:title="${perm.checkedFlag}">
                        <label for="ckeck_item" th:for="${perm.permId}" th:text="${perm.permName}" class="ui-label">文章分类管理</label>
                    </div>
                </div>
            </div>

   从上面的代码中可以看出,权限分栏下的所有checkbox的值为该权限的id。Thymeleaf能够接收Map类型的值,Map的取值方式为
map['key'],如果key是变量的话,取值方式为map['__${variable}__']。
   其中,权限分栏的checkbox的name属性是以checkGroup为前缀,以columnId为后缀,以下划线分隔。权限的checkbox的name属性是以checkItem为前缀,以它所属的columnId为后缀,以下划线分隔。全选的checkbox的name属性的值为checkAll

th:name="'checkGroup_'+${column.columnId}"
th:name="'checkItem_'+${perm.columnId}"
name="checkAll"

下面就是js中checkbox全选和反选的逻辑:

var totalLength = $(":checkbox[name!='checkAll']").length;
        var checkedLength = 0;


        $(":checkbox[name^='checkGroup']").each(
            function(){
                var perffix = 'checkItem';
                var suffix = $(this).attr('name').split('_')[1];
                var itemLength = $(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']").length;
                var itemCheckedLength = $(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']:checked").length;

                if(itemCheckedLength == itemLength){
                    if(itemCheckedLength > 0){
                        this.checked = true;
                        checkedLength += itemCheckedLength+1;
                        $(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']").each(
                            function(){
                                this.checked = true;
                            }
                        );
                    }

                }else{
                    checkedLength += itemCheckedLength;
                }

                if(checkedLength==totalLength){
                    $(":checkbox[name='checkAll']").attr("checked",true);
                }
            }
        );

        $(":checkbox[name^='checkGroup']").click(
            function(){
                var perffix = 'checkItem';
                var suffix = $(this).attr('name').split('_')[1];

                var flag = this.checked;
                $(":checkbox[name^='"+perffix+"'][name$='"+suffix+"']").each(
                    function(){
                        this.checked = flag;
                    }
                );

            }
        );

        $(":checkbox[name^='checkItem']").click(function(){
            var suffix = $(this).attr('name').split('_')[1];
            var itemLength = $(":checkbox[name^='checkItem'][name$='"+suffix+"']").length;
            var itemCheckedLength = $(":checkbox[name^='checkItem'][name$='"+suffix+"']:checked").length;
            if(itemCheckedLength == itemLength){
                $(":checkbox[name^='checkGroup'][name$='"+suffix+"']").each(
                    function () {
                        this.checked = true;
                    }
                );
            }else{
                $(":checkbox[name^='checkGroup'][name$='"+suffix+"']").each(
                    function () {
                        this.checked = false;
                    }
                );
            }
        });


        $(":checkbox[name!='checkAll']").click(function () {
            var checkedLength = $(":checkbox[name!='checkAll']:checked").length;
            if(checkedLength == totalLength){
                $(":checkbox[name='checkAll']").each(
                    function () {
                        this.checked = true;
                    }
                );
            }else {
                $(":checkbox[name='checkAll']").each(
                    function () {
                        this.checked = false;
                    }
                );
            }
        });

        /*全选*/
        $(":checkbox[name^='checkAll']").click(
            function () {
                var flag = this.checked;
                $(":checkbox").each(
                    function () {
                        this.checked = flag;
                    }
                )
            }

        );
        var powerIdArray = new Array();
        $("#submitBtn").click(
            function () {
                var roleId = $("#roleId").val().trim();
                var roleName = $("#roleName").val().trim();
                var roleInfo = $("#roleInfo").val().trim();
                $(":checkbox[name^='checkItem']:checked").each(
                    function () {
                        powerIdArray.push($(this).val());
                        console.info("powerIdArray: "+$(this).val());

                    }
                );

                $.ajax({
                    url: [[@{/powerManage/assignPower}]],
                    type: 'post',
                    dataType: 'json',
                    contentType: 'application/json',
                    data: JSON.stringify({primaryMappingId:roleId,formMappingIdArray : powerIdArray,primaryMappingName : roleName,primaryMappingInfo : roleInfo}),
                    async: true,
                    success: function(data){
                    if(data != null){
                        alert(data.msg);
                        if(data.success == true){
                            window.location.reload();
                        }else{
                            $(".assign_box").hide();
                        }

                    }

                }
            });
            });

   如果某个权限被选中,就将该权限Id加入permIdArray(权限数组)

var permIdArray = new Array();
            $("#submitBtn").click(
                function () {
                    var roleId = $("#roleId").val().trim();
                    var roleName = $("#roleName").val().trim();
                    var roleInfo = $("#roleInfo").val().trim();
                    var creatorName = 'admin';
                    console.info("date: "+getNowFormatDate());
                    console.info("roleId: "+roleId);
                    $(":checkbox[name^='checkItem']:checked").each(
                        function () {
                            permIdArray.push($(this).val());
                            console.info("permIdArray: "+$(this).val());

                        }
                    );

   为方便描述映射关系,这里定义了一个MappingEntity(映射实体类)

public class MappingEntity {

    private int primeMapId;//主映射(一对多的一方)
    private int[] minorMapIdArray;//从映射(一对多的多方)
    private String primeMapName;
    private String primeMapInfo;
    private String creatorName;
    private Date createTime;


    public int getPrimeMapId() {
        return primeMapId;
    }

    public void setPrimeMapId(int primeMapId) {
        this.primeMapId = primeMapId;
    }

    public int[] getMinorMapIdArray() {
        return minorMapIdArray;
    }

    public void setMinorMapIdArray(int[] minorMapIdArray) {
        this.minorMapIdArray = minorMapIdArray;
    }

    public String getPrimeMapName() {
        return primeMapName;
    }

    public void setPrimeMapName(String primeMapName) {
        this.primeMapName = primeMapName;
    }

    public String getPrimeMapInfo() {
        return primeMapInfo;
    }

    public void setPrimeMapInfo(String primeMapInfo) {
        this.primeMapInfo = primeMapInfo;
    }

    public String getCreatorName() {
        return creatorName;
    }

    public void setCreatorName(String creatorName) {
        this.creatorName = creatorName;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

勾选中后提交的请求

$.ajax({
                        url: [[@{/admin/assignPerm.asy}]],
                        type: 'post',
                        dataType: 'json',
                        contentType: 'application/json',
                        data: JSON.stringify({primeMapId:roleId,minorMapIdArray : permIdArray,primeMapName : roleName,primeMapInfo : roleInfo,creatorName : creatorName}),
                        async: true,
                        success: function(data){
                            if(data != null){
                                alert(data.hintMsg);
                                if(data.operFlag == true){
                                    window.location.reload();
                                }else{
                                    $(".role_box").hide();
                                }

                        }

                        }
                    });
                });

   在分配权限的实现过程中,涉及到多次分配权限的问题。首先看看映射表是否存在该映射,如果不存在,说明是第一次分配权限,直接插入即可;如果存在,说明是不是第一次分配权限,要获取上一次权限Id的list,比较前端传过来的数组,将多余的删除,缺少的插入。通过ArrayCompare这个工具来实现

public class ArrayCompare {


    /*第一个数组独有的部分*/
    public static List<Integer> findOwnPart(int[] compareArray,int[] referArray){

       /* int[] array1 = listToArray(list);*/

        List<Integer> fristOwnList=new ArrayList<>();

        for (int compare:compareArray) {
            boolean tag = true;
            for(int refer:referArray){
                if(compare==refer){
                    tag = false;
                    break;
                }
            }
            if(tag){
                fristOwnList.add(compare);
            }
        }


        return fristOwnList;
    }

}

   权限分配的代码逻辑

 @PostMapping("/assignPerm.asy")
    public void addPermMapping(@RequestBody MappingEntity mappingEntity, HttpServletResponse resp) throws Exception{

        //时间格式
        Date date=new Date();
        Timestamp timeStamp = new Timestamp(date.getTime());

        System.out.println(timeStamp.toString());
        JSONObject jsonObject = new JSONObject();
        String hintMsg = null;
        boolean operFlag = false;

        //查找之前是否存在映射关系
        List<Integer> permIdList = permMappingService.permIdList(mappingEntity.getPrimeMapId());


        int[] minorMapIdArray = mappingEntity.getMinorMapIdArray();
        if(minorMapIdArray == null){
            hintMsg = "前端传递的数据为空!!!";
        }else{
            if(permIdList.size()==0){
                //将role-perm映射关系插入permmapping表
                List<PermMapping> permMappingList = new ArrayList<>();

                for(int i=0;i<minorMapIdArray.length;i++){
                    //创建PermMapping对象,存放 role-perm 的映射信息
                    PermMapping permMapping = new PermMapping();
                    permMapping.setRoleId(mappingEntity.getPrimeMapId());
                    permMapping.setPermId(minorMapIdArray[i]);
                    permMapping.setCreatorName(mappingEntity.getCreatorName());
                    permMapping.setCreateTime(timeStamp);

                    //将role-perm 的映射信息存入permMappingList
                    permMappingList.add(permMapping);
                }
                permMappingService.addPermMappingList(permMappingList);

                hintMsg = "插入数据成功!!!";
                operFlag = true;
            }else{

                 int[] oldArray = new int[permIdList .size()];
                    for (int i=0;i<permIdList .size();i++) {
                        oldArray[i] = permIdList .get(i).getPermId();
                    }
                    //需要删除的部分
                    List<Integer> deleteList = ArrayCompare.findOwnPart(oldArray, minorMapIdArray);
                    //需要添加的部分
                    List<Integer> insertList = ArrayCompare.findOwnPart(minorMapIdArray, oldArray);


                if(deleteList.size()>0){
                    ArrayList<PermMapping> permMappingList = new ArrayList<>();
                    for(Integer permId:deleteList){
                        PermMapping permMapping = new PermMapping();
                        permMapping.setPermId(permId);
                        permMapping.setRoleId(mappingEntity.getPrimeMapId());
                        permMappingList.add(permMapping);
                    }
                    permMappingService.deletePermMappingList(permMappingList);
                }


                if(insertList.size()>0){
                    List<PermMapping> permMappingList = new ArrayList<>();
                    for(int permId:insertList){
                        //创建PermMapping对象,存放 role-perm 的映射信息
                        PermMapping permMapping = new PermMapping();
                        permMapping.setRoleId(mappingEntity.getPrimeMapId());
                        permMapping.setPermId(permId);
                        permMapping.setCreatorName(mappingEntity.getCreatorName());
                        permMapping.setCreateTime(timeStamp);

                        //将role-perm 的映射信息存入permMappingList
                        permMappingList.add(permMapping);
                    }

                    permMappingService.addPermMappingList(permMappingList);
                }


                hintMsg = "插入数据成功!!!";
                operFlag = true;

            }

        }

        jsonObject.put("hintMsg",hintMsg);
        jsonObject.put("operFlag",operFlag);
        System.out.println(jsonObject.toJSONString());
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println(jsonObject.toJSONString());
        resp.getWriter().close();

    }

   如果系统中的用户与角色的关系也是1对N的话,给用户分配角色的思路也是一样的。

权限校验

   系统中除了登录,注册,退出操作以外的所有请求都要进行拦截(这里我在考虑能否用网关拦截)。根据请求携带的session或cookie得到当前的用户信息。去数据库查询该用户的所有权限(建议将权限信息存入redis中),看看用户是否有当前操作的权限,如果没有,进行提示。

关于我


    可以扫描关注下面的公众号(公众号:猿类进化论)
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringCloud是一个基于Spring框架的开发工具集合,可以用于构建分布式系统的各个组件。Thymeleaf是一种用于构建Java应用程序的Java模板引擎,用于将数据渲染到HTML页面上。MyBatis-Plus是一个基于MyBatis框架的增强工具,提供了一些便捷的功能,如自动生成SQL语句、分页查询等。 在SpringCloud中,我们可以使用Thymeleaf来构建前端页面,通过MyBatis-Plus来操作数据库进行增删改查操作。 首先,我们需要在SpringCloud项目中引入Thymeleaf的依赖,并配置Thymeleaf的相关属性,如模板文件的存放位置、前缀后缀等。然后我们可以创建一个Controller类,使用@RequestMapping注解来处理请求,并返回视图模板。在视图模板中,我们可以使用Thymeleaf的语法来渲染数据,如插入变量、循环、条件判断等。 在MyBatis-Plus中,我们需要引入MyBatis-Plus的依赖,并配置MyBatis的相关属性,如数据库连接信息、Mapper接口扫描路径等。然后我们可以创建一个Mapper接口,使用@Mapper注解来标识该接口是一个Mapper,并编写相应的增删改查方法。MyBatis-Plus提供了一些注解,如@Select、@Insert、@Update、@Delete等,可以通过这些注解来实现对数据库的操作。 在Controller类中,我们可以通过@Autowired注解来注入Mapper接口,并调用相应的方法来实现对数据库的增删改查操作。通过前端页面的请求,Controller类将数据传递给Thymeleaf视图模板进行渲染,最后将渲染后的页面返回给前端展示。 通过SpringCloudThymeleaf、MyBatis-Plus的结合使用,我们可以方便地实现对数据库的增删改查操作,并将数据展示在前端页面上,实现一个完整的CRUD功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值