最近要开发一个菜单接口,结构是父菜单下面有子菜单,子菜单下面还有子菜单,子菜单可以无限下去,要实现树形结构返给前端。

数据表设计

CREATE TABLE `platform_menu`  (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单id',`menu_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单名称',`menu_value` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单值(前端路由)',`parent_id` bigint NULL DEFAULT NULL COMMENT '上级菜单id',`parent_path` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '菜单全路径(用/隔开)',`func_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '功能类型(0菜单1按钮2区块)',`order_num` int NULL DEFAULT NULL COMMENT '排序',`icon` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标',`created_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',`created_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',`updated_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',`updated_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单信息 ' ROW_FORMAT = Dynamic;

创建树形结构工具类

import cn.hutool.core.collection.CollUtil;
import org.apache.commons.compress.utils.Lists;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;/*** @author ws* @date 2021/9/5*/
public class BaseTreeHelper {/*** @param <T> 节点类型* @param <E> 节点id的类型* @return 树形结构列表* @author ws* @date 2021/9/5* 根据所有树节点列表,生成含有所有树形结构的列表**/public static <T extends TreeNode<E, T>, E> List<T> generateTrees(List<T> data) {if (CollUtil.isEmpty(data)) {return Lists.newArrayList();}//将集合中所有数据按照父Id进行分组,放入Map中,Map<parntId, List<T>>Map<String, List<T>> groupByParentIdMap = data.stream().collect(Collectors.groupingBy(item -> item.root() ? "" : Objects.toString(item.getPid())));//将集合中所有数据以数据Id为key,放入Map中,Map<id,T>Map<String, T> dataMap = data.stream().collect(Collectors.toMap(item -> item.getId().toString(), t -> t));List<T> resp = Lists.newArrayList();//遍历数据,将子节点放入对应父节点Children属性中groupByParentIdMap.forEach((parentId, values) -> {if (dataMap.containsKey(parentId)) {List<T> child = dataMap.get(parentId).getChildren();if (CollUtil.isEmpty(child)) {child = Lists.newArrayList();}child.addAll(values);dataMap.get(parentId).setChildren(child);} else {resp.addAll(values);}});return resp;}/*** @param parent 父节点* @param <T>    实际节点类型* @return 叶子节点* @author ws* @date 2021/9/5* 获取指定树节点下的所有叶子节点**/public static <T extends TreeNode<E, T>, E> List<T> getLeafs(T parent) {List<T> leafs = new ArrayList<>();fillLeaf(parent, leafs);return leafs;}/*** @param parent 父节点* @param leafs  叶子节点列表* @param <T>    实际节点类型* @author ws* @date 2021/9/5* 将parent的所有叶子节点填充至leafs列表中**/private static <T extends TreeNode<E, T>, E> void fillLeaf(T parent, List<T> leafs) {List<T> children = parent.getChildren();// 如果节点没有子节点则说明为叶子节点if (CollUtil.isEmpty(children)) {leafs.add(parent);return;}// 递归调用子节点,查找叶子节点for (T child : children) {fillLeaf(child, leafs);}}
}

import java.util.List;/*** 树节点父类,所有需要使用{@linkplain BaseTreeHelper}工具类形成树形结构等操作的节点都需要实现该接口** @param <T> 节点id类型* @author huangke*/
public interface TreeNode<T, E> {/*** 获取节点id** @return 树节点id*/T getId();/*** 获取该节点的父节点id** @return 父节点id*/T getPid();/*** 是否是根节点** @return true:根节点*/Boolean root();/*** 设置节点的子节点列表** @param children 子节点*/void setChildren(List<E> children);/*** 获取所有子节点** @return 子节点列表*/List<E> getChildren();
}

创建UserMenusVo对象,里面可以只写需要返回的属性字段就行。

import com.knight.common.core.utils.tree.TreeNode;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;/*** @author ws*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserMenusVo implements TreeNode<Long, UserMenusVo> {private static final long serialVersionUID = 1L;/*** id*/@ApiModelProperty("菜单id")private Long id;/*** 菜单名称*/@ApiModelProperty("菜单名称")private String name;/*** 菜单值(前端路由)*/@ApiModelProperty("菜单值")private String menuValue;/*** 上级菜单id*/@ApiModelProperty("上级菜单")private Long pid;/*** 菜单全路径(用/隔开)*/@ApiModelProperty("菜单全路径")private String parentPath;/*** 功能类型(0菜单1按钮2区块)*/@ApiModelProperty("功能类型")private String funcType;/*** 排序*/@ApiModelProperty("排序")private Integer orderNum;/*** 图标*/@ApiModelProperty("图标")private String icon;@ApiModelProperty("子菜单")private List<UserMenusVo> children;@Override@ApiModelProperty("父节点")public Boolean root() {return pid == null;}
}

controller,返回的pid就是parentId。

public Result<List<UserMenusVo>> listMenuAll() {
//查询所有菜单List<UserMenusVo> menus = listMenuAll();
//返回树形结构return Result.ok(BaseTreeHelper.generateTrees(menus));}public List<UserMenusVo> listMenuAll() {List<PlatformMenu> menus = baseService.list();List<UserMenusVo> userMenus = new ArrayList<>();menus.forEach(menu -> {UserMenusVo userMenu = UserMenusVo.builder().build();BeanUtil.copyProperties(menu, userMenu);userMenu.setName(menu.getMenuName());userMenu.setPid(menu.getParentId());userMenus.add(userMenu);});return userMenus;}

java实现树形菜单相关推荐

  1. java构建树形菜单(多级菜单)

    一.树形结构简介 首先构建树形结构,我们得知道什么是树形结构,如下图所示. 如上图所示,可以看出有四级菜单,这就是树形结构. 如果想更深入的了解树形结构,建议去查询数据结构中关于树的章节. 二.树形菜 ...

  2. java递归实现多级菜单栏_Java构建树形菜单以及支持多级菜单的实例代码

    这篇文章主要介绍了Java构建树形菜单的实例代码(支持多级菜单),非常不错,具有参考借鉴价值,需要的朋友可以参考下 效果图:支持多级菜单. 菜单实体类: public class Menu { // ...

  3. java树形菜单_Java构建树形菜单

    构建树形菜单 效果图:支持多级菜单. 菜单实体类: public class Menu { // 菜单id private String id; // 菜单名称 private String name ...

  4. java中遍历树形菜单,你可能不知道还有这样的方法

    版权声明:本文为CSDN博主「穆雄雄」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/qq_34137397/ ...

  5. java实现遍历树形菜单方法——实体类VoteTree

    package org.entity;import java.util.ArrayList; import java.util.List;/*** * * 项目名称:testTree * 类名称:Vo ...

  6. java实现遍历树形菜单方法——设计思路【含源代码】

    开发工具:MyEclipse 10 后台框架:Hibernate + Struts2 数据库:Oracle 11g 前台框架:EasyUi 浏览器:谷歌 在开发中我们经常会遇到左边是树形菜单,右边是一 ...

  7. easyUI前端框架的tree(树)前台展示(树形菜单二)——java

    转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165. 本文出自 不怕报错 就怕不报错的小猿猿 的博客 easyUI前端框架的t ...

  8. Java树形菜单的构建、遍历以及获取树形菜单的Id集合List

    项目的开发过程中经常遇到树形菜单构建,遍历的情况,于是记录一下以便查阅. 1创建一个Menu类,简单起见,这里我只使用了id和pid的字段 package com.huato.tree.menu;im ...

  9. Java GUI编程:swing JTree实现树形菜单代码示例

    package com.zxl;import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode;/*** @Descripti ...

  10. java创建多级xml树_月光软件站 - 编程文档 - Java - 用XSL与XML实现多级树形菜单

    XSL语言功能强大而奇妙.从前面的例子中,我们可以初步了解到,一个xsl文档中使用了很多类似"xsl:xxxxx"这样的标签,这些标签就是xsl语言的部分.一个xsl文档至少是由一 ...

最新文章

  1. 【怎样写代码】参数化类型 -- 泛型(二):泛型的优点
  2. RabbitMQ(一):RabbitMQ快速入门
  3. Markdown使用文档
  4. P2480 [SDOI2010]古代猪文
  5. python 多进程使用总结
  6. Darknet_Yolov4实战(二)_安装OpenCV
  7. Java9都快发布了,Java8的十大新特性你了解多少呢?
  8. 用组策略发布软件的简单解决办法
  9. 量子计算机全世界最新进展,谷歌或于明年公布全球最强大量子计算机
  10. 女生做产品经理好吗_产品经理如何做产品架构设计
  11. Spring Boot 高效入门实战
  12. php get 传循环出来的参数_简单学习PHP中的反射
  13. HDU 5974 2016ICPC大连 D: A Simple Math Problem
  14. python c++ 批量命名文件夹内的图像
  15. Python爬虫系列(五)360图库美女图片下载
  16. 转载 计算广告 03
  17. 20190301小中大
  18. 为什么站点访问慢?请收好这份 Web 服务器性能提升的总结
  19. 如何浏览与下载全球免费的地图高分辨率(亚米级)的遥感影像?
  20. 阿里云ECS云服务器实例重置-更换操作系统

热门文章

  1. Python项目实战:爬取糗事百科最热门的内涵搞笑段子
  2. python全栈工程师熟练的技巧
  3. JDK1.8和JDK1.7的HashMap源码分析以及线程不安全问题
  4. 编码,隐匿在计算机软硬件背后的语言读书笔记(1)
  5. 我的IOS端SIP电话开发历程
  6. vue中的key有什么作用?(key的内部原理)
  7. 秀米排版,从入门到入土(一)
  8. LSTM Networks应用于股票市场探究
  9. java敏捷开发的落地与实施_20165219 《Java程序设计》实验三(敏捷开发与XP实践)实验报告...
  10. 数据结构铁轨问题_数据结构大作业(试题题目)