springboot?vue接口測(cè)試HutoolUtil?TreeUtil處理樹(shù)形結(jié)構(gòu)
基于springboot+vue的測(cè)試平臺(tái)開(kāi)發(fā)
繼續(xù)更新
上次完成了接口定義功能的前端頁(yè)面,那么后端現(xiàn)在開(kāi)始逐一實(shí)現(xiàn)對(duì)應(yīng)的功能,首先就是提供模塊列表接口,這個(gè)模塊是支持子層級(jí)的,所以大概結(jié)構(gòu)是這樣:
[ { id: 1, label: '默認(rèn)', children: [ { id: 4, label: '二級(jí)子模塊1', children: [ { id: 9, label: '三級(jí)子模塊1' }, { id: 10, label: '三級(jí)子模塊2' } ] } ] }, { id: 2, label: '一級(jí)子模塊2', children: [ { id: 5, label: '二級(jí)子模塊 1' }, { id: 6, label: '二級(jí)子模塊 2' } ] } ]
通常來(lái)說(shuō),可以寫(xiě)遞歸代碼來(lái)找出子層級(jí)的數(shù)據(jù),然后再進(jìn)行封裝返回出來(lái),比較麻煩。
后來(lái)發(fā)現(xiàn) HutoolUtil 中有個(gè)工具類(lèi) TreeUtil 可以完成我需求,非常便捷,本次就使用它來(lái)實(shí)現(xiàn)。
下面來(lái)完成接口功能的開(kāi)發(fā)。
一、引用 HutoolUtil
Hutool是一個(gè)小而全的Java工具類(lèi)庫(kù),通過(guò)靜態(tài)方法封裝,降低相關(guān)API的學(xué)習(xí)成本,提高工作效率,使Java擁有函數(shù)式語(yǔ)言般的優(yōu)雅,讓Java語(yǔ)言也可以“甜甜的”。
Hutool中的工具方法來(lái)自每個(gè)用戶的精雕細(xì)琢,它涵蓋了Java開(kāi)發(fā)底層代碼中的方方面面,它既是大型項(xiàng)目開(kāi)發(fā)中解決小問(wèn)題的利器,也是小型項(xiàng)目中的效率擔(dān)當(dāng);
Hutool是項(xiàng)目中“util”包友好的替代,它節(jié)省了開(kāi)發(fā)人員對(duì)項(xiàng)目中公用類(lèi)和公用工具方法的封裝時(shí)間,使開(kāi)發(fā)專(zhuān)注于業(yè)務(wù),同時(shí)可以最大限度的避免封裝不完善帶來(lái)的bug。
要使用它直接添加依賴即可:
<!--hutool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.12</version> </dependency>
官方文檔:https://www.hutool.cn/docs/#/
內(nèi)容很詳細(xì),不僅后面的樹(shù)結(jié)構(gòu)工具,像常用的集合類(lèi)、JSON、日志、緩存、文件、線程和并發(fā)等等應(yīng)有盡有。
二、建表
給模塊建一張新表api_module
:
CREATE TABLE `api_module` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', `projectId` bigint NOT NULL COMMENT '該節(jié)點(diǎn)所屬項(xiàng)目id', `name` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '節(jié)點(diǎn)名稱', `parentId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '父節(jié)點(diǎn)id', `level` int DEFAULT '1' COMMENT '節(jié)點(diǎn)層級(jí)', `createTime` datetime NOT NULL DEFAULT '1900-01-01 00:00:00' COMMENT '創(chuàng)建時(shí)間', `updateTime` datetime NOT NULL DEFAULT '1900-01-01 00:00:00' COMMENT '更新時(shí)間', `pos` double DEFAULT NULL COMMENT '節(jié)點(diǎn)順序位置', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='模塊表';
重要字段:
projectId
:與項(xiàng)目進(jìn)行關(guān)聯(lián)
parentId
:該節(jié)點(diǎn)的父節(jié)點(diǎn),一級(jí)目錄的父節(jié)點(diǎn)我會(huì)設(shè)置為 0 。
level
:該節(jié)點(diǎn)對(duì)應(yīng)層級(jí),從 1 開(kāi)始。
pos
:表示該節(jié)點(diǎn)在父節(jié)點(diǎn)下的位置順序。
三、后端接口實(shí)現(xiàn)
1. Controller 層
新建 ApiModuleController 類(lèi),添加一個(gè)處理器方法 getNodeByProjectId,通過(guò)項(xiàng)目 ID 查詢出下面的所有模塊。
package com.pingguo.bloomtest.controller; import com.pingguo.bloomtest.common.Result; import com.pingguo.bloomtest.service.ApiModuleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("module") public class ApiModuleController { @Autowired ApiModuleService apiModuleService; @GetMapping("/list/{projectId}") public Result getNodeByProjectId(@PathVariable Long projectId) { return Result.success(apiModuleService.getNodeTreeByProjectId(projectId)); } }
2. DAO層
dao 層自然也要有。
package com.pingguo.bloomtest.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.pingguo.bloomtest.pojo.ApiModule; import org.springframework.stereotype.Repository; @Repository public interface ApiModuleDAO extends BaseMapper<ApiModule> { }
3. Service 層
實(shí)現(xiàn) getNodeTreeByProjectId 方法。
public List<Tree<String>> getNodeTreeByProjectId(Long projectId) { this.getDefaultNode(projectId); // 根據(jù) projectId 查詢所有節(jié)點(diǎn) QueryWrapper<ApiModule> wrapperApiModule = new QueryWrapper<>(); List<ApiModule> apiModules = apiModuleDAO.selectList(wrapperApiModule.eq("projectId", projectId)); // 配置 TreeNodeConfig treeNodeConfig = new TreeNodeConfig(); // 自定義屬性名 ,即返回列表里對(duì)象的字段名 treeNodeConfig.setIdKey("id"); treeNodeConfig.setWeightKey("pos"); treeNodeConfig.setParentIdKey("parentId"); treeNodeConfig.setChildrenKey("children"); // 最大遞歸深度 // treeNodeConfig.setDeep(5); treeNodeConfig.setNameKey("name"); //轉(zhuǎn)換器 List<Tree<String>> treeNodes = TreeUtil.build(apiModules, "0", treeNodeConfig, (treeNode, tree) -> { tree.setId(treeNode.getId().toString()); tree.setParentId(treeNode.getParentId().toString()); tree.setWeight(treeNode.getPos()); tree.setName(treeNode.getName()); // 擴(kuò)展屬性 ... tree.putExtra("projectId", treeNode.getProjectId()); tree.putExtra("level", treeNode.getLevel()); tree.putExtra("label", treeNode.getName()); tree.putExtra("createTime", treeNode.getCreateTime()); tree.putExtra("updateTime", treeNode.getUpdateTime()); }); return treeNodes; }
這里開(kāi)頭有個(gè)方法 getDefaultNode,在這里面會(huì)判斷當(dāng)前項(xiàng)目下是否有默認(rèn)模塊,沒(méi)有則添加默認(rèn)模塊。
private void getDefaultNode(Long projectId) { QueryWrapper<ApiModule> wrapperApiModule = new QueryWrapper<>(); wrapperApiModule.eq("projectId", projectId) .eq("pos", 1.0); // 判斷當(dāng)前項(xiàng)目下是否有默認(rèn)模塊,沒(méi)有則添加默認(rèn)模塊 if (apiModuleDAO.selectCount(wrapperApiModule) == 0) { ApiModule apiModule = new ApiModule(); apiModule.setName("默認(rèn)"); apiModule.setPos(1.0); apiModule.setLevel(1); apiModule.setParentId(0L); apiModule.setCreateTime(new Date()); apiModule.setUpdateTime(new Date()); apiModule.setProjectId(projectId); apiModuleDAO.insert(apiModule); } }
然后通過(guò) 項(xiàng)目id 把項(xiàng)目下所有的數(shù)據(jù)查詢出來(lái):
接下來(lái)使用 TreeUtil 來(lái)完成樹(shù)結(jié)構(gòu)處理。
首先,創(chuàng)建一個(gè)配置類(lèi) TreeNodeConfig 對(duì)象,在這個(gè)對(duì)象里設(shè)置屬性,對(duì)應(yīng)的就是返回出來(lái)的字段名。
還可以設(shè)置最大遞歸深度,也可以不設(shè)。我測(cè)試之后就注釋掉了,先不加限制。
最后就是構(gòu)建樹(shù)結(jié)構(gòu) treeNodes,完成處理后返回給 controller 層。
因?yàn)槲乙祷氐倪€有其他的字段,可以使用tree.putExtra
來(lái)添加要返回的其他字段,比如:
tree.putExtra("projectId", treeNode.getProjectId());
第一個(gè)參數(shù)是定義的字段名稱,第二個(gè)參數(shù)就是使用這個(gè)結(jié)點(diǎn)的 get 方法獲取對(duì)應(yīng)的屬性值。
最后返回到上層的是List<Tree<String>>
類(lèi)型,可以直接塞到統(tǒng)一結(jié)果里去返回。
四、測(cè)試一下
1. 測(cè)試結(jié)構(gòu)數(shù)據(jù)
測(cè)試一下接口,先手動(dòng)網(wǎng)表里插入了對(duì)應(yīng)結(jié)構(gòu)的數(shù)據(jù)。
請(qǐng)求接口,傳入 projectId 為 3。
{ "code": 20000, "message": "成功", "data": [ { "id": "9", "parentId": "0", "pos": 1.0, "name": "默認(rèn)", "projectId": 3, "level": 1, "label": "默認(rèn)", "createTime": "2021-09-29 10:50:00", "updateTime": "2021-09-29 10:50:00", "children": [ { "id": "14", "parentId": "9", "pos": 1.0, "name": "默認(rèn)-2", "projectId": 3, "level": 2, "label": "默認(rèn)-2", "createTime": "1900-01-01 08:00:00", "updateTime": "1900-01-01 08:00:00" }, { "id": "10", "parentId": "9", "pos": 1.0, "name": "默認(rèn)-1", "projectId": 3, "level": 2, "label": "默認(rèn)-1", "createTime": "2021-10-01 08:00:00", "updateTime": "1900-01-01 08:00:00", "children": [ { "id": "11", "parentId": "10", "pos": 1.0, "name": "默認(rèn)-1-1", "projectId": 3, "level": 3, "label": "默認(rèn)-1-1", "createTime": "1900-01-01 08:00:00", "updateTime": "1900-01-01 08:00:00", "children": [ { "id": "12", "parentId": "11", "pos": 1.0, "name": "默認(rèn)-1-1-1", "projectId": 3, "level": 4, "label": "默認(rèn)-1-1-1", "createTime": "1900-01-01 08:00:00", "updateTime": "1900-01-01 08:00:00", "children": [ { "id": "13", "parentId": "12", "pos": 1.0, "name": "默認(rèn)-1-1-1-1", "projectId": 3, "level": 5, "label": "默認(rèn)-1-1-1-1", "createTime": "1900-01-01 08:00:00", "updateTime": "1900-01-01 08:00:00" } ] } ] } ] } ] } ] }
結(jié)果正確。
2. 測(cè)試新增默認(rèn)
傳入一個(gè) projectId 為 4 ,localhost:8080/bloomtest/module/list/4:
{ "code": 20000, "message": "成功", "data": [ { "id": "15", "parentId": "0", "pos": 1.0, "name": "默認(rèn)", "projectId": 4, "level": 1, "label": "默認(rèn)", "createTime": "2021-10-01 12:25:54", "updateTime": "2021-10-01 12:25:54" } ] }
返回正確。
落庫(kù)正常。
以上就是springboot vue接口測(cè)試HutoolUtil TreeUtil處理樹(shù)形結(jié)構(gòu)的詳細(xì)內(nèi)容,更多關(guān)于HutoolUtil TreeUtil處理樹(shù)形結(jié)構(gòu)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot如何獲取Get請(qǐng)求參數(shù)詳解
- springBoot 過(guò)濾器去除請(qǐng)求參數(shù)前后空格實(shí)例詳解
- SpringBoot通過(guò)JSON傳遞請(qǐng)求參數(shù)的實(shí)例詳解
- springboot如何設(shè)置請(qǐng)求參數(shù)長(zhǎng)度和文件大小限制
- SpringBoot常見(jiàn)get/post請(qǐng)求參數(shù)處理、參數(shù)注解校驗(yàn)及參數(shù)自定義注解校驗(yàn)詳解
- SpringBoot之自定義Filter獲取請(qǐng)求參數(shù)與響應(yīng)結(jié)果案例詳解
- springboot?vue接口測(cè)試前后端實(shí)現(xiàn)模塊樹(shù)列表功能
- springboot?vue接口測(cè)試前后端樹(shù)節(jié)點(diǎn)編輯刪除功能
- springboot?vue接口測(cè)試前端動(dòng)態(tài)增刪表單功能實(shí)現(xiàn)
- springboot3請(qǐng)求參數(shù)種類(lèi)及接口測(cè)試案例小結(jié)
相關(guān)文章
Java實(shí)現(xiàn)簡(jiǎn)單文件過(guò)濾器功能
下面小編就為大家分享一篇Java實(shí)現(xiàn)簡(jiǎn)單文件過(guò)濾器功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01SpringBoot整合Redisson實(shí)現(xiàn)分布式鎖
本文主要介紹了SpringBoot整合Redisson實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11ActiveMQ中consumer的消息確認(rèn)機(jī)制詳解
這篇文章主要介紹了ActiveMQ中consumer的消息確認(rèn)機(jī)制詳解,對(duì)于broker而言,只有接收到確認(rèn)指令,才會(huì)認(rèn)為消息被正確的接收或者處理成功了,InforSuiteMQ提供以下幾種Consumer與Broker之間的消息確認(rèn)方式,需要的朋友可以參考下2023-10-10Java Swing實(shí)現(xiàn)餐廳點(diǎn)餐系統(tǒng)源碼(收藏版)
這篇文章主要介紹了Java Swing實(shí)現(xiàn)餐廳點(diǎn)餐系統(tǒng)源碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02