递归权限树

一、 权限树的问题由来

  1. 在开发中难免遇到一个有多级菜单结构树,或者多级部门的结构树,亦或是省市区县的多级结构,数据结构类似如下的json数据
    [
        {
            "id": "1",
            "name": "主菜单1",
            "pid": "0",
            "menuChildren": [
                {
                    "id": "4",
                    "name": "子菜单1.1",
                    "pid": "1",
                    "menuChildren": [
                        {
                            "id": "6",
                            "name": "子菜单1.1.1",
                            "pid": "4",
                            "menuChildren": []
                        },
                        {
                            "id": "9",
                            "name": "子菜单1.1.2",
                            "pid": "4",
                            "menuChildren": []
                        }
                    ]
                },
                {
                    "id": "5",
                    "name": "子菜单1.2",
                    "pid": "1",
                    "menuChildren": []
                }
            ]
        },
        {
            "id": "2",
            "name": "主菜单2",
            "pid": "0",
            "menuChildren": [
                {
                    "id": "7",
                    "name": "子菜单2.1",
                    "pid": "2",
                    "menuChildren": []
                },
                {
                    "id": "8",
                    "name": "子菜单2.2",
                    "pid": "2",
                    "menuChildren": []
                }
            ]
        },
        {
            "id": "3",
            "name": "主菜单3",
            "pid": "0",
            "menuChildren": []
        }
    ]
    

    二、 解决方案
    目前的解决方案主要有以下两种方案:

    方案一:后端把所有需要的数据以一个大list返回前端,前端进行操作,把数据搞成树状结构
    方案二: 后端在后端返回数据之前把数据搞成已经有层次结构的数据,方案二也分为两种解决方法
       1.方法一:次性将数据查询出来,在java程序中进行树状结构的构建
       2.方法二: 第一次将最高层次的数据查询出来,然后多次循环查询数据库将子数据查询出来
    由于博主的前端水平有限,目前只能用后端的实现方式,再加上每次查询数据库的开销比较大,所以本文使用方案二的方法一进行验证

    实现步骤
    以菜单的结构树为例

    准备mysql数据库的基础数据
    在这里插入图片描述

  2. java的实体类 :

    @Data
    @NoArgsConstructor
    public class Menu implements Serializable {
    
        private String  id;
        private String name;
        private String pid;
        private List<Menu> menuChildren;
    }
    
  3. dao层

@Mapper
public interface MenuDao {

    /**
     * 根据父类id查询子类菜单
     * @param pid
     * @return
     */
     List<Menu> selectByPid(Integer pid);

    /**
     * 查询所有的菜单
     * @return
     */
     List<Menu> selectAll();

    /**
     * 查询除了一级菜单以外的菜单
     * @return
     */
     List<Menu> selectAllNotBase();
}

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.ratel.shiro.dao.MenuDao">


    <select id="selectByPid" resultType="com.ratel.shiro.entity.Menu">
        SELECT * FROM menu WHERE  pid=#{pid}
    </select>

    <select id="selectAll" resultType="com.ratel.shiro.entity.Menu">
        SELECT * FROM menu
    </select>

    <select id="selectAllNotBase" resultType="com.ratel.shiro.entity.Menu">
        SELECT * FROM menu where pid!= 0
    </select>
</mapper>

5.Controller层(由于是查询操作,并且没有复杂的操作,偷个懒没写service层)

@RestController
@RequestMapping("mymenu")
public class MenuController {

    @Autowired
    private MenuDao menuDao;


    @RequestMapping("/getMenuTree")
    public List<Menu> getMenuTree(){
        List<Menu> menusBase = menuDao.selectByPid(0);
        List<Menu> menuLNotBase = menuDao.selectAllNotBase();
        for (Menu menu : menusBase) {
            List<Menu> menus = iterateMenus(menuLNotBase, menu.getId());
            menu.setMenuChildren(menus);
        }
        return  menusBase;
    }


    /**
     *多级菜单查询方法
     * @param menuVoList 不包含最高层次菜单的菜单集合
     * @param pid 父类id
     * @return
     */
    public List<Menu> iterateMenus(List<Menu> menuVoList,String pid){
        List<Menu> result = new ArrayList<Menu>();
        for (Menu menu : menuVoList) {
            //获取菜单的id
            String menuid = menu.getId();
            //获取菜单的父id
            String parentid = menu.getPid();
            if(StringUtils.isNotBlank(parentid)){
                if(parentid.equals(pid)){
                    //递归查询当前子菜单的子菜单
                    List<Menu> iterateMenu = iterateMenus(menuVoList,menuid);
                    menu.setMenuChildren(iterateMenu);
                    result.add(menu);
                }
            }
        }
        return result;
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值