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

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. 前端福利之overflow-scrol 怎么隐藏滚动条(转)

    最近用vue写wap站的时候遇到了微信打开页面滚动条无法隐藏的问题. 对于隐藏滚动条,我们最常用的方法首先是: 1.使用以下CSS可以隐藏滚动条: .container::-webkit-scroll ...

  2. Intel Cyclone SoC FPGA介绍

    3.1 Intel Cyclone SoC FPGA介绍 3.1.1 SoC FPGA的基本概念 Intel Cyclone V SoC FPGA是Intel PSG(原Altera)于2013年发布 ...

  3. 编译语言 vs 解释语言

    编译语言 vs 解释语言 阅读:  评论:  作者:Rybby  日期:  来源:rybby.com 一直以为,编译语言的性能绝对比解释语言快,因为就理论而言,解释语言要一边解释(将脚本语言翻译成计算 ...

  4. Java Float类型 减法运算时精度丢失问题

    package test1; public class Test2 { /*** @param args*/public static void main(String[] args) {   Flo ...

  5. Tips and Examples Using FNDLOAD (DOC ID 735338.1)

    In this Document Goal Solution Some Tips About FNDLOAD Some sample examples Diagnostics & Utilit ...

  6. 咏南中间件修正了一处BUG,调用中间件插件会报:非法访问

    咏南中间件修正了一处BUG,调用中间件插件会报:非法访问将以下方法修改成如下的代码即可function TServerMethods1.GetSvrData(const accountNo, defi ...

  7. B/S 类项目改善的一些建议

    body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...

  8. CVE-2018-7600 Drupal核心远程代码执行漏洞分析

    0x01 漏洞介绍 Drupal是一个开源内容管理系统(CMS),全球超过100万个网站(包括政府,电子零售,企业组织,金融机构等)使用.两周前,Drupal安全团队披露了一个非常关键的漏洞,编号CV ...

  9. swagger简单配置

    第一步: 在nuget.org中查找Swashbuckle并下载 在nuget.org中查找Swagger.net.UI,并下载 第二步: 下载完之后,App_Start多了三个文件 Swagger. ...

  10. JSON is undefined. Infopath Form People Picker in SharePoint 2013

    After some analysis, we found that, this is a known defect with the Microsoft and it is being fixed ...