菜单根据菜单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 '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');

第二步:引入相应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);


    }



}
原文地址:https://www.cnblogs.com/liuxiaoming123/p/8000598.html