在后台体系中,菜单栏有着严格的层次结构,它是体系便利与否的重要功能,像一级菜单,二级菜单,三级菜单乃至更多层级的菜单,咱们将它称为
菜单树
,菜单树往往需要后端程序员来构建好了之后再给前端程序员,前端程序员再去渲染到页面上这样一个流程,而且菜单列表是动态改变的。
那么该怎么构建一个菜单树呢?
在数据库中,menu 表最常见的字段
- id(主键)
- parent_id(父级ID)
- menu_name(菜单名称)
- path(途径)
- …(等等)
思路
- 咱们能够把菜单列表返回,获取
parent_id
字段等于0
的节点,称为根节点
,这样的节点代表一级菜单- 再经过
根节点
的主键
去寻觅子菜单
,由于要有多及菜单,所以要用递归
构建子树,直到没有子菜单为止- 最后经过构建完好的菜单树
menu 实体类
public class Menu {
private Long id;
private Long parentId;
private String name;
private List<Menu> childrenList;
public Menu(Long id, Long parentId, String name) {
this.id = id;
this.parentId = parentId;
this.name = name;
}
// getter setter...
}
构建菜单树分为以下几个步骤:
- 返回菜单的根节点
private List<Menu> getRootNode() {
List<Menu> rootNode = new ArrayList<>();
menuList.forEach(item -> {
if (item.getParentId() == 0) {
rootNode.add(item);
}
});
return rootNode;
}
- 构建子菜单树
private Menu builderChildrenNode(Menu rootNode) {
List<Menu> childrenList = new ArrayList<>();
menuList.forEach(item -> {
if (Objects.equals(item.getParentId(), rootNode.getId())) {
// 还需要遍历三级菜单今后的
Menu menu = builderChildrenNode(item);
childrenList.add(menu);
}
});
rootNode.setChildrenList(childrenList);
return rootNode;
}
- 构建菜单树
public List<Menu> buildTree() {
List<Menu> menus = getRootNode();
menus.forEach(this::builderChildrenNode);
return menus;
}
- 完好代码
public class MenuTree {
private final List<Menu> menuList;
public MenuTree(List<Menu> menuList) {
this.menuList = menuList;
}
/**
* 获取根结点
*
* @return
*/
private List<Menu> getRootNode() {
List<Menu> rootNode = new ArrayList<>();
menuList.forEach(item -> {
if (item.getParentId() == 0) {
rootNode.add(item);
}
});
return rootNode;
}
/**
* 构建子树
*
* @param rootNode
* @return
*/
private Menu builderChildrenNode(Menu rootNode) {
List<Menu> childrenList = new ArrayList<>();
menuList.forEach(item -> {
if (Objects.equals(item.getParentId(), rootNode.getId())) {
// 还需要遍历三级菜单今后的
Menu menu = builderChildrenNode(item);
childrenList.add(menu);
}
});
rootNode.setChildrenList(childrenList);
return rootNode;
}
/**
* 构建树
*
* @return
*/
public List<Menu> buildTree() {
List<Menu> menus = getRootNode();
menus.forEach(this::builderChildrenNode);
return menus;
}
}
测验
用到了fastjson2
依靠
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.28</version>
</dependency>
public class MenuTreeTest {
public static void main(String[] args) {
List<Menu> menuList = new ArrayList<>();
menuList.add(new Menu(1L, 0L, "一级菜单1"));
menuList.add(new Menu(2L, 0L, "一级菜单2"));
menuList.add(new Menu(3L, 0L, "一级菜单3"));
menuList.add(new Menu(4L, 1L, "二级菜单1"));
menuList.add(new Menu(5L, 1L, "二级菜单2"));
menuList.add(new Menu(6L, 4L, "三级菜单"));
menuList.add(new Menu(7L, 6L, "四级菜单"));
MenuTree menuTree = new MenuTree(menuList);
List<Menu> menus = menuTree.buildTree();
String jsonString = JSON.toJSONString(menus);
System.out.println(jsonString);
}
}
成果
[{
"childrenList": [{
"childrenList": [{
"childrenList": [{
"childrenList": [],
"id": 7,
"name": "四级菜单",
"parentId": 6
}],
"id": 6,
"name": "三级菜单",
"parentId": 4
}],
"id": 4,
"name": "二级菜单1",
"parentId": 1
}, {
"childrenList": [],
"id": 5,
"name": "二级菜单2",
"parentId": 1
}],
"id": 1,
"name": "一级菜单1",
"parentId": 0
}, {
"childrenList": [],
"id": 2,
"name": "一级菜单2",
"parentId": 0
}, {
"childrenList": [],
"id": 3,
"name": "一级菜单3",
"parentId": 0
}]
小伙伴们学会了嘛?赶快去动手试一试,欢迎提出主张。