菜单根据菜单ID向下递归
第一步:我们根据这个类定义数据库,并插入菜单数据
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 '' COMMENT '菜单顺序',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单表'; -- ----------------------------
-- Records of jrbac_menu
-- ----------------------------
INSERT INTO `jrbac_menu` VALUES ('', 'Forms', null, 'forms.html', 'fa fa-edit', '');
INSERT INTO `jrbac_menu` VALUES ('', 'UI Elements', null, '', 'fa fa-wrench', '');
INSERT INTO `jrbac_menu` VALUES ('', 'Buttons', '', 'buttons.html', '', '');
INSERT INTO `jrbac_menu` VALUES ('', 'Icons', '', 'icons.html', null, '');
INSERT INTO `jrbac_menu` VALUES ('', 'Multi-Level Dropdown', '', '', 'fa fa-sitemap', '');
INSERT INTO `jrbac_menu` VALUES ('', 'Second Level Item', '', 'second.html', null, '');
INSERT INTO `jrbac_menu` VALUES ('', 'Third Level', '', null, '', '');
INSERT INTO `jrbac_menu` VALUES ('', 'Third Level Item', '', 'third.html', null, '');
第二步:引入相应pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.payease</groupId>
<artifactId>sell</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>sell</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!-- ===================== mysql驱动 ======================== -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- ===================== jpa ======================== -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> <!-- ===================== @Getter @Setter @Slf4j @Data ======================== -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency> <!-- ===================== google: gson ======================== -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.36</version>
</dependency> <!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>2.7.0</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> <dependency>
<groupId>cn.springboot</groupId>
<artifactId>best-pay-sdk</artifactId>
<version>1.1.0</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
第三步:相应数据库的实体类(把数据库的那张表jrbac_menu 改为 menu)
package com.payease.dataobject; import lombok.Data; import javax.persistence.Entity;
import javax.persistence.Id; /**
* 菜单循环递归类
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午12:46
**/
@Entity
@Data
public class Menu {
// 菜单id
@Id
private String id;
// 菜单名称
private String name;
// 父菜单id
private String parentId;
// 菜单url
private String url;
// 菜单图标
private String icon;
// 菜单顺序
private int order; // ... 省去getter和setter方法以及toString方法
}
第四步:树形数据实体接口
package com.payease.utils; import java.util.List; /**
* 树形数据实体接口
* @param <E>
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午3:39
**/
public interface TreeEntity<E> {
// 菜单id
public String getId();
// 菜单名称
public String getName();
// 父菜单id
public String getParentId();
// 菜单url
public String getUrl();
// 菜单图标
public String getIcon();
// 菜单顺序
public int getOrder(); public void setChildList(List<E> childList); }
第五步:封装类menuVO
package com.payease.VO; import com.payease.utils.TreeEntity;
import lombok.Data; import java.util.List; /**
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午12:58
**/
@Data
public class MenuVO implements TreeEntity<MenuVO> {
// 菜单id
public String id;
// 菜单名称
public String name;
// 父菜单id
public String parentId;
// 菜单url
public String url;
// 菜单图标
public String icon;
// 菜单顺序
public int order;
// 子菜单
public List<MenuVO> childList; }
第六步:编写 解析树形数据工具类
package com.payease.utils; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList;
import java.util.List; /**
* 解析树形数据工具类
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午3:41
**/
public class TreeParser{
/**
* 解析树形数据
* @param topId
* @param entityList
* @return
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午3:41
*/
public static <E extends TreeEntity<E>> List<E> getTreeList(String topId, List<E> entityList) {
List<E> resultList=new ArrayList<>(); //获取顶层元素集合
String parentId;
if(StringUtils.isBlank(topId)){
//全查
for (E entity : entityList) {
parentId=entity.getParentId();
if(StringUtils.isBlank(parentId))
resultList.add(entity);
}
}else{
//根据传入的ID进行向下递归
for (E entity : entityList) {
parentId=entity.getParentId();
if(parentId!=null && topId.equals(parentId)){
resultList.add(entity);
}
}
} //获取每个顶层元素的子数据集合
for (E entity : resultList) {
entity.setChildList(getSubList(entity.getId(),entityList));
} return resultList;
} /**
* 获取子数据集合
* @param id
* @param entityList
* @return
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午3:41
*/
private static <E extends TreeEntity<E>> List<E> getSubList(String id, List<E> entityList) {
List<E> childList=new ArrayList<>();
String parentId; //子集的直接子对象
for (E entity : entityList) {
parentId=entity.getParentId();
if(id.equals(parentId)){
childList.add(entity);
}else{ }
} //子集的间接子对象
for (E entity : childList) {
entity.setChildList(getSubList(entity.getId(), entityList));
} //递归退出条件
if(childList.size()==0){
return null;
} return childList;
} }
第七步:编写对应的dao层
package com.payease.repository; import com.payease.dataobject.Menu;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import java.util.List; /**
* Created by liuxiaoming on 2017/11/13.
*/
@Repository
public interface MenuRepository extends JpaRepository<Menu, String> { List<Menu> findById(String orderId);
}
第八步:编写测试类
package com.payease.repository; import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.payease.VO.MenuVO;
import com.payease.dataobject.Menu;
import com.payease.utils.TreeParser;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList;
import java.util.List; /**
* @Created By liuxiaoming
* @CreateTime 2017/12/7 下午12:51
**/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class MenuRepositoryTest { @Autowired
private MenuRepository repository;
@Test
public void findById() throws Exception {
// 原始的数据
List<Menu> rootMenu = repository.findAll();
// 查看结果
List<MenuVO> rootMenuVO = new ArrayList<>();
for (Menu menu : rootMenu) {
MenuVO menuVO = new MenuVO();
BeanUtils.copyProperties(menu,menuVO);
rootMenuVO.add(menuVO);
// System.out.println("rootMenu:" + menuVO.toString());
} List<MenuVO> child = TreeParser.getTreeList("2",rootMenuVO); List<MenuVO> menus = TreeParser.getTreeList("2",rootMenuVO);
System.out.println(menus); Gson gson = new Gson();
String gJson = gson.toJson(menus);
System.out.println("gjson:"+gJson); String fastJson = JSON.toJSONString(child); System.out.println("fastJson:"+fastJson); } }
菜单根据菜单ID向下递归的更多相关文章
- PHP递归获得树形菜单和遍历文件夹下的所有文件以及子文件夹
PHP递归获得树形菜单和遍历文件夹下的所有文件以及子文件夹 一.使用递归获取树形菜单 数据表category(id,name,parent_id) <?php class category{ / ...
- #AOS应用基础平台# 添加了用户自己定义快捷菜单在平铺布局下的用户自己定义排序管理
#AOS开发平台# 添加了用户自己定义快捷菜单在平铺布局下的用户自己定义排序管理.
- jq自定义下拉菜单,在点击非当前下拉菜单区域时,关闭下拉菜单(点击事件的对象不是目标元素本身)
jq自定义下拉菜单,在点击非当前下拉菜单区域时,关闭下拉菜单(点击事件的对象不是目标元素本身) //点击非当前下拉菜单区域时,关闭下拉菜单 $(document).mousedown(function ...
- jq自定义下拉菜单,当用户点击非自身元素(下拉菜单)本身时关闭下拉菜单
jq自定义下拉菜单,当用户点击非自身元素(下拉菜单)本身时关闭下拉菜单 截图: 代码如下: //关闭用户菜单 $(document).mousedown(function(e){ var _con = ...
- 自定义右键菜单,禁用浏览器自带的右键菜单[右键菜单实现--Demo]
许多从事Web开发的会发现有些事,我们需要禁用浏览器本事自带的右键菜单,而实现自定义的右键菜单下面我们也来实现一个自定义的右键菜单 首先来创建JSP页面 <%@ page language=&q ...
- 微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理
1.概述 自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能.菜单分为默认菜单与个性化菜单.个性化菜单接口是为了帮助公众号实现灵活的业务运营,开发者可以通过该接口,让公众号的不同用户群 ...
- VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)
鸡啄米在上一节中讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为菜单的操作提供了CMenu类,下面鸡啄米就常用的几个成员函数进行简单的介绍. B ...
- Android_(菜单)选项菜单
Android系统中菜单分为Options Menu.Context Menu.Sub Men三种 Options Menu和Context Menu属于一级菜单 Sub Menu属于Options ...
- VS2010-MFC(菜单:菜单及CMenu类的使用)
转自:http://www.jizhuomi.com/software/212.html 上一节讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为 ...
随机推荐
- UVa 1606 Amphiphilic Carbon Molecules (扫描法+极角排序)
题意:平面上有 n 个点,每个点不是黑的就是白的,现在要放一个隔板,把它们分成两部分,使得一侧的白点数加上另一侧的黑点数最多. 析:这个题很容易想到的就是暴力,不妨假设隔板至少经过两个点,即使不经过也 ...
- windows环境下配置tornado
1.前言 在网上看过一些在windows下配置tornado的教程,有一些写的十分复杂,让人望而生却.然后我就自己试着在windows下面配置tornado.我发现,方法非常简单,短短几 ...
- iconv用法解读
iconv是一个字符集转换函数,原型为: size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, ...
- VM参数收集(部分)
VM参数收集 -verbose:gc 输出虚拟机中GC的详细情况 -Xms20M Heap初始容量为 20M -Xmx20M Heap最大容量为 20M -XX:+HeapDumpOnOutOfMem ...
- Objective-C 学习笔记(五) 指针
Objective-C 指针 每一个变量是一个内存位置和每一个存储单元都有其定义的地址,可以使用符号(&)的运算符,它表示内存中的地址访问. a. 我们定义一个指针变量 b. 分配一个指针变量 ...
- 报表导出jxls的使用笔记
基于poi的jxls工具的使用:1.依赖: <dependency> <groupId>org.jxls</groupId> <artifactId>j ...
- [51单片机] nRF24L01 无线模块 串口法命令 通过无线控制另一个的灯
>_<!概述: 这是在上一个的基础上通过按键发送4种不同命令来控制接收端的LED灯亮的改进版(上一个:http://www.cnblogs.com/zjutlitao/p/3840013. ...
- Pi 实现VLC网络视频监控
安装摄像头 将Pi的原装摄像头安装在pi上面 ssh连接pi 通过xshell或者putty等工具连接ssh 安装VLC $ sudo apt-get update $ sudo apt-get in ...
- Java50道经典习题-程序17 猴子吃桃问题
题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩下的桃子吃掉一半,又多吃了一个.以后每天早上都吃了前一天剩下的一半零一个.到第10天早上想再吃时,见只 ...
- java中集合
一. List集合: 一次只存储一个元素 1.常用的list集合是ArrayList (1)在创建这个集合的对象时, 需要指定这个集合存储的数据类型! 否则这个集合的数据是不安全的. (2)与数组的 ...