ztree权限树形菜单多级数据封装和遍历

本文档详细介绍了如何在Java后端及Vue前端实现Ztree的权限树形菜单数据封装和遍历。从后台数据格式、实体类、控制器、Mapper文件到前端页面和接口的实现,全方位展示了一套完整的解决方案。涉及到的技术栈包括Servlet、Mybatis、XML以及Vue。
摘要由CSDN通过智能技术生成

一、参照1

这里主要介绍controller封装ztree参数,具体业务以实际为准,这里controller里封装的数据最好写在service层。

1.前台返回数据的格式

var zNodes =[
               { name:"父节点1 - 展开", open:true,
                   children: [
                       { name:"父节点11 - 折叠",
                           children: [
                               { name:"叶子节点111"},
                               { name:"叶子节点112"},
                               { name:"叶子节点113"},
                               { name:"叶子节点114"}

]}, { name:"父节点12 - 折叠", children: [ { name:"叶子节点121"}, { name:"叶子节点122"}, { name:"叶子节点123"}, { name:"叶子节点124"} ]}, { name:"父节点13 - 没有子节点", isParent:true} ]}, { name:"父节点2 - 折叠", children: [ { name:"父节点21 - 展开", open:true, children: [ { name:"叶子节点211"}, { name:"叶子节点212"}, { name:"叶子节点213"}, { name:"叶子节点214"} ]}, { name:"父节点22 - 折叠", children: [ { name:"叶子节点221"}, { name:"叶子节点222"}, { name:"叶子节点223"}, { name:"叶子节点224"} ]}, { name:"父节点23 - 折叠", children: [ { name:"叶子节点231"}, { name:"叶子节点232"}, { name:"叶子节点233"}, { name:"叶子节点234"} ]} ]}, { name:"父节点3 - 没有子节点", isParent:true} ];
    <c:forEach items="${sessionScope.permissionRoot.children }" var="permission">
        <c:if test="${empty permission.children}">
            <li class="list-group-item tree-closed" >
                <a href="${APP_PATH }/${permission.url }"><i class="${permission.icon}"></i> ${permission.name }</a> 
            </li>
        </c:if>
        <c:if test="${not empty permission.children}" >
            <li class="list-group-item tree-closed">
                <span><i class="${permission.icon}"></i> ${permission.name } <span class="badge" style="float:right">${fn:length(permission.children)}    <%-- ${permission.children.size() } --%></span></span> 
                <ul style="margin-top:10px;display:none;">
                    <c:forEach items="${permission.children }" var="innerPermission">
                        <li style="height:30px;">                    
                            <a href="${APP_PATH }/${innerPermission.url}"><i class="${innerPermission.icon }"></i> ${innerPermission.name }</a> 
                        </li>
                    </c:forEach>
                </ul>
            </li>
        </c:if>
    </c:forEach> 

2.封装的类

package com.stuwork.crowdfunding.bean;

import java.util.ArrayList;
import java.util.List;

public class Permission {
    private Integer id;

    private Integer pid;

    private String name;

    private String icon;

    private String url;
    private boolean open;
    private boolean checked;
    
    private List<Permission> children = new ArrayList<Permission>();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getPid() {
        return pid;
    }

    public void setPid(Integer pid) {
        this.pid = pid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon == null ? null : icon.trim();
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url == null ? null : url.trim();
    }

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        this.open = open;
    }

    public List<Permission> getChildren() {
        return children;
    }

    public void setChildren(List<Permission> children) {
        this.children = children;
    }

    public boolean isChecked() {
        return checked;
    }

    public void setChecked(boolean checked) {
        this.checked = checked;
    }
}
package com.stuwork.crowdfunding.util;
public class AjaxResult {
    private boolean success;
    private String message;
    private Page page;
    private Object data;
    
    public Page getPage() {
        return page;
    }

    public void setPage(Page page) {
        this.page = page;
    }

