Java 项目中的菜单管理实现
一、前言
在现代 Java 应用开发中,菜单管理是一个常见的功能模块。本文将详细介绍一个基于 Spring 框架和 MyBatis Plus 的菜单查询实现,重点分析代码逻辑和设计思路,以帮助读者更好地理解和扩展这一实现。
1. 功能概述
该方法 getList(QueryMenuDTO queryMenuDTO)
的主要功能是根据查询条件获取系统菜单列表,并进行父级菜单的查找与分组。返回的结果是一个菜单视图对象的列表 (MenuVO
),适合前端展示。
2. 代码结构分析
2.1 查询条件设置
首先,使用 LambdaQueryWrapper
创建查询条件:
LambdaQueryWrapper<SystemMenu> menuVOLambdaQueryWrapper = new LambdaQueryWrapper<>();
接着,根据传入的 QueryMenuDTO
对象中的字段动态构造查询条件:
-
名称过滤:如果
name
字段不为空,则使用like
进行模糊查询。if (StrUtil.isNotBlank(queryMenuDTO.getName())) { menuVOLambdaQueryWrapper.like(SystemMenu::getName, queryMenuDTO.getName()); }
-
状态过滤:如果
status
字段不为 null,则添加等于条件。if (queryMenuDTO.getStatus() != null) { menuVOLambdaQueryWrapper.eq(SystemMenu::getStatus, queryMenuDTO.getStatus()); }
2.2 菜单列表获取
通过构造的查询条件,获取符合条件的菜单列表:
List<SystemMenu> list = this.list(menuVOLambdaQueryWrapper);
List<MenuVO> menuVOList = BeanUtil.copyToList(list, MenuVO.class);
2.3 父级菜单查找
为了确保返回的菜单列表包含所有父级菜单,我们需要对菜单进行逐级查找。使用一个集合 parentIds
来存储所有父级菜单的 ID:
Set<String> parentIds = new HashSet<>();
for (SystemMenu menu : list) {
String currentParentId = menu.getParentId();
while (StrUtil.isNotBlank(currentParentId)) {
parentIds.add(currentParentId);
SystemMenu parentMenu = this.getById(currentParentId);
if (parentMenu != null) {
currentParentId = parentMenu.getParentId();
} else {
break;
}
}
}
2.4 去重处理
通过菜单 ID 去重,确保父级菜单不重复添加:
Set<String> existingIds = new HashSet<>(list.stream().map(SystemMenu::getId).collect(Collectors.toSet()));
parentIds.removeIf(parentId -> existingIds.contains(parentId));
2.5 查找并添加父级菜单
如果有剩余的父级菜单 ID,则查询这些父级菜单并添加到结果列表中:
if (!parentIds.isEmpty()) {
LambdaQueryWrapper<SystemMenu> parentWrapper = new LambdaQueryWrapper<>();
parentWrapper.in(SystemMenu::getId, parentIds);
List<SystemMenu> parentMenus = this.list(parentWrapper);
menuVOList.addAll(BeanUtil.copyToList(parentMenus, MenuVO.class));
}
2.6 菜单分组
最终,通过 groupMenus
方法对菜单进行分组,将子菜单归入对应的父菜单下,并支持按权限分组的选项:
List<MenuVO> resultMenuVOList = this.groupMenus(menuVOList, false);
return resultMenuVOList;
3. 菜单分组逻辑
在 groupMenus
方法中,首先构建一个菜单映射表,然后遍历菜单列表,将子菜单按照父级菜单进行归类:
Map<String, MenuVO> menuMap = new HashMap<>();
for (MenuVO menu : menuList) {
menuMap.put(menu.getId(), menu);
}
对于每个菜单,如果其存在父级,便将其添加到相应的父级菜单的子菜单列表中;否则,将其视为根菜单加入到根菜单列表中。
4. 总结
本篇文章详细描述了如何通过 Java 实现一个灵活的菜单管理系统。通过动态构造查询条件、父级菜单的递归查找以及结果的分组处理,我们能够高效地展示菜单层级结构。这种设计不仅适用于简单的菜单结构,也为更加复杂的菜单系统奠定了基础。
希望本文能够帮助你更好地理解 Java 中的菜单管理实现,并为你自己的项目提供启发和参考。