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

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

首先看一下菜单的样子

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

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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖
  • 递归
    15 引用 • 9 回帖
  • 菜单
    3 引用 • 5 回帖

相关帖子

欢迎来到这里!

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

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

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

  • 其他回帖
  • someone

    😄

  • someone

    😄 😄 😄

推荐标签 标签

  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 719 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 165 关注
  • PostgreSQL

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

    22 引用 • 22 回帖 • 3 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 75 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 369 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 145 关注
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖
  • GitBook

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

    3 引用 • 8 回帖
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    84 引用 • 324 回帖 • 1 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 389 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 542 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    157 引用 • 289 回帖
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖 • 3 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 157 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 262 关注
  • 电影

    这是一个不能说的秘密。

    122 引用 • 608 回帖 • 1 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 20 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • OneNote
    1 引用 • 3 回帖 • 1 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    498 引用 • 1395 回帖 • 256 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    211 引用 • 358 回帖 • 1 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    335 引用 • 324 回帖 • 1 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 359 关注