Hutool樹結構工具-TreeUtil快速構建樹形結構的兩種方式 + 數據排序
- 一、業務場景
- 二、Hutool官網樹結構工具
- 2.1 介紹
- 2.2 使用
- 2.2.1 定義結構
- 2.2.2 構建Tree
- 2.2.3 自定義字段名
- 2.3 說明
- 三、具體的使用場景
- 3.1 實現的效果
- 3.2 業務代碼
- 3.3 實現自定義字段的排序
- 四、踩過的坑
- 4.1 坑1:weight權重屬性 類型異常
- 4.2 坑2:weight權重屬性 字符串只能根據首字母排序
一、業務場景
Springboot + vue 開發;
想實現樹結構業務,并在樹結構節點有業務功能,比如根據樹結構節點排序、節點的狀態顯示等功能。
在開發過程中,必定會遇到樹形結構的數據,一般都是后端直接從庫里查詢出來然后自定義方法去封裝成樹形樹形返回給前端。這里就會用到遞歸、封裝再返回,非常麻煩。后來發現 HutoolUtil 中有個工具類 TreeUtil 可以完成本次項目的需求,非常便捷,使用方式很簡單,本次就使用它來實現。
二、Hutool官網樹結構工具
如果想查詢Hutool官網最新的樹結構工具,請各位看官移步至傳送門:官網樹結構工具-TreeUtil。
以下是當時使用此 TreeUtil 時的官網介紹。
2.1 介紹
考慮到菜單等需求的普遍性,有用戶提交了一個擴展性極好的樹狀結構實現。這種樹狀結構可以根據配置文件靈活的定義節點之間的關系,也能很好的兼容關系數據庫中數據。實現 關系型數據庫數據 <-> Tree <-> JSON 樹狀結構中最大的問題就是關系問題,在數據庫中,每條數據通過某個字段關聯自己的父節點,每個業務中這個字段的名字都不同,如何解決這個問題呢?
PR的提供者提供了一種解決思路:自定義字段名,節點不再是一個bean,而是一個map,實現靈活的字段名定義。
2.2 使用
2.2.1 定義結構
我們假設要構建一個菜單,可以實現系統管理和店鋪管理,菜單的樣子如下:
系統管理
|- 用戶管理
|- 添加用戶
店鋪管理
|- 商品管理
|- 添加商品
那這種結構如何保存在數據庫中呢?一般是這樣的:
2.2.2 構建Tree
// 構建node列表
List<TreeNode<String>> nodeList = CollUtil.newArrayList();nodeList.add(new TreeNode<>("1", "0", "系統管理", 5));
nodeList.add(new TreeNode<>("11", "1", "用戶管理", 222222));
nodeList.add(new TreeNode<>("111", "11", "用戶添加", 0));
nodeList.add(new TreeNode<>("2", "0", "店鋪管理", 1));
nodeList.add(new TreeNode<>("21", "2", "商品管理", 44));
nodeList.add(new TreeNode<>("221", "2", "商品管理2", 2));
TreeNode表示一個抽象的節點,也表示數據庫中一行數據。 如果有其它數據,可以調用setExtra添加擴展字段。
// 0表示最頂層的id是0
List<Tree<String>> treeList = TreeUtil.build(nodeList, "0");
因為兩個Tree是平級的,再沒有上層節點,因此為List。
2.2.3 自定義字段名
//配置
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定義屬性名 都要默認值的
treeNodeConfig.setWeightKey("order");
treeNodeConfig.setIdKey("rid");
// 最大遞歸深度
treeNodeConfig.setDeep(3);//轉換器
List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig,(treeNode, tree) -> {tree.setId(treeNode.getId());tree.setParentId(treeNode.getParentId());tree.setWeight(treeNode.getWeight());tree.setName(treeNode.getName());// 擴展屬性 ...tree.putExtra("extraField", 666);tree.putExtra("other", new Object());});
通過TreeNodeConfig我們可以自定義節點的名稱、關系節點id名稱,這樣就可以和不同的數據庫做對應。
2.3 說明
官網上描述的是最通用和最簡單的使用方法,但是在實際開發中,我們的業務場景都會比實際的復雜很多,所以結合業務場景實現此功能。
三、具體的使用場景
3.1 實現的效果
3.2 業務代碼
3.3 實現自定義字段的排序
使用官網推薦的方法排序
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定義屬性名 都要默認值的
treeNodeConfig.setWeightKey("order");
然后在轉換器中取出此自定義的排序字段時,無論怎么配置和設置都是無法使用自定義的字段。
在網上搜索的自定義方法都是與官網上一樣,通過 TreeNodeConfig 配置類設置,然后在轉換器 treeNode 類中獲取。在我所使用的項目中始終不生效。所以只能靠自己解決了。
通過自己的摸索和研究,如3.2中的代碼通過拓展字段可以實現。
然后在轉換器中,通過拓展字段把自定義的排序字段取出然后再賦值給 Tree 類中的 weight 屬性即可。
四、踩過的坑
4.1 坑1:weight權重屬性 類型異常
官網中的weight權重屬性不能使用 int 類型的字段,項目啟動正常,調用接口時會報類型轉換異常錯誤。
4.2 坑2:weight權重屬性 字符串只能根據首字母排序
如果此字段設置為字符串類型的排序字段時,TreeUtil 只會根據首字母排序,限制了我們使用的情況,所以此種情況也不符合我們的期望。
本文完結!