微信公众号:潇雷
当努力到一定程度,幸运自与你不期而遇。
后台管理系统是web开发必备的一个项目,因此有必要对系统的一些基本功能做个梳理,今天要看的内容是如何递归生成树形结构菜单,效果图如下:
菜单分为一级菜单、二级菜单、复杂的菜单甚至包含三级菜单和四级菜单,这些数据在表里面都是在一个菜单目录表里。
表的核心设计如下:
字段 | 名称 | 备注 |
---|---|---|
id | int | 主键id |
parent_id | int | 一级菜单为0 ,其他菜单指向父类的id |
menu_path | varchar | 资源路径 |
sort | int | 排序 |
menu_button | tinyint | 是否作为目录展示,或者隐藏等需求 |
思路比较统一:
1、首先找到菜单数据的所有数据
2、然后找到所有的一级菜单,将它的子树拼接上
3、子树也会有子菜单,需要递归拼接子树的子菜单。
首先对原先的实体类,我们需要增加一个字段存放子菜单的列表,加上注解表示该字段不在数据库中拥有。
@Override
public List<ChildMenuVO> listWithTree() {
//1、查出所有菜单
List<CategoryEntity> categoryEntities = categoryDao.selectList(null);
//2、组装成父子的树形结构
List<ChildMenuVO> childMenuVOS =treeMenu(categoryEntities);
return childMenuVOS;
}
private List<ChildMenuVO> treeMenu(List<CategoryEntity> categoryEntities) {
List<ChildMenuVO> childMenuVOS=new ArrayList<>();
for (int i = 0; i < categoryEntities.size(); i++) {
CategoryEntity categoryEntity=categoryEntities.get(i);
//如果父id为0 的话,就不执行后续方法
if(0!=categoryEntity.getParentCid().intValue()){
continue;
}
ChildMenuVO childMenuVO = new ChildMenuVO();
BeanUtils.copyProperties(categoryEntity,childMenuVO);
//递归判断 当前menu 是否有子节点,如果有则set
childMenuVO.setChild(subMenu(categoryEntity,categoryEntities));
childMenuVOS.add(childMenuVO);
}
return childMenuVOS;
}
private List<ChildMenuVO> subMenu(CategoryEntity parentMenu, List<CategoryEntity> categoryEntities) {
List<ChildMenuVO> childMenuVOS =new ArrayList<>();
//遍历所有目录
for (int i = 0; i < categoryEntities.size(); i++) {
CategoryEntity subCategory=categoryEntities.get(i);
if(subCategory.getParentCid().equals(parentMenu.getCatId())){
ChildMenuVO childMenuVO = new ChildMenuVO();
BeanUtils.copyProperties(subCategory,childMenuVO);
childMenuVO.setChild(subMenu(subCategory,categoryEntities));
childMenuVOS.add(childMenuVO);
}
}
return childMenuVOS;
}
public List<CategoryEntity> listWithTree() {
//1、查出所有菜单
List<CategoryEntity> categoryEntities = categoryDao.selectList(null);
//2、组装成父子的树形结构
//2.1 找到所有的一级分类
List<CategoryEntity> level1Menus = categoryEntities.stream().filter(categoryEntity -> {
return categoryEntity.getParentCid() == 0;
}).map(menu->{
menu.setChildren(getChildrens(menu,categoryEntities));
return menu;
}).sorted((menu1,menu2)->{
return (menu1.getSort()==null?0:menu1.getSort())-(menu2.getSort()==null?0:menu2.getSort());
})
.collect(Collectors.toList());
return level1Menus;
}
//递归找到当前菜单的子菜单
private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){
List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
return categoryEntity.getParentCid().equals(root.getCatId());
}).map(categoryEntity -> {
categoryEntity.setChildren(getChildrens(categoryEntity,all));
return categoryEntity;
}).sorted((menu1,menu2)->{
return (menu1.getSort()==null?0:menu1.getSort())-(menu2.getSort()==null?0:menu2.getSort());
}).collect(Collectors.toList());
return children;
}
不得不说java8的stream流极大的简洁了代码,后续也会记录java8的文章,效果也达到了,stream流有点像sql,可以做出排序、过滤、判断等各种简洁的操作。
今天的分享就到这里,有兴趣可以关注,后续更多内容干货敬请期待。
[本文出自天外归云的博客园]简介APP性能测试一般对以下几个方面进行测试:1.启动时间(可以通过本工具测试);2.CPU的占用(可以通过本工具测试);3.内存的占用(可以通过本工具测试);4.流量的耗用(可以通过本工具测试);5.电量的耗用(用户实际使用中感知即可)。除了可以做以上这几个专项测试外,本工具还能进行monkey测试等等...
PAT甲级2019春季题目及满分代码下载A Sexy Primes 签到题,素数不需要用筛法,直接O(sqrt(n))即可。#include<iostream>using namespace std;bool check(int a) { if (a < 2) return false; for (int i = 2; i * i <= a; i++) if (a % i == 0) retur_2019 pat春季题解
最近在bring up ak7739这颗codec的时候遇到一个spi问题。开机在spi_probe函数中调用spi_write机器就会dump,log如下:代码是这样的:同时tz那边也给了相应的权限{ QUPV3_1_SE1, QUPV3_PROTOCOL_SPI, QUPV3_MODE_GSI, AC_HLOS, FALSE, TRUE, TRUE },看这个dump的Call trace,跟dma扯上了关系,猜测应该是和buffer相关,然后将tz中bAllowFifo标志改成_qupv3l_model_gsi
用python从一个文件(.txt)中读取数据写入到另一个文件(.txt)中import osfile_list=[]#从PaddleDetection/dataset/fruit/fruit-detection/ImageSets/Main文件夹下的train.txt文件中读取数据with open(r’PaddleDetection/dataset/fruit/fruit-detection/ImageSets/Main/train.txt’) as f1:cNames = f1.readli
什么是逆向工程 MyBatis的一个主要的特点就是需要程序员自己编写sql,那么如果表太多的话,难免会很麻烦,所以mybatis官方提供了一个逆向工程,可以针对单表自动生成mybatis执行所需要的代码(包括mapper.xml、mapper.java、po..)。一般在开发中,常用的逆向工程方式是通过数据库的表生成代码。1:mybatis逆向工程开发源码:https://do..._反向工程代码下载
多线程下载主要用到http请求中的headerContent-Length:资源长度,用于确认资源的总长度,从而便于规划每个线程的任务量Range:bytes=beg1-end1;beg2-end2,用来控制下载的资源的某一部分,需要注意,这里的beg、end是前闭后闭区间。当下载的片段较小时,很容易出错,需要重试,可以使用retry模块通过注解方式实现重试,这个模块非常好用。...
CreateSpace Quick JavaScript Interview Questions Learn Frequently Asked Questions.pdf 本书描述 这本书是关于javascript中的关键概念的。这本书收集javascript面试中的一系列常见的问题...
步骤一查看路由表,抓包,验证安全!配置过后,查看R1和R2的路由表信息。现在的路由表上的信息是正常的,R3发送的欺骗路由在表中消失了,与简单验证配置的结果一致。抓包查看现象:此时不显示密码内容。_ripv2认证
英文履历 英文履历:电脑程序员[ 2006-03-28 15:39 ]一份漂亮的英文履历可以让你的求职简历增色不少。下面是一位电脑程序员的履历表,希望可以给各位程序员GGMM一点启示哦!Gang XuSouth China Computer Company23 South Xianlie RoadGuangzhou, Guangdong...
前言本文的最新内容,更新于 2020-06-19。大家完全不用担心这篇文章会过时,因为随着 VS Code 的版本更新和插件更新,本文也会随之更新。本文的最新内容,也会在GitHub上同步更新,欢迎 star。VS Code 软件实在是太酷、太好用了,越来越多的新生代互联网青年正在使用它。前端男神尤雨溪大大这样评价 VS Code:有一点你可能会感到惊讶:VS Code 这款软件本身,是用 JavaScript 语言编写的(具体请自行查阅基于 JS 的客户端开发框架 Electron)._visual studio code左侧插件出不来
题目链接:http://hihocoder.com/problemset/problem/1227题目大意:平面上有m个点,要从这m个点当中找出n个点,使得包含这n个点的圆的半径(圆心为n个点当中的某一点且半径为整数)最小,同时保证圆周上没有点。分析:枚举这m个点,以每个点为圆心找出一个符合条件的半径,然后找出这些半径中的最小值即可。至于如何找出半径,我们可以二分[-100_hihocoder 1227
很多App设置里面都会有清理缓存这个小功能,当我们app所浏览一些图片啊,或者信息,都会缓存起来,包括存在本地的一些数据,这些呢会使我们app占用的内存变大,但是会节省我们的流量使用,我们清理缓存后占用内存就会小很多,下面进行我们的代码 首先 我们要一个工具类,这个工具类是用来清理缓存的,调用里面的方法就可以public class DataCleanManager {/*** * 清除本应用..._android缓存的目的