使用Mybatis生成樹形菜單的方法詳解
開發(fā)中我們難免會遇到各種樹形結(jié)構(gòu)展示的場景。比如用戶登錄系統(tǒng)后菜單的展示,某些大型購物網(wǎng)站商品的分類展示等等,反正開發(fā)中會遇到各種樹形展示的功能,這些功能大概處理的思路都是一樣的,所以本文就總結(jié)一下樹形結(jié)構(gòu)的代碼生成,在開發(fā)的時(shí)候套用這種結(jié)構(gòu)就可以了。
好了正文開始,首先相關(guān)的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,'數(shù)據(jù)主菜單',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)數(shù)據(jù)結(jié)構(gòu)一般就是上面得那樣,只是初始化得數(shù)據(jù)按照你開發(fā)得需求初始化。
然后就是創(chuàng)建簡單得項(xiàng)目,好了那我就貼出相關(guān)得代碼,這些大家開發(fā)得時(shí)候可以根據(jù)需求進(jìn)行嵌套使用。
// 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對象了,
* 加一個(gè)children屬性,注意如果不是數(shù)據(jù)庫的字段一定要
* 加下面d額那個(gè)注解
*/
@TableField(exist=false)
private List<SysMenu> children;
}// mapper接口,很簡單沒有多余代碼
public interface SysMenuDao extends BaseMapper<SysMenu> {
}mapper 文件也是沒有多余的代碼,使用Mybatis-Plus特有的就行
其中下面的resultMap也可以去掉。
<mapper namespace="io.renren.mapper.SysMenuDao">
<!-- 可根據(jù)自己的需求,是否要使用 -->
<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、組裝成樹形結(jié)構(gòu)
//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;
}
//遞歸查找所有菜單的子菜單,主要就是用了這個(gè)遞歸查詢。
// 我也都寫了相關(guān)的注釋。
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;
}有的小伙伴可能會說,博主我們項(xiàng)目使用的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的遞歸調(diào)用
* @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()) {
// 遞歸調(diào)用
SysMenu result = getChildrens02(sysMenu2, list);
children.add(result);
}
}
sysMenu.setChildren(children);
return sysMenu;
}使用Java7的菜單樹我沒有進(jìn)行排序,Java7的排序使用起來也很簡單,相信大家開發(fā)的時(shí)候都使用過,大家可以自行完成排序。生成的樹形結(jié)構(gòu)太多我就不貼出來了肯定是正確的。
開發(fā)中就是需要這種記錄,為什么呢,當(dāng)你沒看到這篇文章你寫一個(gè)樹形結(jié)構(gòu)的代碼可能需要一天,而你點(diǎn)一下關(guān)注,后面開發(fā)中你遇到這種功能的開發(fā)一個(gè)小時(shí)應(yīng)該就能搞定并且還沒有問題,極大的提高了開發(fā)效率,領(lǐng)導(dǎo)看到你效率那么高應(yīng)該也會很高興,說不定升職加薪就在眼前。點(diǎn)點(diǎn)關(guān)注何樂而不為呢?生活中也一樣,你同樣需要記錄總結(jié),這樣你應(yīng)該也越走越順,比如你今天上班路上遇到一個(gè)坑,你記住了。下次走過這里你就會避開這個(gè)坑,路也越走越順了。
到此這篇關(guān)于使用Mybatis生成樹形菜單的方法詳解的文章就介紹到這了,更多相關(guān)Mybatis樹形菜單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA中HTML通過servlet3.0注解名提交表單到servlet類找不到頁面的問題
這篇文章主要介紹了IDEA中HTML通過servlet3.0注解名提交表單到servlet類找不到頁面的問題,本文通過場景描述及問題解析,給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Java reservedcodecachesize虛擬機(jī)參數(shù)案例詳解
這篇文章主要介紹了Java reservedcodecachesize虛擬機(jī)參數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
application.yaml與bootstrap.yaml的使用
這篇文章主要介紹了application.yaml與bootstrap.yaml的使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Java構(gòu)造代碼塊,靜態(tài)代碼塊原理與用法實(shí)例分析
這篇文章主要介紹了Java構(gòu)造代碼塊,靜態(tài)代碼塊,結(jié)合實(shí)例形式分析了Java構(gòu)造代碼塊,靜態(tài)代碼塊的功能、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04