    public boolean getSuccess() {
        return success;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    
    
}

3.controller几种返回数据格式封装和优化

package com.stuwork.crowdfunding.manager.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.stuwork.crowdfunding.bean.Permission;
import com.stuwork.crowdfunding.manager.service.PermissionService;
import com.stuwork.crowdfunding.util.AjaxResult;

@Controller
@RequestMapping("/permission")
public class PermissionController {

    @Autowired
    private PermissionService permissionService;
    
    //最终版方式1
    //最终优化版,减少循环的次数
    @ResponseBody
    @RequestMapping("/loadData")
    public Object loadData(){
        AjaxResult result = new AjaxResult();

        try {
            List<Permission> root = new ArrayList<Permission>();
            List<Permission>  permissionList = permissionService.getAllPermission();//根菜单
            Map<Integer,Permission> map = new HashMap<Integer,Permission>();
            for(Permission bean :permissionList){
                map.put(bean.getId(), bean);
            }
            for(Permission bean :permissionList){
                Permission children = bean;
                if(bean.getPid() == 0){
                   root.add(bean);
                }else{
                    Permission parent = map.get(children.getPid());
                    parent.getChildren().add(children);     
                }
            }
            
            result.setData(root);
            result.setSuccess(true);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage("许可树加载失败");
            e.printStackTrace();
        }
        
        return result;
        
    }
   //方式2 @ResponseBody //递归优化 @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); List<Permission> permissionList = permissionService.getAllPermission();//根菜单 for(Permission bean :permissionList){ Permission children = bean;//子菜单 if(children.getPid() == 0){ root.add(bean); }else{ for(Permission innerPermission:permissionList){ if(children.getPid() == innerPermission.getId()){ innerPermission.getChildren().add(children); break; } } } } result.setData(root); result.setSuccess(true); } catch (Exception e) { result.setSuccess(false); result.setMessage("许可树加载失败"); e.printStackTrace(); } return result; } //方式3 //递归,解决多个层次 //效率低,多次调用数据库 @ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); Permission permission = permissionService.getRootPermission();//根菜单 root.add(permission); getPermissionChildern(permission); result.setData(root); result.setSuccess(true); } catch (Exception e) { result.setSuccess(false); result.setMessage("许可树加载失败"); e.printStackTrace(); } return result; } /** * 递归使用注意事项 * 1.调用自身 * 2.范围要不断缩小 * 3.要有跳出条件 * @param permission */ private void getPermissionChildern(Permission permission){ List<Permission> childrenList = permissionService.getChildrenPermissionByPid(permission.getId()); permission.setChildren(childrenList); for(Permission bean:childrenList){ getPermissionChildern(bean); } } //方式4(这个是demo,没从数据库取数据) @ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { Permission permission = new Permission();//父菜单 Permission permission1 = new Permission();//子菜单 Permission permission2 = new Permission();//子菜单 List<Permission> list = new ArrayList<Permission>();//子菜单 List<Permission> root = new ArrayList<Permission>();//根菜单 permission.setName("系统权限菜单"); permission.setOpen(true); permission1.setName("控制面板"); permission2.setName("权限管理"); list.add(permission1); list.add(permission2); permission.setChildren(list); root.add(permission); result.setData(root); result.setSuccess(true); } catch (Exception e) { result.setSuccess(false); result.setMessage("许可树加载失败"); e.printStackTrace(); } return result; }
//方式5 @ResponseBody @RequestMapping("/loadData") public Object loadData(){ AjaxResult result = new AjaxResult(); try { List<Permission> root = new ArrayList<Permission>(); Permission permission = permissionService.getRootPermission();//根菜单 permission.setOpen(true); root.add(permission); List<Permission> childrenList = permissionService.getChildrenPermissionByPid(permission.getId()); permission.setChildren(childrenList); for(Permission bean :childrenList){ bean.setOpen(true); List<Permission> innerChildrenList = permissionService.getChildrenPermissionByPid(bean.getId()); bean.setChildren(innerChildrenList); } result.setData(root); result.setSuccess(true); } catch (Exception e) { result.setSuccess(false); result.setMessage("许可树加载失败"); e.printStackTrace(); } return result; } }

4.mapper文件方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stuwork.crowdfunding.manager.dao.PermissionMapper">
  <resultMap id="BaseResultMap" type="Permission">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="pid" jdbcType="INTEGER" property="pid" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="icon" jdbcType="VARCHAR" property="icon" />
    <result column="url" jdbcType="VARCHAR" property="url" />
  </resultMap>
    <select id="getPermissionByRoleId" resultType="int">
    SELECT permissionid
      FROM t_role_permission 
     WHERE roleid = #{roleid}
  </select>
  <select id="getRootPermission" resultMap="BaseResultMap">
    SELECT id,pid,icon,url,name
      FROM t_permission 
     WHERE pid = 0
  </select>
  <select id="getChildrenPermissionByPid" resultMap="BaseResultMap">
    SELECT id,pid,icon,url,name
      FROM t_permission
     WHERE pid = #{id}
  </select>
  <select id="getAlltPermission" resultMap="BaseResultMap">
    SELECT id,pid,icon,url,name
      FROM t_permission 
  </select>

</mapper>

5.数据库表数据

二、参照2

1、实体类

package com.stu.aclservice.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.List;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 权限
 * </p>
 *
 * @author testjava
 * @since 2020-01-12
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("acl_permission")
@ApiModel(value="Permission对象", description="权限")
public class Permission implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "编号")
    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty(value = "所属上级")
    private String pid;

