开发中我们难免会遇到各种树形结构展示的场景。比如用户登录系统后菜单的展示,某些大型购物网站商品的分类展示等等,反正开发中会遇到各种树形展示的功能,这些功能大概处理的思路都是一样的,所以本文就总结一下树形结构的代码生成,在开发的时候套用这种结构就可以了。

好了正文开始,首先相关的SQL脚本【MYSQL】提供给你(包吃包住包SQL)【如果巅峰留不住那就进厂包吃住】。

DDL语句:

CREATE TABLE `student`.`SYS_menu`(
`ID` INT(10) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(200) NOT NULL,
`permissions` VARCHAR(1000),
`url` VARCHAR(200),
`description` VARCHAR(2000),
`icon_cls` VARCHAR(2000),
`pid` INT(10),
`status` INT(2),
`resource_type` INT(2),
`sort` INT(6),
`create_time` TIMESTAMP,
`update_time` TIMESTAMP,
PRIMARY KEY (`ID`)
) ENGINE=INNODB CHARSET=utf8;

初始化语句:

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('主菜单',NULL,NULL,'数据主菜单',NULL,0,1,1,NOW(),NOW(),NULL) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1',NULL,NULL,'菜单1',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='主菜单') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2',NULL,NULL,'菜单2',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='主菜单') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3',NULL,NULL,'菜单3',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='主菜单') a ),1,1,NOW(),NOW(),3) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1.1',NULL,NULL,'菜单1的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单1') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1.2',NULL,NULL,'菜单1的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单1') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1.3',NULL,NULL,'菜单1的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单1') a ),1,1,NOW(),NOW(),3) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2.1',NULL,NULL,'菜单2的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单2') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2.2',NULL,NULL,'菜单2的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单2') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2.3',NULL,NULL,'菜单2的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单2') a ),1,1,NOW(),NOW(),3) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3.1',NULL,NULL,'菜单3的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单3') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3.2',NULL,NULL,'菜单3的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单3') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3.3',NULL,NULL,'菜单3的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单3') a ),1,1,NOW(),NOW(),3) 

数据结构一般就是上面得那样,只是初始化得数据按照你开发得需求初始化。

然后就是创建简单得项目,好了那我就贴出相关得代码,这些大家开发得时候可以根据需求进行嵌套使用。

