一 提出需求
先看一下我们的需求,我们的需求是要实现下面这个页面的树形展示。使用的技术是MyBatis-plus。
二 分析需求
首先分析一下这个页面,这个页面是以树形结构的方式展示权限(资源)列表。虽然是树形展示,本质上,它还是一个表。我们可以这样定义权限(资源)表。
CREATE TABLE `sys_resource` (
`id` varchar(30) NOT NULL,
`name` varchar(50) NOT NULL,
`parent_id` varchar(30) DEFAULT NULL,
`type` int(1) NOT NULL DEFAULT '0',
`url` varchar(100) DEFAULT NULL,
`permission` varchar(50) DEFAULT NULL,
`color` varchar(10) DEFAULT NULL,
`icon` varchar(30) DEFAULT NULL,
`sort` int(11) NOT NULL DEFAULT '0',
`verification` tinyint(1) NOT NULL DEFAULT '0',
`create_date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
看上去,还是有点抽象,我们拿表数据说话。
我们分析一下这个表。其中绿色标识出来的是一级节点。红色标识出来的是二级节点,其它都是三级节点。一级节点和二级节点是通过parent_id进行关联,二级节点和三级节点也是通过parent_id进行关联。
关于不同级别节点的关联关系,上面这个表格看得不是太清楚。我们看下面这个图就比较清楚了。
我们需要关注的是12行的id列。19到21行,以及24到27行的parent_id列。也就是绿色标识的地方。这个是反映“用户管理”二级节点和三级节点的关系,它们是通过parent_id进行关联的。
数据库分析到这里,下面我们最后分析代码。
三 代码分析
这里给出最关键的二段代码。
1 查询入口函数
@Override
public List<SysResource> list() {
EntityWrapper<SysResource> wrapper = new EntityWrapper<>();
wrapper.eq("parent_id", 0)
.or()
.isNull("parent_id")
.orderBy("sort");
// 得到一级节点资源列表
List<SysResource> resources = this.selectList(wrapper);
if (resources != null && resources.size() > 0) {
resources.forEach(this::findAllChild);
}
return resources;
}
2 递归查询函数findAllChild
public void findAllChild( SysResource resource ) {
EntityWrapper<SysResource> wrapper = new EntityWrapper<>();
wrapper.eq("parent_id", resource.getId()).orderBy("sort");
// 首次进入这个方法时,查出的是二级节点列表
// 递归调用时,就能依次查出三、四、五等等级别的节点列表,
// 递归能实现不同节点级别的无限调用,这个层次不易太深,否则有性能问题
List<SysResource> resources = this.selectList(wrapper);
resource.setChildren(resources);
if (resources != null && resources.size() > 0) {
resources.forEach(this::findAllChild);
}
}
这两段代码都用到了MyBatis-plus的功能,就是这样简洁,两段代码完成了树形结构的封装。注释在代码中写得很详细。
以“首页”这个节点为例,我们可以通过调试以及查数据库的方法跟踪一下过程。
第一步:查询一级节点语句以及结果如下
SELECT id AS id,`name`,parent_id AS parentId,`type`,url,permission,color,icon,sort,verification,create_date AS createDate
FROM sys_resource WHERE (parent_id = 0 OR parent_id IS NULL) ORDER BY sort
+---------------------+--------------+----------+------+-----------+------------+---------+------------------+------+--------------+---------------------+
| id | name | parentId | type | url | permission | color | icon | sort | verification | createDate |
+---------------------+--------------+----------+------+-----------+------------+---------+------------------+------+--------------+---------------------+
| 987977834901315586 | 首页 | NULL | 0 | /home | home | #19BE6B | ios-home-outline | -1 | 1 | 2018-04-22 16:54:06 |
| 1259381996845158401 | 业务管理 | NULL | 0 | /business | business | #19BE6B | | 0 | 1 | 2020-05-10 15:16:21 |
| 987981277195968513 | 系统设置 | NULL | 0 | /system | system | #19BE6B | ios-gear | 0 | 1 | 2018-04-22 17:07:46 |
+---------------------+--------------+----------+------+-----------+------------+---------+------------------+------+--------------+---------------------+
3 rows in set (0.00 sec)
下面这个结果是调试时打印出的一级节点“首页”。
SysResource(id=987977834901315586, name=首页, parentId=null, type=0, url=/home, permission=home, color=#19BE6B, icon=ios-home-outline, sort=-1,
verification=true, createDate=Sun Apr 22 16:54:06 CST 2018, children=null)
第二步: 查询一级节点“首页”的二级节点语句以及结果如下
SELECT id AS id,`name`,parent_id AS parentId,`type`,url,permission,color,icon,sort,verification,create_date AS createDate
FROM sys_resource WHERE (parent_id = '987977834901315586') ORDER BY sort ;
+---------------------+--------+--------------------+------+-------------+------------+---------+------+------+--------------+---------------------+
| id | name | parentId | type | url | permission | color | icon | sort | verification | createDate |
+---------------------+--------+--------------------+------+-------------+------------+---------+------+------+--------------+---------------------+
| 1001315563194589185 | 首页 | 987977834901315586 | 0 | /home/index | home_index | #19BE6B | | 0 | 0 | 2018-05-29 12:13:28 |
+---------------------+--------+--------------------+------+-------------+------------+---------+------+------+--------------+---------------------+
1 row in set (0.00 sec)
注意结果中此首页非彼首页,虽然名字一样,但完全是两条不同的记录。注意id号不一样哦。
下面这个结果是调试时打印出的二级节点“首页”,二级节点“首页”很惨,没有孩子。
SysResource(id=1001315563194589185, name=首页, parentId=987977834901315586, type=0, url=/home/index, permission=home_index, color=#19BE6B, icon=, sort=0,
verification=false, createDate=Tue May 29 12:13:28 CST 2018, children=null)
第三步:查询二级“首页”节点的三级节点语句以及结果如下
SELECT id AS id,`name`,parent_id AS parentId,`type`,url,permission,color,icon,sort,verification,create_date AS createDate
FROM sys_resource WHERE (parent_id = '1001315563194589185') ORDER BY sort
Empty set (0.00 sec)
查询结果为空,因为二级“首页”根本就没三级节点。
分析到这里,就算完了,大家好好揣摩一下,也可试着调试下代码。
最后再看一下封装后返回的resources到底长得怎么样。
来源:oschina
链接:https://my.oschina.net/u/4297638/blog/4274284