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

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向下递归的更多相关文章

  1. PHP递归获得树形菜单和遍历文件夹下的所有文件以及子文件夹

    PHP递归获得树形菜单和遍历文件夹下的所有文件以及子文件夹 一.使用递归获取树形菜单 数据表category(id,name,parent_id) <?php class category{ / ...

  2. #AOS应用基础平台# 添加了用户自己定义快捷菜单在平铺布局下的用户自己定义排序管理

    #AOS开发平台# 添加了用户自己定义快捷菜单在平铺布局下的用户自己定义排序管理.

  3. jq自定义下拉菜单,在点击非当前下拉菜单区域时,关闭下拉菜单(点击事件的对象不是目标元素本身)

    jq自定义下拉菜单,在点击非当前下拉菜单区域时,关闭下拉菜单(点击事件的对象不是目标元素本身) //点击非当前下拉菜单区域时,关闭下拉菜单 $(document).mousedown(function ...

  4. jq自定义下拉菜单,当用户点击非自身元素(下拉菜单)本身时关闭下拉菜单

    jq自定义下拉菜单,当用户点击非自身元素(下拉菜单)本身时关闭下拉菜单 截图: 代码如下: //关闭用户菜单 $(document).mousedown(function(e){ var _con = ...

  5. 自定义右键菜单,禁用浏览器自带的右键菜单[右键菜单实现--Demo]

    许多从事Web开发的会发现有些事,我们需要禁用浏览器本事自带的右键菜单,而实现自定义的右键菜单下面我们也来实现一个自定义的右键菜单 首先来创建JSP页面 <%@ page language=&q ...

  6. 微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理

    1.概述 自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能.菜单分为默认菜单与个性化菜单.个性化菜单接口是为了帮助公众号实现灵活的业务运营,开发者可以通过该接口,让公众号的不同用户群 ...

  7. VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)

    鸡啄米在上一节中讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为菜单的操作提供了CMenu类,下面鸡啄米就常用的几个成员函数进行简单的介绍. B ...

  8. Android_(菜单)选项菜单

    Android系统中菜单分为Options Menu.Context Menu.Sub Men三种 Options Menu和Context Menu属于一级菜单 Sub Menu属于Options ...

  9. VS2010-MFC(菜单:菜单及CMenu类的使用)

    转自:http://www.jizhuomi.com/software/212.html 上一节讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为 ...

随机推荐

  1. 23 DesignPatterns学习笔记:C++语言实现 --- 2.1 Bridge

    23 DesignPatterns学习笔记:C++语言实现 --- 2.1 Bridge 2016-07-22 (www.cnblogs.com/icmzn) 模式理解  

  2. 汉诺塔问题的算法分析与实现(Java)

    汉诺塔问题是源于印度一个古老传说的益智玩具.要求将圆盘从A柱移动到C柱规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘. 可以先通过3个盘子的hanoi游戏得出其算法步骤如下: if ...

  3. View Pi's Status on WebBrowser

    1. install php and cgi support sudo apt-get install php5-common sudo apt-get install php5-cgi sudo a ...

  4. Js复制链接代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. WIN7或2008远程连接特别慢的解决方法 【转】

    方法一. 原因在于从vista开始,微软在TCP/IP协议栈里新加了一个叫做“Window Auto-Tuning”的功能.这个功能本身的目的是为了让操作系统根据网络的实时性能,(比如响应时间)来动态 ...

  6. ffmpeg学习(二) 通过rtsp获取H264裸流并保存到mp4文件

    本篇将使用上节http://www.cnblogs.com/wenjingu/p/3977015.html中编译好的库文件通过rtsp获取网络上的h264裸流并保存到mp4文件中. 1.VS2010建 ...

  7. you need to be root to perform this command

    在linux 终端执行某条命令时 提示一下错误 you need to be root to perform this command 是提示要获取root权限 输入su 回车输入密码 即可解决 参考 ...

  8. Npoi将excel数据导入到sqlserver数据库

    /// <summary> /// 将excel导入到datatable /// </summary> /// <param name="filePath&qu ...

  9. MVC-controller随笔

    初识MVC-controller随笔 之前用的一些其他框架,也没有系统性的学习MVC框架.最近才开始接触,给大家简单的分享一下经验. 1    MVC的核心就是Controller(控制器),它负责处 ...

  10. C#多线程编程系列(一)- 简介

    目录 系列大纲 一.前言 二.目录结构 四.章节结构 五.相关链接 系列大纲 目前只整理到第二章,线程同步,笔者后面会慢慢更新,争取能把这本书中精华的知识都分享出来. C#多线程编程系列(一)- 简介 ...