// entity
@Data
@TableName("sys_menu")
public class SysMenu implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private Integer id;
private String name;
private String permissions;
private String url;
private String description;
private String iconCls;
private Integer pid;
private Integer status;
private Integer resourceType;
private Integer sort;
private Date createTime;
private Date updateTime;
/**
* 此处为了简单我就不新建DTO对象了,
* 加一个children属性,注意如果不是数据库的字段一定要
* 加下面d额那个注解
*/
@TableField(exist=false)
private List<SysMenu> children; }
// mapper接口,很简单没有多余代码
public interface SysMenuDao extends BaseMapper<SysMenu> { }
// mapper 文件也是没有多余的代码,使用Mybatis-Plus特有的就行
// 其中下面的resultMap也可以去掉。
<mapper namespace="io.renren.mapper.SysMenuDao">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="io.renren.domain.SysMenu" id="sysMenuMap">
<result property="id" column="ID"/>
<result property="name" column="name"/>
<result property="permissions" column="permissions"/>
<result property="url" column="url"/>
<result property="description" column="description"/>
<result property="iconCls" column="icon_cls"/>
<result property="pid" column="pid"/>
<result property="status" column="status"/>
<result property="resourceType" column="resource_type"/>
<result property="sort" column="sort"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>
// service 主要的逻辑代码就在这里。
public interface SysMenuService extends IService<SysMenu> { List<SysMenu> getMenuTree();
} @Service("sysMenuService")
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenu> implements SysMenuService { @Autowired
private SysMenuDao sysMenuDao ;
@Override
public List<SysMenu> getMenuTree() {
//查询出所有菜单
List<SysMenu> sysMenus = sysMenuDao.selectList(null);
//2、组装成树形结构
//2.1)、找到所有的一级菜单
List<SysMenu> level1Menus = sysMenus.stream().filter(sysMenu ->
sysMenu.getPid() == 0
).map((menu) -> {
menu.setChildren(getChildrens(menu, sysMenus));
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<SysMenu> getChildrens(SysMenu root, List<SysMenu> all) { List<SysMenu> children = all.stream().filter(sysMenu -> {
return sysMenu.getPid() == root.getId();
}).map(sysMenu -> {
//1、找到子菜单
sysMenu.setChildren(getChildrens(sysMenu, all));
return sysMenu;
}).sorted((menu1, menu2) -> {
//2、菜单的排序
return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
}).collect(Collectors.toList());
return children;
}

有的小伙伴可能会说,博主我们项目使用的jdk7 。上面的代码使用不了啊,这篇文章对我来说不合适啊。好了安排上,既然写文章我就要写的明明白白,下面是不使用Stream流完成的功能。

List<SysMenu> getMenuTreeVerLowJava8() ;

   @Override
public List<SysMenu> getMenuTreeVerLowJava8() {
List<SysMenu> sysMenus = sysMenuDao.selectList(null);
List<SysMenu> tree = new ArrayList<>();
for (SysMenu sysmenu: sysMenus) {
if (sysmenu.getPid()==0){
tree.add(getChildrens02(sysmenu,sysMenus)) ;
}
}
return tree;
} /**
* 不使用stream的递归调用
* @param list
* @return
*/
private SysMenu getChildrens02(SysMenu sysMenu, List<SysMenu> list) { List<SysMenu> children = new ArrayList<SysMenu>();
for (SysMenu sysMenu2 : list) {
if (sysMenu2.getPid() == sysMenu.getId()) {
// 递归调用
SysMenu result = getChildrens02(sysMenu2, list);
children.add(result);
}
}
sysMenu.setChildren(children);
return sysMenu;
}

使用Java7的菜单树我没有进行排序,Java7的排序使用起来也很简单,相信大家开发的时候都使用过,大家可以自行完成排序。生成的树形结构太多我就不贴出来了肯定是正确的。

开发中就是需要这种记录,为什么呢,当你没看到这篇文章你写一个树形结构的代码可能需要一天,而你点一下关注,后面开发中你遇到这种功能的开发一个小时应该就能搞定并且还没有问题,极大的提高了开发效率,领导看到你效率那么高应该也会很高兴,说不定升职加薪就在眼前。点点关注何乐而不为呢?生活中也一样,你同样需要记录总结,这样你应该也越走越顺,比如你今天上班路上遇到一个坑,你记住了。下次走过这里你就会避开这个坑,路也越走越顺了。

11

使用Mybatis生成树形菜单-适用于各种树形场景的更多相关文章

  1. 雷林鹏分享:jQuery EasyUI 树形菜单 - 创建异步树形菜单

    jQuery EasyUI 树形菜单 - 创建异步树形菜单 为了创建异步的树形菜单(Tree),每一个树节点必须要有一个 'id' 属性,这个将提交回服务器去检索子节点数据. 创建树形菜单(Tree) ...

  2. 雷林鹏分享:jQuery EasyUI 树形菜单 - 创建复杂树形网格

    jQuery EasyUI 树形菜单 - 创建复杂树形网格 树形网格(TreeGrid)可以展示有限空间上带有多列和复杂数据电子表格.本教程将演示如何将表格数据排列在分割的网格和多行表头中,以便组织共 ...

  3. 雷林鹏分享:jQuery EasyUI 树形菜单 - 创建基础树形网格

    jQuery EasyUI 树形菜单 - 创建基础树形网格 树形网格(TreeGrid)组件从数据网格(DataGrid)继承,但是允许在行之间存在父/子节点关系.许多属性继承至数据网格(DataGr ...

  4. JQuery实现动态生成树形菜单

    jQuery实现动态生成树形菜单 有一个需求:菜单导航条需要依据不同的权限动态提取出来.计划是将功能模块与用户权限之间的关系保持到一个配置表中.所以功能菜单的话就需要动态提取出来再显示.借助jquer ...

  5. JavaScript生成树形菜单(递归算法)

    1.最终效果图(这里仅为实现算法,并加载至页面,不做任何css界面优化) 注释:本示例包含三级目录菜单,但实际上可支持N级(可使用该代码自行测试) 2.数据源 菜单信息一般来源于数据库中数据表,且为自 ...

  6. WEB开发中前后台树形菜单的展示设计

    在WEB开发中经常需要进行树形菜单的展示,本例通过不同角度的总结了如下三种实现方式: 通过JS的递归实现前端菜单DOM的动态创建 通过JSP的include指令结合JSTL表达式语言递归实现菜单的展示 ...

  7. jquery树形菜单完整代码

    本实例实现了树形的动态菜单,兼容IE8,火狐,Chrome等浏览器.使用了jQuery的toggle() 方法.效果和代码如下: <!DOCTYPE html PUBLIC "-//W ...

  8. 实用的树形菜单控件tree

     jQuery plugin: Treeview  这个插件能够把无序列表转换成可展开与收缩的Tree. jQuery plugin: Treeview  jQuery  jstree  jsTree ...

  9. Android 多级树形菜单

    在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单... ...

  10. html树形菜单控件

    html树形菜单控件  链接 http://www.ithao123.cn/content-713974.html         jQuery plugin: Treeview  这个插件能够把无序 ...

随机推荐

  1. Sping Security前后端分离两种方案

    前言 本篇文章是基于Spring Security实现前后端分离登录认证及权限控制的实战,主要包括以下四方面内容: Spring Seciruty简单介绍: 通过Spring Seciruty实现的基 ...

  2. Windows的压缩文件夹(zip/cab)

    https://weibo.com/1114096665/DtHXgvnva #windows10# 硬要把zip.cab文件当文件夹,不爽怎么解决? 删除注册表 "HKEY_CLASSES ...

  3. 第三章3.3 selenium基础

    seleniumIDE:是一款可以实现录制回放的操作:存在可视化窗口进行录制回放操作:它属于firefox(chrome)浏览器的插件;安装方式:两种 : 1.下载安装包离线安装2.在线安装 注意:不 ...

  4. VUE插值语法

    目录 基本使用 基本使用 在body中创建一个标签,一般使用div,定义好id后,在script中进行定义,在前台使用{{变量}}的形式进行调用,语法如下: <!DOCTYPE html> ...

  5. python类详解

    类封装 继承 多态一静态属性1.静态变量和静态方法都属于类的静态成员,它们与普通的成员变量和成员方法不同,静态变量和静态方法只属于定义它们的类,而不属于某一个对象.2.静态变量和静态方法都可以通过类名 ...

  6. pandas之窗口函数

    为了能更好地处理数值型数据,Pandas 提供了几种窗口函数,比如移动函数(rolling).扩展函数(expanding)和指数加权函数(ewm).窗口函数应用场景非常多.举一个简单的例子:现在有 ...

  7. 四月二十二日java基础知识

    1.利用接口实现类的多重继承:java语言中接口的主要作用是可以帮助实现类似于类的多重继承功能.多重继承,是指一个子类可以有一个以上的直接父类,该子类可以直接继承它所有父类的非私有成员.2.一个类实现 ...

  8. Python GDAL库在Anaconda环境中的配置

      本文介绍在Anaconda环境下,安装Python中栅格.矢量等地理数据处理库GDAL的方法.   需要注意的是,本文介绍基于conda install命令直接联网安装GDAL库的方法:这一方法有 ...

  9. docker 容器操作、应用部署、mysql,redis,nginx、迁移与备份、Dockerfile

    容器操作 # 启动容器 docker start 容器id # 停止容器 docker stop 容器id # 文件拷贝 先创建文件 mkdir:文件夹 vi vim touch:文件 # 容器的文件 ...

  10. 「学习笔记」重修 FHQ-treap

    无旋 treap 的操作方式使得它天生支持维护序列.可持久化等特性. 无旋 treap 又称分裂合并 treap.它仅有两种核心操作,即为 分裂 与 合并.通过这两种操作,在很多情况下可以比旋转 tr ...