Java8 流式递归树形菜单

Web端常用界面 树形菜单

    • 1. 说明
    • 2. 表设计
    • 3. 普通递归
    • 4. 流式递归语法糖

1. 说明

树形菜单在web后台管理系统, 权限管理中基本上很容易见到。如:csdn的个人后台管理系统。

只不过这个目录只有两层。三层的如下:

甚至可以套n层。


为什么要递归?

因为数据库表的设计,菜单会用一张表设计。菜单表的两个关键列,主键id和其父级id。使用父级id引用主键id 来作为父级菜单。即主键自关联。

2. 表设计

create table acl_permission
(id               char(19)            default '' not null comment '编号' primary key,pid              char(19)            default '' not null comment '所属上级',name             varchar(20)         default '' not null comment '名称',type             tinyint(3)          default 0  not null comment '类型(1:菜单,2:按钮)',permission_value varchar(50)         null comment '权限值',path             varchar(100)        null comment '访问路径',component        varchar(100)        null comment '组件路径',icon             varchar(50)         null comment '图标',status           tinyint             null comment '状态(0:禁止,1:正常)',is_deleted       tinyint(1) unsigned default 0  not null comment '逻辑删除 1(true)已删除, 0(false)未删除',gmt_create       datetime            null comment '创建时间',gmt_modified     datetime            null comment '更新时间'
)comment '权限';

实体类

package top.bitqian.rye.acl.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;import java.io.Serializable;
import java.util.Date;
import java.util.List;import lombok.Data;/*** 权限* * @author echo lovely* @date 2021-01-21 19:31:47*/
@Data
@TableName("acl_permission")
public class PermissionEntity implements Serializable {private static final long serialVersionUID = 1L;/*** 编号*/@TableIdprivate String id;/*** 所属上级*/private String pid;/*** 名称*/private String name;/*** 类型(1:菜单,2:按钮)*/private Integer type;/*** 权限值*/private String permissionValue;/*** 访问路径*/private String path;/*** 组件路径*/private String component;/*** 图标*/private String icon;/*** 状态(0:禁止,1:正常)*/private Integer status;/*** 逻辑删除 1(true)已删除, 0(false)未删除*/@TableField(fill = FieldFill.INSERT)private Integer isDeleted;/*** 创建时间*/@TableField(fill = FieldFill.INSERT)private Date gmtCreate;/*** 更新时间*/@TableField(fill = FieldFill.INSERT_UPDATE)private Date gmtModified;/*** 等级 根节点为0*/@TableField(exist = false)private String level;/*** 子级结点*/@TableField(exist = false)private List<PermissionEntity> children;}