    @ApiModelProperty(value = "名称")
    private String name;

    @ApiModelProperty(value = "类型(1:菜单,2:按钮)")
    private Integer type;

    @ApiModelProperty(value = "权限值")
    private String permissionValue;

    @ApiModelProperty(value = "访问路径")
    private String path;

    @ApiModelProperty(value = "组件路径")
    private String component;

    @ApiModelProperty(value = "图标")
    private String icon;

    @ApiModelProperty(value = "状态(0:禁止,1:正常)")
    private Integer status;

    @ApiModelProperty(value = "层级")
    @TableField(exist = false)
    private Integer level;

    @ApiModelProperty(value = "下级")
    @TableField(exist = false)
    private List<Permission> children;

    @ApiModelProperty(value = "是否选中")
    @TableField(exist = false)
    private boolean isSelect;


    @ApiModelProperty(value = "逻辑删除 1(true)已删除, 0(false)未删除")
    private Boolean isDeleted;

    @ApiModelProperty(value = "创建时间")
    private Date gmtCreate;

    @ApiModelProperty(value = "更新时间")
    private Date gmtModified;


}

2、业务类

package com.stu.aclservice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.stu.aclservice.entity.Permission;
import com.stu.aclservice.entity.RolePermission;
import com.stu.aclservice.entity.User;
import com.stu.aclservice.helper.MemuHelper;
import com.stu.aclservice.helper.PermissionHelper;
import com.stu.aclservice.mapper.PermissionMapper;
import com.stu.aclservice.service.PermissionService;
import com.stu.aclservice.service.RolePermissionService;
import com.stu.aclservice.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2020-01-12
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Autowired
    private RolePermissionService rolePermissionService;
    
    @Autowired
    private UserService userService;
    
    //获取全部菜单
    @Override
    public List<Permission> queryAllMenu() {

        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<Permission> permissionList = baseMapper.selectList(wrapper);

        List<Permission> result = bulid(permissionList);

        return result;
    }

    //根据角色获取菜单
    @Override
    public List<Permission> selectAllMenu(String roleId) {
        List<Permission> allPermissionList = baseMapper.selectList(new QueryWrapper<Permission>().orderByAsc("CAST(id AS SIGNED)"));

        //根据角色id获取角色权限
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().eq("role_id",roleId));
        //转换给角色id与角色权限对应Map对象
