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

                       

首先看一下菜单的样子

这里写图片描述

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

publicclassMenu{ // 菜单id privateString id; // 菜单名称 privateString name; // 父菜单id privateString parentId; // 菜单url privateString url; // 菜单图标 privateString icon; // 菜单顺序 privateintorder; // 子菜单 privateList<Menu>childMenus; // ... 省去getter和setter方法以及toString方法}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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

DROPTABLEIFEXISTS`jrbac_menu`;CREATETABLE`jrbac_menu`(  `id`varchar(32)NOTNULLCOMMENT'主键id,uuid32位',  `name`varchar(64)NOTNULLCOMMENT'菜单名称',  `parent_id`varchar(32)DEFAULTNULLCOMMENT'父菜单id',  `url`varchar(64)DEFAULTNULLCOMMENT'访问地址',  `icon`varchar(32)DEFAULTNULLCOMMENT'菜单图标',  `order`tinyint(4)DEFAULT'0'COMMENT'菜单顺序',  PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8 COMMENT='菜单表';-- ------------------------------ Records of jrbac_menu-- ----------------------------INSERTINTO`jrbac_menu`VALUES('1','Forms',null,'forms.html','fa fa-edit','0');INSERTINTO`jrbac_menu`VALUES('2','UI Elements',null,'','fa fa-wrench','1');INSERTINTO`jrbac_menu`VALUES('3','Buttons','2','buttons.html','','0');INSERTINTO`jrbac_menu`VALUES('4','Icons','2','icons.html',null,'1');INSERTINTO`jrbac_menu`VALUES('5','Multi-Level Dropdown','','','fa fa-sitemap','2');INSERTINTO`jrbac_menu`VALUES('6','Second Level Item','5','second.html',null,'0');INSERTINTO`jrbac_menu`VALUES('7','Third Level','5',null,'','1');INSERTINTO`jrbac_menu`VALUES('8','Third Level Item','7','third.html',null,'0');
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

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

测试方法与递归方法

privatefinalGson gson =newGsonBuilder().disableHtmlEscaping().create();@TestpublicvoidtestQueryMenuList(){ // 原始的数据 List<Menu>rootMenu =menuDao.queryMenuList(null); // 查看结果 for(Menu menu :rootMenu){  System.out.println(menu); } // 最后的结果 List<Menu>menuList =newArrayList<Menu>(); // 先找到所有的一级菜单 for(inti =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 =newHashMap<>(); jsonMap.put("menu",menuList); System.out.println(gson.toJson(jsonMap));}/** * 递归查找子菜单 *  * @param id *            当前菜单id * @param rootMenu *            要查找的列表 * @return */privateList<Menu>getChild(String id,List<Menu>rootMenu){ // 子菜单 List<Menu>childList =newArrayList<>(); 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){  returnnull; } returnchildList;}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

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

这里写图片描述

meuDao

packagecom.jrbac.dao;importjava.util.List;importcom.jrbac.entity.LoginUser;importcom.jrbac.entity.Menu;publicinterfaceMenuDao{ /**  * 查找用户的菜单  * @param loginUser  * @return  */ publicList<Menu>queryMenuList(LoginUser loginUser);}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

mybatis

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//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>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

这里写图片描述

最终效果

这里写图片描述

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

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

if(element.is('li')){    element.addClass('active');    element.parent().addClass('in');}
  
  
  • 1
  • 2
  • 3
  • 4

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

<c:forEach items="${userMenuList }"var="menu"varStatus="status">                   <!--一级子菜单没有parentId,有url -->                   <c:iftest="${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:iftest="${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:iftest="${not empty secondChild.url }">      <li>                                 <a href="<c:url value='${secondChild.url }'/>">${secondChild.name }</a>                              </li>     </c:if>     <!--二级菜单url为空,表示还有三级菜单 -->     <c:iftest="${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>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
           
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值