2025年Java代码实现项目两级菜单展示(图文教程)

Java代码实现项目两级菜单展示(图文教程)本微博只适用于两层的菜单展示 写作的初衷是为了介绍递归做铺垫 详细说明都写在了代码的注释上 不做单独说明了 希望对你有所帮助 1 数据库设计 为了方便大家练习 提供建表 SQL 如下 Table structure for

大家好,我是讯享网,很高兴认识大家。

本微博只适用于两层的菜单展示,写作的初衷是为了介绍递归做铺垫。

详细说明都写在了代码的注释上,不做单独说明了,希望对你有所帮助。

1.数据库设计


讯享网

为了方便大家练习,提供建表SQL如下:

-- ---------------------------- -- Table structure for sys_menu -- ---------------------------- DROP TABLE IF EXISTS `sys_menu`; CREATE TABLE `sys_menu` ( `menu_id` bigint(20) NOT NULL AUTO_INCREMENT, `parent_id` bigint(20) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0', `name` varchar(50) DEFAULT NULL COMMENT '菜单名称', `url` varchar(200) DEFAULT NULL COMMENT '菜单URL', `perms` varchar(500) DEFAULT NULL COMMENT '授权(多个用逗号分隔,如:user:list,user:create)', `type` int(11) DEFAULT NULL COMMENT '类型 0:目录 1:菜单 2:按钮', `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标', `order_num` int(11) DEFAULT NULL COMMENT '排序', `gmt_create` datetime DEFAULT NULL COMMENT '创建时间', `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`menu_id`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COMMENT='菜单管理';

讯享网

2.实体类MenuDO

该实体类是在工作中总结出来的,字段较全,适用场景也比较多。但实际上,最主要的字段只有前几个:menuId、parentId、name、url。

讯享网import java.io.Serializable; import java.util.Date; public class MenuDO implements Serializable { private static final long serialVersionUID = 1L; // 主键 private Long menuId; // 父菜单ID,一级菜单为0 private Long parentId; // 菜单名称 private String name; // 菜单URL private String url; // 授权(多个用逗号分隔,如:user:list,user:create) private String perms; // 类型 0:目录 1:菜单 2:按钮 private Integer type; // 菜单图标 private String icon; // 排序 private Integer orderNum; // 创建时间 private Date gmtCreate; // 修改时间 private Date gmtModified; ...... // 省略get()、set()等方法 }

3.业务类Tree<T>

public class Tree<T> { // 节点ID private String id; // 显示节点文本 private String text; // 节点状态,open closed private Map<String, Object> state; // 节点是否被选中 true false private boolean checked = false; // 节点属性 private Map<String, Object> attributes; // 节点的子节点 private List<Tree<T>> children = new ArrayList<Tree<T>>(); // 父ID private String parentId; // 是否有父节点 private boolean hasParent = false; // 是否有子节点 private boolean hasChildren = false; ...... // 省略get()、set()等方法 }

4.service层调用的方法

返回的list结果,就是满足逻辑的tree型数据,可以直接返回给页面使用。

讯享网 public List<Tree<MenuDO>> listMenuTree() { String idParam = "0"; // 自定义顶级结点 List<Tree<MenuDO>> trees = new ArrayList<Tree<MenuDO>>(); // 存放结果 List<MenuDO> menuDOs = menuMapper.queryList(); // 取出数据 // 1. 初步处理:让原始数据具备我们自定的的tree的特征 for (MenuDO sysMenuDO : menuDOs) { Tree<MenuDO> tree = new Tree<MenuDO>(); tree.setId(sysMenuDO.getMenuId().toString()); tree.setParentId(sysMenuDO.getParentId().toString()); tree.setText(sysMenuDO.getName()); Map<String, Object> attributes = new HashMap<>(16); attributes.put("url", sysMenuDO.getUrl()); attributes.put("icon", sysMenuDO.getIcon()); tree.setAttributes(attributes); trees.add(tree); } // 2. 递归处理:根据数据库实际情况调整顶级结点的parentId值,默认为0 List<Tree<MenuDO>> list = BuildTree.buildList(trees, idParam); return list; }

5.util类

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; / * 递归树形结构类 */ public class BuildTree { / * 自定义顶级结点的parentId,返回递归树形结构 */ public static <T> List<Tree<T>> buildList(List<Tree<T>> nodes, String idParam) { // 1.非空判断 if (nodes == null) { return null; } // 2.定义返回数据类型 List<Tree<T>> topNodes = new ArrayList<Tree<T>>(); // 3.取出每一个元素,判断它有没有父类 for (Tree<T> children : nodes) { String pid = children.getParentId(); // 3.1 pid(parentId)为空,或者等于父节点,则没有父类,直接返回 if (pid == null || idParam.equals(pid)) { topNodes.add(children); continue; } // 3.2 否则,遍历一遍集合,找它的父类,原则:子类的parentId = 父类的id for (Tree<T> parent : nodes) { String id = parent.getId(); if (id != null && id.equals(pid)) { // 3.2.1 将子类添加到父类的children属性下 parent.getChildren().add(children); // 3.2.2 设置子节点闭合状态:true - 关闭 children.setHasParent(true); parent.setChildren(true); } } } // 4. 返回结果集 return topNodes; } }

6.结果展示

基于BootDo成熟的架构,小编自己搭建了一个开发框架,使用递归展示菜单栏,效果如下:

 

更多精彩,请关注我的"今日头条号":Java云笔记
随时随地,让你拥有最新,最便捷的掌上云服务

小讯
上一篇 2025-04-10 09:41
下一篇 2025-02-06 10:47

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/66210.html