- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章springboot构造树形结构数据并查询的方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
因为项目需要,页面上需要树形结构的数据进行展示(类似下图这样),因此需要后端返回相应格式的数据.
不说废话,直接开干!!! 。
我这里用的是springboot+mybatis-plus+mysql,示例的接口是查询一级权限以及二级权限、三级权限整个权限树… 。
下面是导入的maven依赖 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<
dependency
>
<
groupId
>org.springframework.boot</
groupId
>
<
artifactId
>spring-boot-starter-web</
artifactId
>
</
dependency
>
<!--数据库连接-->
<
dependency
>
<
groupId
>com.alibaba</
groupId
>
<
artifactId
>druid-spring-boot-starter</
artifactId
>
<
version
>1.1.21</
version
>
</
dependency
>
<
dependency
>
<
groupId
>mysql</
groupId
>
<
artifactId
>mysql-connector-java</
artifactId
>
</
dependency
>
<!--mybatis增强工具-->
<
dependency
>
<
groupId
>com.baomidou</
groupId
>
<
artifactId
>mybatis-plus-boot-starter</
artifactId
>
<
version
>3.4.0</
version
>
</
dependency
>
<
dependency
>
<
groupId
>org.projectlombok</
groupId
>
<
artifactId
>lombok</
artifactId
>
<
optional
>true</
optional
>
</
dependency
>
<
dependency
>
<
groupId
>cn.hutool</
groupId
>
<
artifactId
>hutool-all</
artifactId
>
<
version
>5.0.6</
version
>
</
dependency
>
|
下面是实体类Permission 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
@Data
public
class
Permission
implements
Serializable {
@TableId
private
String permissionId;
@NotNull
(message =
"权限名称不能为空"
)
private
String permissionName;
/**
* 权限标识
*/
@NotNull
(message =
"权限标识不能为空"
)
private
String permissionCode;
/**
* 父菜单ID,如果是-1就表示是一级权限菜单。
*/
@NotBlank
(message =
"父菜单ID不能为空"
)
private
String parentId;
/**
* 前端URL访问接口路径
*/
private
String path;
/**
* 排序值
*/
private
Integer sort;
/**
* 创建时间
*/
private
LocalDateTime createTime;
/**
* 更新时间
*/
private
LocalDateTime updateTime;
/**
* 0--正常 1--删除
*/
private
String delFlag;
public
Permission() {
this
.permissionId = IdUtil.simpleUUID();
}
|
树形结点类 。
1
2
3
4
5
6
7
8
9
10
11
|
@Data
public
class
TreeNode {
protected
String id;
protected
String parentId;
protected
List<TreeNode> children =
new
ArrayList<TreeNode>();
protected
boolean
hasChildren;
public
void
addTreeNode(TreeNode node){
children.add(node);
}
}
|
树形结点详细信息类 。
1
2
3
4
5
6
7
8
9
10
11
12
|
@Data
@EqualsAndHashCode
(callSuper =
true
)
public
class
PermissionTree
extends
TreeNode
implements
Serializable {
private
String permissionName;
private
String permissionCode;
private
String path;
private
Integer sort;
private
String label;
private
boolean
hasChildren;
public
PermissionTree() {
}
}
|
构建树形结点工具类(关键),在这里我用@UtilityClass注解就表示这个类中的方法都是静态方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
@UtilityClass
public
class
TreeUtil {
public
<T
extends
TreeNode> List<T> build(List<T> treeNodes, String root) {
List<T> trees =
new
ArrayList<>();
for
(T treeNode : treeNodes) {
if
(root.equals(treeNode.getParentId())) {
trees.add(treeNode);
}
for
(T node : treeNodes) {
if
(node.getParentId().equals(treeNode.getId())) {
treeNode.addTreeNode(node);
treeNode.setHasChildren(
true
);
}
}
}
return
trees;
}
/**
* 通过permission创建树形节点
*
* @param permissionList
* @param root
* @return
*/
public
List<PermissionTree> buildTree(List<Permission> permissionList, String root) {
System.out.println(Arrays.toString(permissionList.toArray()));
List<PermissionTree> treeNodeList =
new
ArrayList<>();
PermissionTree treeNode =
null
;
for
(Permission permission : permissionList) {
treeNode =
new
PermissionTree();
treeNode.setId(permission.getPermissionId());
treeNode.setPermissionName(permission.getPermissionName());
treeNode.setPath(permission.getPath());
treeNode.setSort(permission.getSort());
treeNode.setParentId(permission.getParentId());
treeNode.setLabel(permission.getPermissionName());
treeNode.setHasChildren(
false
);
treeNodeList.add(treeNode);
}
return
TreeUtil.build(treeNodeList, root);
}
}
|
响应消息主体类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/**
* 响应信息主体
*
* @param <T>
*/
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Accessors
(chain =
true
)
public
class
R<T>
implements
Serializable {
private
static
final
long
serialVersionUID = 1L;
private
int
code;
private
String msg;
private
T data;
public
int
getCode() {
return
code;
}
public
void
setCode(
int
code) {
this
.code = code;
}
public
String getMsg() {
return
msg;
}
public
void
setMsg(String msg) {
this
.msg = msg;
}
public
T getData() {
return
data;
}
public
void
setData(T data) {
this
.data = data;
}
public
static
<T> R<T> ok() {
return
restResult(
null
, CommonConstants.SUCCESS, CommonConstants.MSG_SUCCESS);
}
public
static
<T> R<T> ok(T data) {
return
restResult(data, CommonConstants.SUCCESS, CommonConstants.MSG_SUCCESS);
}
public
static
<T> R<T> ok(T data, String msg) {
return
restResult(data, CommonConstants.SUCCESS, msg);
}
public
static
<T> R<T> failed() {
return
restResult(
null
, CommonConstants.FAIL,
null
);
}
public
static
<T> R<T> failed(String msg) {
return
restResult(
null
, CommonConstants.FAIL, msg);
}
public
static
<T> R<T> failed(T data) {
return
restResult(data, CommonConstants.FAIL,
null
);
}
public
static
<T> R<T> failed(T data, String msg) {
return
restResult(data, CommonConstants.FAIL, msg);
}
private
static
<T> R<T> restResult(T data,
int
code, String msg) {
R<T> apiResult =
new
R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return
apiResult;
}
}
|
数据查询接口mapper类 。
1
2
3
4
|
@Mapper
public
interface
PermissionMapper
extends
BaseMapper<Permission>{
}
|
数据逻辑处理业务接口 。
1
2
3
4
5
6
7
8
9
10
11
12
|
public
interface
PermissionService
extends
IService<Permission> {
/**
* 构建权限树
*
* @param lazy
* @param parentId
* @return
*/
List<PermissionTree> treePermission(
boolean
lazy, String parentId);
}
|
数据逻辑处理业务接口实现类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@Service
public
class
PermissionServiceImpl
extends
ServiceImpl<PermissionMapper, Permission>
implements
PermissionService {
/**
* 构建权限树:1、不是懒加载情况,查询全部
* 2、是懒加载,根据parentId查询
*
* @param lazy
* @param parentId
* @return
*/
@Override
public
List<PermissionTree> treePermission(
boolean
lazy, String parentId) {
if
(!lazy) {
return
TreeUtil.buildTree(
baseMapper.selectList(Wrappers.<Permission>lambdaQuery().orderByAsc(Permission::getSort)),
CommonConstants.PERMISSION_ROOT_ID);
}
String parent = parentId ==
null
? CommonConstants.PERMISSION_ROOT_ID : parentId;
return
TreeUtil.buildTree(
baseMapper.selectList(Wrappers.<Permission>lambdaQuery().eq(Permission::getParentId, parent).orderByAsc(Permission::getSort)), parent
);
}
}
|
查询权限树请求接口类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@RestController
@RequestMapping
(
"/permission"
)
public
class
PermissionController {
@Autowire
private
PermissionService permissionService;
/**
* 查询权限列表,并以树状结构显示
*
* @param lazy 懒加载: false时, parentId这个参数失效, 加载所有的权限; true时, 根据parentId加载
* @param parentId
* @return
*/
@RequestMapping
(value =
"/getTree"
, method = RequestMethod.GET)
public
R getTree(
boolean
lazy, String parentId) {
return
R.ok(permissionService.treePermission(lazy, parentId));
}
}
|
表中测试数据如下(注意它的parent_id) 。
测试一:不是懒加载,查询整个权限树。 结果如下.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
{
"code"
: 0,
"msg"
:
"SUCCESS"
,
"data"
: [
{
"id"
:
"1"
,
"parentId"
:
"-1"
,
"children"
: [
{
"id"
:
"2"
,
"parentId"
:
"1"
,
"children"
: [
{
"id"
:
"3"
,
"parentId"
:
"2"
,
"children"
: [],
"hasChildren"
:
false
,
"permissionName"
:
"update"
,
"permissionCode"
:
null
,
"path"
:
null
,
"sort"
: 3,
"label"
:
"update"
,
"owned"
:
false
},
{
"id"
:
"4"
,
"parentId"
:
"2"
,
"children"
: [],
"hasChildren"
:
false
,
"permissionName"
:
"insert_role"
,
"permissionCode"
:
null
,
"path"
:
null
,
"sort"
: 4,
"label"
:
"insert_role"
,
"owned"
:
false
}
],
"hasChildren"
:
true
,
"permissionName"
:
"delete"
,
"permissionCode"
:
null
,
"path"
:
null
,
"sort"
: 2,
"label"
:
"delete"
,
"owned"
:
false
}
],
"hasChildren"
:
true
,
"permissionName"
:
"add"
,
"permissionCode"
:
null
,
"path"
:
null
,
"sort"
: 1,
"label"
:
"add"
,
"owned"
:
false
},
{
"id"
:
"5"
,
"parentId"
:
"-1"
,
"children"
: [],
"hasChildren"
:
false
,
"permissionName"
:
"role:saveRole"
,
"permissionCode"
:
null
,
"path"
:
"/role/saveRole"
,
"sort"
: 5,
"label"
:
"role:saveRole"
,
"owned"
:
false
}
]
}
|
测试二:是懒加载,根据parent_id查询当前分支。 结果如下.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
{
"code"
: 0,
"msg"
:
"SUCCESS"
,
"data"
: [
{
"id"
:
"3"
,
"parentId"
:
"2"
,
"children"
: [],
"hasChildren"
:
false
,
"permissionName"
:
"update"
,
"permissionCode"
:
null
,
"path"
:
null
,
"sort"
: 3,
"label"
:
"update"
,
"owned"
:
false
},
{
"id"
:
"4"
,
"parentId"
:
"2"
,
"children"
: [],
"hasChildren"
:
false
,
"permissionName"
:
"insert_role"
,
"permissionCode"
:
null
,
"path"
:
null
,
"sort"
: 4,
"label"
:
"insert_role"
,
"owned"
:
false
}
]
}
|
到此这篇关于springboot构造树形结构数据并查询的方法的文章就介绍到这了,更多相关springboot 树形结构并查询内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/to10086/article/details/109730685 。
最后此篇关于springboot构造树形结构数据并查询的方法的文章就讲到这里了,如果你想了解更多关于springboot构造树形结构数据并查询的方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
谁能解释一下原因: (define a (lambda() (cons a #f))) (car (a)) ==> procedure ((car (a))) ==> (procedure . #f)
这是 PyBrain 网站的摘录。我了解大部分正在发生的事情,但是一行让我完全难住了。我以前从未在 python 代码中看到过这样的东西。这是整个循环,对于上下文: for c in [0,
我是gradle / groovy的新手。我想创建将做一些事情的自定义任务。我的第一个问题是任务完成时该如何做?我可以覆盖doFirst / doLast闭包吗?也许我可以重写某些在开始和结束时都会执
我刚刚开始评估 MS 企业库。他们使用以下指令来获取实例: var customerDb = EnterpriseLibraryContainer.Current.GetInstance("C
这是我的 if else Ansible 逻辑.. - name: Check certs exist stat: path=/etc/letsencrypt/live/{{ rootDomain
我正在使用construct 2.8 对一些失传已久的 Pascal 程序创建的一些文件的 header 进行逆向工程。 header 由许多不同的记录组成,其中一些是可选的,我不确定顺序是否固定。
我在将 getchar() 的输入放入 char *arr[] 数组时遇到问题。我这样做的原因是因为输入数据(将是一个带有命令行参数的文件)将存储在一个 char 指针数组中以传递给 execvp 函
通常我们不能约束类型参数 T派生自密封类型(例如 struct 类型)。这将毫无意义,因为只有一种类型适合,因此不需要泛型。所以约束如下: where T : string 或: where T :
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
#include using namespace std; class A { private: int m_i; friend int main(int argc, char cons
这个问题在这里已经有了答案: Are there legitimate uses for JavaScript's "with" statement? (33 个答案) 关闭 9 年前。 我有这个代
在this answer我看到了下一个 Bash 结构。 yes "$(< file.txt)" 什么意思 "$(< file.txt)" ? 我明白了 命令替换 - $(command)用命令的结
if (a == 1) //do something else if (a == 2) //do something else if (a == 3) //do somethi
关于构造的快速简单的问题。 我有以下用于将项目添加到 ListView 的代码。 ListViewItem item = new ListViewItem(); item.Text = file; i
我想使用 std::vector 来控制给定的内存。首先,我很确定这不是好的做法,但好奇心占了上风,无论如何我都想知道如何做到这一点。 我遇到的问题是这样的方法: vector getRow(unsi
下面显示了一段简单的javascript: var mystring = ("random","ignored","text","h") + ("ello world") 这个字符串会生成 hello
在 Java 中,创建对象的标准方法是使用 MyClass name = new MyClass(); 我也经常看到构造 new MyClass() { /*stuff goes in here*/
我正在编写 C++ ndarray 类。我需要动态大小和编译时大小已知的数组(分别分配自由存储和分配堆栈)。我想支持从嵌套的 std::initializer_list 进行初始化。 动态大小的没问题
我正在将一个项目从 Visual Studio 2005 转换为 Visual Studio 2008,并提出了上述结构。 using Castle.Core.Resource; using Cast
我想知道我在这里的想法是否正确,我主要针对接口(interface)进行编程,所以我想知道下面的类是否应该通过 DI 注入(inject),或者我应该自己实例化一个类... 注意:这些服务保存在我的核
我是一名优秀的程序员,十分优秀!