树状结构:是我目前接触过最复杂的一种数据格式之一。
树在展开的时候有三种状态:1全选、2半选、3不选。
针对不同的状态,会有不同的结果。1全选的意思是:当下的所有的子节点也被展开了。2半选的意思是:下面节点有被选择,同时不是选了全部的状态。3不选:就是没选择。
数据库设计:我的解决方案是:id与pid关联。
但是有业务限制:数据量过大,需要一级一级展开。于是接口的思路就变成了:一级一级给前端展开。于是创建数据的时候,依据树的层级分配了不同的nodeLevel。0是顶级节点。1是0级节点的子节点,以此类推!
前端第一次调用接口,传入nodeLevel = 0,然后每次展开的时候 nodeLevel 自加1 传给我们,我们也可以通过nodeLevel控制接口返回的内容。
于是数据库设计变成了 id、pid、nodeLevel。
看似没什么问题了。一开始我们设计也是设计一级一级展开。产品看到后:需求变成是下拉树回显!就是创建的时候,从下拉树选择一个内容。保存到数据库后,再次编辑的时候,还能弹出这个被选中的带有高亮的回显树。
。一级一级展开,肯定是不可能满足这个需求了。于是我们开始尝试给出当前被选中节点ID,然后倒着查询所有节点。直到nodeLevel = 0的时候终止。一切也很美好。我们的数据是多张表凑出来的假树,为了还原这个残的全量树,要调很多张表,接口性能不行,开发复杂度高,可维护性差,不要问为什么这么设计,实际业务比上面描述的更加复杂。于是还是切换为维护一颗真数,这样无论如何,开发只需要维护一个树即可。不用担心为了凑这个数需要的信息了。
本来通过nodeLevel控制不就行了么。结果这树的层级有变化,顶层有XXX分类,算新的一层。新的一层可能存在,也有可能不存在,就冲这个薛定谔的猫。不确定,nodeLevel方案肯定是不可行的!(nodeLevel实际上是具化的信息,比如部门是1,小组是2,如果部门、小组中间加一个工会,业务必定会牵扯到代码变更)
然后我就发下了Hutool有一个工具类 TreeUtil,他最大的功能,传入一个List集合,当然集合的元素有id与pid关联的属性就行,直接给我构建好树了!就是说我们只需要传入一个集合,配置一下id与pid的关联字段是啥,就可以直接构建一个完整的树了。样例代码:
// ClickNode是我自己定义的对象,有id、pid、nodeName、nodeCode等其他属性
ArrayList<ClickNode> clickNodes = new ArrayList<>();
// 配置节点规则对象
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
treeNodeConfig.setIdKey("id"); // Json看到的主键ID变成id
treeNodeConfig.setParentIdKey("pid"); // Json序列化成为父节点为pid
// 注意参数顺序依次是:集合、父节点id(我这里填的是null)、节点规则对象、lambda表达式(主要配置映射关系node是我们的集合的元素,tree就是构建树的元素)
List<Tree<String>> treeList = TreeUtil.build(clickNodes, null, treeNodeConfig, (node, tree) -> {
tree.setId(node.getId()); // 必须配置
tree.setParentId(node.getPid()); // 必须配置
tree.setName(node.getNodeCode()); // 非必须配置,就是节点的名称
tree.putExtra("我是随便填写的属性",node.getNodeCode()); // 添加额外信息。返回时候与id、pid属性一个层级
});
如何判断节点存在这个树中呢?
如何获得这个节点的所有父节点ID呢?
如何获得这个节点所有节点名称呢?
如何获得这个节点的兄弟节点呢?
特殊说明: 上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com 第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