java 从数据库读取菜单,递归生成菜单树

本贴最后更新于 2751 天前,其中的信息可能已经渤澥桑田

首先看一下菜单的样子

根据这个样子我们定义菜单类

public class Menu { // 菜单id private String id; // 菜单名称 private String name; // 父菜单id private String parentId; // 菜单url private String url; // 菜单图标 private String icon; // 菜单顺序 private int order; // 子菜单 private List<Menu> childMenus; // ... 省去getter和setter方法以及toString方法 }

我们根据这个类定义数据库,并插入菜单数据

DROP TABLE IF EXISTS `jrbac_menu`; CREATE TABLE `jrbac_menu` ( `id` varchar(32) NOT NULL COMMENT '主键id,uuid32位', `name` varchar(64) NOT NULL COMMENT '登录用户名', `parent_id` varchar(32) DEFAULT NULL COMMENT '父菜单id', `url` varchar(64) DEFAULT NULL COMMENT '访问地址', `icon` varchar(32) DEFAULT NULL COMMENT '菜单图标', `order` tinyint(4) DEFAULT '0' COMMENT '菜单顺序', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单表'; -- ---------------------------- -- Records of jrbac_menu -- ---------------------------- INSERT INTO `jrbac_menu` VALUES ('1', 'Forms', null, 'forms.html', 'fa fa-edit', '0'); INSERT INTO `jrbac_menu` VALUES ('2', 'UI Elements', null, '', 'fa fa-wrench', '1'); INSERT INTO `jrbac_menu` VALUES ('3', 'Buttons', '2', 'buttons.html', '', '0'); INSERT INTO `jrbac_menu` VALUES ('4', 'Icons', '2', 'icons.html', null, '1'); INSERT INTO `jrbac_menu` VALUES ('5', 'Multi-Level Dropdown', '', '', 'fa fa-sitemap', '2'); INSERT INTO `jrbac_menu` VALUES ('6', 'Second Level Item', '5', 'second.html', null, '0'); INSERT INTO `jrbac_menu` VALUES ('7', 'Third Level', '5', null, '', '1'); INSERT INTO `jrbac_menu` VALUES ('8', 'Third Level Item', '7', 'third.html', null, '0');

为了演示,我们把可展开的没有做完,仅仅插入几条数据能出效果就可以了。

测试方法与递归方法

private final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); @Test public void testQueryMenuList() { // 原始的数据 List<Menu> rootMenu = menuDao.queryMenuList(null); // 查看结果 for (Menu menu : rootMenu) { System.out.println(menu); } // 最后的结果 List<Menu> menuList = new ArrayList<Menu>(); // 先找到所有的一级菜单 for (int i = 0; i < rootMenu.size(); i++) { // 一级菜单没有parentId if (StringUtils.isBlank(rootMenu.get(i).getParentId())) { menuList.add(rootMenu.get(i)); } } // 为一级菜单设置子菜单,getChild是递归调用的 for (Menu menu : menuList) { menu.setChildMenus(getChild(menu.getId(), rootMenu)); } Map<String,Object> jsonMap = new HashMap<>(); jsonMap.put("menu", menuList); System.out.println(gson.toJson(jsonMap)); } /** * 递归查找子菜单 * * @param id * 当前菜单id * @param rootMenu * 要查找的列表 * @return */ private List<Menu> getChild(String id, List<Menu> rootMenu) { // 子菜单 List<Menu> childList = new ArrayList<>(); for (Menu menu : rootMenu) { // 遍历所有节点,将父菜单id与传过来的id比较 if (StringUtils.isNotBlank(menu.getParentId())) { if (menu.getParentId().equals(id)) { childList.add(menu); } } } // 把子菜单的子菜单再循环一遍 for (Menu menu : childList) {// 没有url子菜单还有子菜单 if (StringUtils.isBlank(menu.getUrl())) { // 递归 menu.setChildMenus(getChild(menu.getId(), rootMenu)); } } // 递归退出条件 if (childList.size() == 0) { return null; } return childList; }

menuDao.queryMenuList(null);查找的结果是一条一条的数据

meuDao

package com.jrbac.dao; import java.util.List; import com.jrbac.entity.LoginUser; import com.jrbac.entity.Menu; public interface MenuDao { /** * 查找用户的菜单 * @param loginUser * @return */ public List<Menu> queryMenuList(LoginUser loginUser); }

mybatis

<?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.jrbac.dao.MenuDao"> <select id="queryMenuList" resultType="Menu"> SELECT id,`name`,parent_id,url,icon,`order` FROM jrbac_menu ORDER BY `order` ASC </select> </mapper>

测试程序的运行结果,对输出的 json 进行个格式化后的对比

最终效果

如果你也使用 sbadmin 后台模版的话,它只做到了二级菜单,三级的没有做展开控制。

要做到三级将 sb-admin-2.js 的最后一个替换成下面的。

if (element.is('li')) { element.addClass('active'); element.parent().addClass('in'); }

再奉上前端 jsp 页面输出菜单的代码

<c:forEach items="${userMenuList }" var="menu" varStatus="status"> <!-- 一级子菜单没有parentId,有url --> <c:if test="${empty menu.parentId and not empty menu.url}"> <li> <a href="<c:url value='${menu.url }'/>"> <i class="${menu.icon } fa-fw"></i> ${menu.name } </a> </li> </c:if> <!-- 可展开的一级菜单,没有parentId,有url --> <c:if test="${empty menu.parentId and empty menu.url}"> <li> <a href="#"> <i class="${menu.icon } fa-fw"></i> ${menu.name }<span class="fa arrow"></span> </a> <ul class="nav nav-second-level"> <!-- 没有url的是三级菜单,有url的直接输出到li中 --> <c:forEach items="${menu.childMenus}" var="secondChild" varStatus="status"> <c:if test="${not empty secondChild.url }"> <li> <a href="<c:url value='${secondChild.url }'/>">${secondChild.name }</a> </li> </c:if> <!-- 二级菜单url为空,表示还有三级菜单 --> <c:if test="${empty secondChild.url }"> <li> <a href="#">${secondChild.name }<span class="fa arrow"></span></a> <ul class="nav nav-third-level"> <c:forEach items="${secondChild.childMenus}" var="thirdChild" varStatus="status"> <li> <a href="<c:url value='${thirdChild.url }'/>">${thirdChild.name }</a> </li> </c:forEach> </ul> </li> </c:if> </c:forEach> </ul> </li> </c:if> </c:forEach> 转载自:http://blog.csdn.net/frankcheng5143/article/details/52958486
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8217 回帖
  • 递归
    15 引用 • 9 回帖
  • 菜单
    3 引用 • 5 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    😄

  • 其他回帖
  • someone

    😄 😄 😄

  • leap

    我也做了个类似的。不过前端是 vue。哈哈😂

推荐标签 标签

  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    229 引用 • 476 回帖
  • Office

    Office 现已更名为 Microsoft 365. Microsoft 365 将高级 Office 应用(如 Word、Excel 和 PowerPoint)与 1 TB 的 OneDrive 云存储空间、高级安全性等结合在一起,可帮助你在任何设备上完成操作。

    5 引用 • 34 回帖
  • Access
    1 引用 • 3 回帖 • 3 关注
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    346 引用 • 757 回帖 • 1 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    92 引用 • 752 回帖 • 3 关注
  • abitmean

    有点意思就行了

    36 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 43 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 31 回帖
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 16 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    167 引用 • 408 回帖 • 486 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 656 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 443 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 82 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 104 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 1 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖 • 1 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 8 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 2 关注
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    32 引用 • 99 回帖
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    46 引用 • 114 回帖 • 168 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • OneDrive
    2 引用 • 3 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 546 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    93 引用 • 122 回帖 • 616 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 1 关注