//        List<String> permissionIdList = rolePermissionList.stream().map(e -> e.getPermissionId()).collect(Collectors.toList());
//        allPermissionList.forEach(permission -> {
//            if(permissionIdList.contains(permission.getId())) {
//                permission.setSelect(true);
//            } else {
//                permission.setSelect(false);
//            }
//        });
        for (int i = 0; i < allPermissionList.size(); i++) {
            Permission permission = allPermissionList.get(i);
            for (int m = 0; m < rolePermissionList.size(); m++) {
                RolePermission rolePermission = rolePermissionList.get(m);
                if(rolePermission.getPermissionId().equals(permission.getId())) {
                    permission.setSelect(true);
                }
            }
        }


        List<Permission> permissionList = bulid(allPermissionList);
        return permissionList;
    }

    //给角色分配权限
    @Override
    public void saveRolePermissionRealtionShip(String roleId, String[] permissionIds) {

        rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));

  

        List<RolePermission> rolePermissionList = new ArrayList<>();
        for(String permissionId : permissionIds) {
            if(StringUtils.isEmpty(permissionId)) continue;
      
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permissionId);
            rolePermissionList.add(rolePermission);
        }
        rolePermissionService.saveBatch(rolePermissionList);
    }

    //递归删除菜单
    @Override
    public void removeChildById(String id) {
        List<String> idList = new ArrayList<>();
        this.selectChildListById(id, idList);

        idList.add(id);
        baseMapper.deleteBatchIds(idList);
    }

    //根据用户id获取用户菜单
    @Override
    public List<String> selectPermissionValueByUserId(String id) {

        List<String> selectPermissionValueList = null;
        if(this.isSysAdmin(id)) {
            //如果是系统管理员,获取所有权限
            selectPermissionValueList = baseMapper.selectAllPermissionValue();
        } else {
            selectPermissionValueList = baseMapper.selectPermissionValueByUserId(id);
        }
        return selectPermissionValueList;
    }

    @Override
    public List<JSONObject> selectPermissionByUserId(String userId) {
        List<Permission> selectPermissionList = null;
        if(this.isSysAdmin(userId)) {
            //如果是超级管理员,获取所有菜单
            selectPermissionList = baseMapper.selectList(null);
        } else {
            selectPermissionList = baseMapper.selectPermissionByUserId(userId);
        }

        List<Permission> permissionList = PermissionHelper.bulid(selectPermissionList);
        List<JSONObject> result = MemuHelper.bulid(permissionList);
        return result;
    }

    /**
     * 判断用户是否系统管理员
     * @param userId
     * @return
     */
    private boolean isSysAdmin(String userId) {
        User user = userService.getById(userId);

        if(null != user && "admin".equals(user.getUsername())) {
            return true;
        }
        return false;
    }

    /**
     *    递归获取子节点
     * @param id
     * @param idList
     */
    private void selectChildListById(String id, List<String> idList) {
        List<Permission> childList = baseMapper.selectList(new QueryWrapper<Permission>().eq("pid", id).select("id"));
        childList.stream().forEach(item -> {
            idList.add(item.getId());
            this.selectChildListById(item.getId(), idList);
        });
    }

    /**
     * 使用递归方法建菜单
     * @param treeNodes
     * @return
     */
    private static List<Permission> bulid(List<Permission> treeNodes) {
        List<Permission> trees = new ArrayList<>();
        for (Permission treeNode : treeNodes) {
            if ("0".equals(treeNode.getPid())) {
                treeNode.setLevel(1);
                trees.add(findChildren(treeNode,treeNodes));
            }
        }
        return trees;
    }

    /**
     * 递归查找子节点
     * @param treeNodes
     * @return
     */
    private static Permission findChildren(Permission treeNode,List<Permission> treeNodes) {
        treeNode.setChildren(new ArrayList<Permission>());

        for (Permission it : treeNo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值