3. 普通递归

   @Testvoid contextLoad1() {// 表中所有数据List<PermissionEntity> list = permissionService.list();List<PermissionEntity> nodeList = new ArrayList<>();for (PermissionEntity item : list) {if ("1".equals(item.getPid())) {// 一级父节点nodeList.add(item);// 为每个父结点设置 childrenitem.setChildren(collectTreeData(item, list));}}nodeList.forEach(System.out::println);}/**** @param permission 每个父级结点* @param list 所有数据* @return 封装好的数据 子节点*/private List<PermissionEntity> collectTreeData(PermissionEntity permission, List<PermissionEntity> list) {List<PermissionEntity> tmpList = new ArrayList<>();// 遍历所有元素for (PermissionEntity item : list) {// 找到子节点if (item.getPid().equals(permission.getId())) {// 将儿子收集tmpList.add(item);// 继续递归collectTreeData(item, list);}}// 设置父级结点的儿子permission.setChildren(tmpList);return tmpList;}

4. 流式递归语法糖

    public List<PermissionEntity> getMenuTree() {// 所有树形菜单List<PermissionEntity> list = this.list();// pid = 1 的根节点List<PermissionEntity> nodeList = list.stream().filter(r -> "1".equals(r.getPid())).collect(Collectors.toList());// 为 pid=1 设置子节点。递归。return nodeList.stream().peek(r -> {r.setLevel("0");// 为每个根结点 设置 childrenList<PermissionEntity> dataList = collectTreeData(r, list);r.setChildren(dataList);}).collect(Collectors.toList());}private List<PermissionEntity> collectTreeData(PermissionEntity permission, List<PermissionEntity> list) {return list.stream().filter(r -> r.getPid().equals(permission.getId())).peek(r -> {// set value..r.setChildren(collectTreeData(r, list));}).collect(Collectors.toList());}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

catia钣金根据线段折弯_折弯大神分析钣金折弯下刀顺序

相关阅读&#xff1a;钣金折弯设计要诀&#xff0c;这就是钣金设计界的武功秘籍solidworks在钣金中折弯系数表如何设置折弯系数统计表及公司正在使用的系数表工厂在用折弯工艺规范&#xff01;折弯机模具如何选用&#xff1f;不是不能折&#xff0c;是你折弯刀不全&#xff0c;…

前端学习(1313):get请求参数

//创建网站服务器模板 const http require(http); //内置模块 const url require(url); //网站服务器对象 const app http.createServer(); //客户端有请求 app.on(request, (req, res) > {//获取请求方式//console.log(req.method);//获取请求地址//console.log(req.url…

cmd pc如何开多个微信_抖音打击刷赞刷粉,240多个百万粉丝大V被封;微信PC版再更新...

1. 微信PC版更新&#xff0c;支持在小程序中使用微信支付新榜讯 12月19日&#xff0c;微信PC端推出内测版&#xff0c;新版本支持以下新功能&#xff1a;1. 新增看一看精选内容2. 新的订阅号浏览体验3. 支持在小程序中使用微信支付2. 抖音“啄木鸟2019”行动打击刷赞刷粉&#…

回溯法 -数据结构与算法

1.回溯法算法思想&#xff1a; 定义&#xff1a; 回溯法(探索与回溯法)是一种选优搜索法&#xff0c;按选优条件向前搜索&#xff0c;以达到目标。但当探索到某一步时&#xff0c;发现原先选择并不优或达不到目标&#xff0c;就退回一步重新选择&#xff0c;这种走不通就退回再…

Idea 封装Java代码片段 快速提示

title一&#xff0c;将代码片段抽取为方法二&#xff0c;将代码封装成模板 快速提示一&#xff0c;将代码片段抽取为方法 快速生成方法快捷键 。 ctrl alt m二&#xff0c;将代码封装成模板 快速提示 步骤都在下面。 博客新域名&#xff1a; https://bitqian.blog.csdn.n…

fputc会覆盖吗_蔬菜覆盖地膜有什么好处?选择什么膜好?

大棚蔬菜种植一般都会用于地膜覆盖&#xff0c;即覆膜种植。地膜覆盖可以预先种植&#xff0c;也可以是淡季栽培&#xff0c;那么具体地膜覆盖的好处是什么呢&#xff1f;让我们来看一看地膜覆盖的好处和地膜覆盖的类型。一、用地膜覆盖蔬菜的益处1、提高地温地膜覆盖的明显效果…

前端学习(1315):路由

//引入系统模块http//创建网站服务器//为网站添加请求事件 const http require(http); const url require(url); const app http.createServer();app.on(request, (req, res) > {//获取请求方式const method req.method.toLowerCase();//获取请求地址const pathname ur…

Java四大函数式接口

Java8函数式接口1. Consumer<T> 消费型接口2. Supplier <R> 供给型接口3. Function<T, R> 函数型接口4. Predicate<T> 断定型接口5. 四大接口总结函数式接口有利于lambda表达式的编写和流式计算。在Java中定义了四种函数式接口&#xff0c; Consumer …

前端学习(1316):静态资源

//创建网站服务器模板 const http require(http); const url require(url); //网站服务器对象 const app http.createServer(); const path require(path); const fs require(fs); //客户端有请求 /* const querystring require(querystring); */ app.on(request, (req, …

Linux内核源码目录说明

Linux内核源代码位于/usr/src/linux目录下&#xff0c;其结构分布如图1.3所示&#xff0c;每一个目录或子目录可以看作一个模块&#xff0c;其目录之间的连线表示“子目录或子模块”的关系。下面是对每一个目录的简单描述。 Arch 目录包括了所有和体系结构相关的核心代码。它下…

线程,进程,并发,并行

Java util concurrent 是Java工具包&#xff0c;用于并发编程的。 1. jdk8 文档 2. 进程/线程是什么&#xff1f; 进程&#xff1a; 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元&#xff0c;在传统的操作系统中&#x…

前端学习(1317):静态资源2

//创建网站服务器模板 const http require(http); const url require(url); //网站服务器对象 const app http.createServer(); const path require(path); const fs require(fs); const mime require(mime); //客户端有请求 /* const querystring require(querystring)…

制作双足机器人用易拉罐_小学生手工小制作用易拉罐做飞机模型的方法

阅读本文前&#xff0c;请您先点击上面的“蓝色字体”&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到文章了。每天都有分享&#xff0c;完全是免费订阅&#xff0c;请放心关注。注&#xff1a;本文转载自网络&#xff0c;不代表本平台立场&#xff0c;仅供读…

Lock锁实现多线程卖票

理解多线程卖票demoLock架构使用lock替代synchronized总结使用Lock 实现。Lock架构 使用lock替代synchronized import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;/*** 企业级的多线程代码* 在高内聚低耦合情况下 多线程 操作 资源类…

小程序引入的echarts过大如何解决_解决生鲜行业“获客难”的难题,教你如何妙用小程序...

近年来&#xff0c;随着生鲜食品产业的快速发展&#xff0c;大量企业和商家加入了生鲜食品的“大本营”。但大量的企业和商家也对市场产生了一定的影响&#xff0c;不少生鲜商家陷入了一个困境——难以获得客户。当生鲜食品企业面临“获客难”的困境时&#xff0c;不妨开发一个…

前端学习(1319):node.js异步编程

test,js function getMsg(callback) {setTimeout(function() {callback({msg: hello node js})}, 2000) } getMsg(function(data) {console.log(data); }); callback.js function getData(callback) {callback(123); } getData(function(n) {console.log(被调用了);console.…

docker web程序本地化_Docker-01-Docker介绍

一 什么是虚拟化在计算机中&#xff0c;虚拟化&#xff08;Virtualization&#xff09;是一种资源管理技术&#xff0c;是计算机的各种实体资源&#xff0c;如服务器&#xff0c;网络&#xff0c;内存及存储等&#xff0c;予以抽象&#xff0c;转换后呈现出来&#xff0c;打破实…

tk-mapper 生成器

tk-mapper生成代码代码&#xff0c;项目地址如何使用1. 生成实体类, XML文件, Mapper接口。 2. 版本相关&#xff1a;mapper&#xff1a; 3.4.1mapper-spring-boot-starter: 1.1.2mybatis-generator-core: 1.3.6 3. 这里以SpringBoot为demo, 作为一个程序&#xff0c;运行Gener…