将id,pid 形式的数据生成 parent-> children 树形结构。
jdk8.0+maven3
spring-boot 2.2.6.RELEASE
- 引入 node-tree-spring-boot-starter 包
<dependency>
<groupId>com.sharkman</groupId>
<artifactId>node-tree-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
- 创建树节点类
树节点对象既支持使用注解标注 id ,pid ,children 属性
也支持不使用注解标注,实现 Treeable 接口
程序会自动识别使用哪种形式。
// 注解版
// 示例使用 lombok 生成 getter and setter
@Getter
@Setter
public final class TreeNode {
@NodeID
private String id;
@NodePID
private String pId;
@NodeChildren
private List<TreeNode> children;
// 其他属性和方法...
}
// 实现接口版
// 示例使用 lombok 生成 getter and setter
@Getter
@Setter
public final class TreeNode implements Treeable {
private String id;
private String pId;
private List<Treeable> children;
// 可添加其他属性以及方法,如
private String nodeType;
}
- 在返回值需要转化为树形式的方法上加上 @NodeTree 注解
前提,方法的返回值必须是 List<节点对象> , 节点对象可使用注解标注或实现接口。
- 场景一:固定根节点id 或 pid 为固定值
注意: 如果 id 和 pid 都填值,则以 id 为准。
// 根节点 pid 为固定值 0
@NodeTree(pid = "0")
public List<TreeNode> findAllNodes(int nodesCount) {
int maxChild = 2;
return AutoData.makeRandomNodes(nodesCount, maxChild, "0");
}
// 注意,如果 TreeNode 实现了Treeable 接口,那么返回值写接口或者实现类均可,即
// 返回值是 List<TreeNode> List<Treeable> 均可,下不赘述
// 根节点 id 为固定值 0
@NodeTree(id = "0")
public List<TreeNode> findAllNodes(int nodesCount) {
int maxChild = 2;
return AutoData.makeRandomNodes(nodesCount, maxChild, "0");
}
// 根节点 pid 为 null
@NodeTree(isPidNull = true)
public List<TreeNode> findAllNodes(int nodesCount) {
int maxChild = 2;
return AutoData.makeRandomNodes(nodesCount, maxChild, "0");
}
- 场景二:动态传入根节点id 或 pid,且id 和 pid 为方法参数
// 通过 Id 获取, 方法参数个数不限,在对应参数前加注解即可
@NodeTree
public List<TreeNode> findAllNodesByCorpId(@RootID String corpId) {
return corpRepository.findCorpTreeByCorpId(corpId);
}
// 通过 父Id 获取,方法参数个数不限,在对应参数前加注解即可
@NodeTree
public List<TreeNode> findAllNodesByPCorpId(@RootPID String corpId) {
return corpRepository.findCorpTreeByPCorpId(corpId);
}
- 场景三:动态传入根节点id 或 pid,且id 和 pid 为方法参数的对象属性
// 参数对象
@Getter
@Setter
public final class SearchParam {
@RootID
private String corpId; // 此处增加注解,获取对象内部属性值作为 root id
private Date startDate;
private Date endDate;
// 其他属性和方法...
}
// 通过 Id 获取,方法参数个数不限,在对应参数前加注解即可
@NodeTree
public List<TreeNode> findAllNodesByCorpId(SearchParam param) {
return corpRepository.findCorpTreeByCorpId(param.getCorp());
}
// 参数对象
@Getter
@Setter
public final class SearchParam {
@RootPID
private String corpId; // 此处增加注解,获取对象内部属性值作为 root pid
private Date startDate;
private Date endDate;
// 其他属性和方法...
}
// 通过 父Id 获取,方法参数个数不限,在对应参数前加注解即可
@NodeTree
public List<TreeNode> findAllNodesByPCorpId(SearchParam param) {
return corpRepository.findCorpTreeByPCorpId(param.getCorp());
}
- 只需要引入 node-tree-core 包
<dependency>
<groupId>com.sharkman</groupId>
<artifactId>node-tree-core</artifactId>
<version>2.0.0</version>
</dependency>
- 创建树节点类,对象同上
- 调用 TreeUtil 或 TreeUtilForAnnotation 对应方法实现功能
- 场景1,已知根节点的父id,构造树。 父 id 可以为 null
// 接口形式
// 若根节点唯一
Treeable root = TreeUtil.buildTreeOfRootPId(nodes, rootPid);
// 若根节点不唯一
List<Treeable> root = TreeUtil.buildTreeOfRootPIdForList(nodes, rootPid);
// 注解形式
// 若根节点唯一
TreeNode root = TreeUtilForAnnotation.buildTreeOfRootPId(nodes, rootPid);
// 若根节点不唯一
List<TreeNode> root = TreeUtilForAnnotation.buildTreeOfRootPIdForList(nodes, rootPid);
- 场景2,已知根节点的id,构造树。
// 若根节点唯一
Treeable root = TreeUtil.buildTreeOfRootId(nodes, rootId);
// 若根节点不唯一
List<Treeable> root = TreeUtil.buildTreeOfRootIdForList(nodes, rootId);
// 注解形式
// 若根节点唯一
TreeNode root = TreeUtilForAnnotation.buildTreeOfRootId(nodes, rootId);
// 若根节点不唯一
List<TreeNode> root = TreeUtilForAnnotation.buildTreeOfRootIdForList(nodes, rootId);
- 场景3,已知符合根节点的条件,可以使用 lambda 表达式找到根节点,构造树。
// 若根节点唯一
Predicate<Treeable> predicate = vo -> Objects.equals(vo.getPId(), "root") && OrganEnum.isCorp(vo.getNodeType());
Treeable root = TreeUtil.buildTree(nodes, predicate);
// 若根节点不唯一
List<Treeable> root = TreeUtil.buildTreeForList(nodes, predicate);
// 注解形式
TreeNode root = TreeUtilForAnnotation.buildTree(nodes, predicate);
// 若根节点不唯一
List<TreeNode> root = TreeUtilForAnnotation.buildTreeForList(nodes, predicate);
- 场景4,已知叶子节点,反向找出谱系内父节点,构造树。(此方法从项目中使用,未进行通用性优化。暂时不支持注解版)
说明,常用的场景是数据权限进行组织机构过滤,权限只配置人员,但是需要展示有权限的组织树。 另外,此方法支持取子树,比如共4级节点,通过4级节点逆向生成树,根节点传入3级id ,则根从传入的3级开始。
// 若根节点唯一
// 起始构造的子节点集合
List<String> ids=xxxx;
// 最终取出的根节
String rootId="root";
List<Treeable> roots=TreeUtil.constructTreeForSpecifyNode(nodes,ids,rootId);
测试代码已添加, 见子项目 node-tree-run AutoDataTest测试类 TODO 待补充
- Fork 本仓库
- 新建 feature_xxx 分支
- 提交代码
- 新建 Pull Request