java从数据库读取菜单,递归生成菜单树
首先看一下菜单的样子
根据这个样子我们定义菜单类
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进行个格式化后的对比