大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
完整示例代码地址如下:
https://github.com/Dr-Water/springboot-action/tree/master/springboot-shiro
一、 权限树的问题由来
- 在开发中难免遇到一个有多级菜单结构树,或者多级部门的结构树,亦或是省市区县的多级结构,数据结构类似如下的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返回前端,前端进行操作,把数据搞成树状结构
- 方案二: 后端在后端返回数据之前把数据搞成已经有层次结构的数据,方案二也分为两种解决方法
- 方法一:次性将数据查询出来,在java程序中进行树状结构的构建
- 方法二: 第一次将最高层次的数据查询出来,然后多次循环查询数据库将子数据查询出来
由于博主的前端水平有限,目前只能用后端的实现方式,再加上每次查询数据库的开销比较大,所以本文使用方案二的方法一进行验证
实现步骤
以菜单的结构树为例
- 准备mysql数据库的基础数据
- java的实体类:
@Data
@NoArgsConstructor
public class Menu implements Serializable {
private String id;
private String name;
private String pid;
private List<Menu> menuChildren;
}
- java的dao层
@Mapper
public interface MenuDao {
/** * 根据父类id查询子类菜单 * @param pid * @return */
List<Menu> selectByPid(Integer pid);
/** * 查询所有的菜单 * @return */
List<Menu> selectAll();
/** * 查询除了一级菜单以外的菜单 * @return */
List<Menu> selectAllNotBase();
}
- 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>
- 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;
}
}
- 启动程序用postman进行测试:
返回的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": []
}
]
参考链接:
java递归 处理权限管理菜单树或分类
一次性搞定权限树遍历——–权限树后台遍历的通用解决方案
(java后台)用户权限的多级菜单遍历方法
java 用递归实现球上下级(牵涉到对上级的去重)
java递归获取某个父节点下面的所有子节点
java递归算法总结
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/193334.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...