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”行动打击刷赞刷粉&#…

nuxt.js 配置后端的请求地址

1、在nuxt.config.js中配置 env上下文环境 81是网关所在 module.exports {env: {baseUrl: process.env.BASE_URL || http://localhost:81/api/}, }2、axios取到路径 使用 process.env.baseUrl取值. const service axios.create({baseURL: process.env.baseUrl, // api的b…

回溯法 -数据结构与算法

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…

布局总结

layout对于顺速搭建界面和适应不同的分辨率有很重要的作用&#xff0c;layout大致分成5种&#xff0c;LinearLayout ,FrameLayout , TableLayout ,RelativeLayout, AbsoluteLayout. 1.几种Layout中Item所共有的XML属性&#xff1a; (1)layout_width(2)layout_height注: (1)和…

Java四大函数式接口

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

python pandas dataframe 排序,如何按两列或更多列对python pandas中的dataFrame进行排序?...

Suppose I have a dataframe with columns a, b and c, I want to sort the dataframe by column b in ascending order, and by column c in descending order, how do I do this?解决方案As of the 0.17.0 release, the sort method was deprecated in favor of sort_values…

前端学习(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;仅供读…

怎样学好C++ ----高手的话

用一年时间如何能掌握 C &#xff1f;修改有一定 C 语言基础&#xff0c;日后想从事游戏开发等工作&#xff0c;给自己一年时间&#xff0c;能在此期间精通 C 吗&#xff1f;Milo Yip&#xff0c;游戏程序员、《游戏引擎架构》译者张麦克、什么、乘风者 等人赞同本人大约从20多…

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;不妨开发一个…