通常我们在给前端返回登陆数据的时候需要返回用户拥有的树状菜单,关于树状菜单的生成,这里提供两种方式
定义菜单实体类
/**
* 内部类-菜单树
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
private class MenuTree implements Serializable {
private static final long serialVersionUID = 3395212845810432335L;
/**
* 菜单id
*/
private Integer id;
/**
* 菜单名称
*/
private String menuName;
/**
* 父级菜单id
*/
private Integer parentId;
/**
* 菜单类型(0-目录 1-页面 2-按钮 9-系统)
*/
private Integer menuType;
/**
* 子菜单列表
*/
private List<MenuTree> children;
}
添加测试数据
/**
* 内部方法-生成测试数据
*/
private List<MenuTree> generateTestData() {
List<MenuTree> menuTrees = new ArrayList<>();
MenuTree menuTree = new MenuTree(1, "系统管理", 0, 0, null);
menuTrees.add(menuTree);
MenuTree menuTree2 = new MenuTree(2, "用户管理", 1, 1, null);
menuTrees.add(menuTree2);
MenuTree menuTree3 = new MenuTree(3, "角色管理", 1, 1, null);
menuTrees.add(menuTree3);
MenuTree menuTree4 = new MenuTree(4, "菜单管理", 1, 1, null);
menuTrees.add(menuTree4);
MenuTree menuTree5 = new MenuTree(5, "用户添加", 2, 2, null);
menuTrees.add(menuTree5);
MenuTree menuTree6 = new MenuTree(6, "用户删除", 2, 2, null);
menuTrees.add(menuTree6);
MenuTree menuTree7 = new MenuTree(7, "角色添加", 3, 2, null);
menuTrees.add(menuTree7);
MenuTree menuTree8 = new MenuTree(8, "角色删除", 3, 2, null);
menuTrees.add(menuTree8);
MenuTree menuTree9 = new MenuTree(9, "菜单添加", 4, 2, null);
menuTrees.add(menuTree9);
return menuTrees;
}
方式一: 递归生成菜单树
/**
* 内部方法-递归获取获取菜单树(核心是设置子菜单集)
* @param parentId
* @param menus
* @return
*/
private List<MenuTree> recursionMenuTree(int parentId, List<MenuTree> menus) {
List<MenuTree> children = new ArrayList<>();
for (MenuTree menu : menus) {
// 递归出口-如果当前是子菜单
if (menu.getParentId() == parentId) {
MenuTree child = new MenuTree();
BeanUtil.copyProperties(menu, child);
child.setChildren(recursionMenuTree(menu.getId(), menus));
children.add(child);
}
}
return children;
}
方式二: 通过双循环生成菜单树
/**
* 双循环获取菜单树
* @param menus
* @return
*/
private List<MenuTree> loopMenuTree(List<MenuTree> menus) {
// 最终结果
List<MenuTree> resultMenus = new ArrayList<>();
// 所有菜单集(含children)
List<MenuTree> loopMenus = new ArrayList<>();
// 第一层循环 拿到每一个菜单
for (MenuTree parent : menus) {
// 第二层循环 获取每一个菜单的直接子菜单集
List<MenuTree> children = new ArrayList<>();
for (MenuTree child : menus) {
if (child.getParentId() == (parent.getId())) {
children.add(child);
}
}
parent.setChildren(children);
loopMenus.add(parent);
}
// 最后只取父级id为0的菜单
for (MenuTree resultMenu : loopMenus) {
if (resultMenu.getParentId() == 0) {
resultMenus.add(resultMenu);
}
}
return resultMenus;
}
测试效果
public static void main(String[] args) {
TreeTest test = new TreeTest();
List<MenuTree> menuTrees = test.generateTestData();
System.out.println("初始菜单列表:" + JSONObject.toJSONString(menuTrees));
// 递归获取菜单树
List<MenuTree> recursionMenus = test.recursionMenuTree(0, menuTrees);
System.out.println("递归获取菜单树:" + JSONObject.toJSONString(recursionMenus));
// 循环获取菜单树
List<MenuTree> loopMenus = test.loopMenuTree(menuTrees);
System.out.println("循环获取菜单树:" + JSONObject.toJSONString(loopMenus));
}
最后总结:
两种方式其实都是在内部循环设置子菜单列表,区别在于递归的方式写法比较简单,但是理解起来要困难些,循环的方式便于理解,就是代码略微复杂。都是基本功,在此作记录,^_^
评论区