springboot?vue測試平臺接口定義及發(fā)送請求功能實現(xiàn)
基于 springboot+vue 的測試平臺開發(fā)
繼續(xù)更新
添加的接口,我要來調(diào)試確定是否是通的,那么要發(fā)送接口請求,今天來實現(xiàn)這個功能,先預覽一下:
捋一下思路,分為三步走:
點擊發(fā)送按鈕,調(diào)用后端接口后端接口處理內(nèi)部,發(fā)送http接口請求后端接口把響應返回給前端展示
一、http客戶端選型
為了更方便快捷的開發(fā)功能,直接選用 hutool 框架中封裝好的 http客戶端。
官方介紹:Hutool-http 針對JDK 的HttpUrlConnection做一層封裝,簡化了HTTPS請求、文件上傳、Cookie記憶等操作,使Http請求變得無比簡單。
Hutool-http的核心集中在兩個類:
HttpRequest
HttpResponse
同時針對大部分情境,封裝了HttpUtil工具類。根據(jù)Hutool的“便捷性與靈活性并存”原則,HttpUtil 的存在體現(xiàn)了便捷性,那 HttpRequest對象的使用則體現(xiàn)了靈活性,使用此對象可以自定義更多的屬性給請求,以適應Http請求中的不同場景(例如自定義header、自定義cookie、自定義代理等等)。
看過介紹,我瀏覽了下源代碼,然后測試了一下,發(fā)現(xiàn)可以滿足我使用需求。
// get1 @Test void get1() { String result1 = HttpUtil.get("http://localhost:8080/bloomtest/user/useInfo?token=admin-token"); System.out.println(result1); } // get2 @Test void get2() { Map<String, Object> paramMap = new HashMap<>(); paramMap.put("id", 33); String result2 = HttpRequest.get("http://localhost:8080/bloomtest/apiDefinition/getApi") .form(paramMap) .execute() .body(); System.out.println(result2); }
比如,發(fā)送get請求,HttpUtil 其實是基于 HttpRequest 的進一步分裝,我這里還是直接統(tǒng)一使用 HttpRequest 。
另外,發(fā)送 post 請求也很簡單,可以直接傳入 json 字符串:
@Test void testPost() { String reqBody = "{\n" + " \"projectName\": \"項目zzz1\",\n" + " \"description\": \"測試新增項目\"\n" + "}"; //鏈式構(gòu)建請求 String result3 = HttpRequest.post("http://localhost:8080/bloomtest/project/add") // .header(Header.CONTENT_TYPE, "application/json")//頭信息,多個頭信息多次調(diào)用此方法即可 // .timeout(20000)//超時,毫秒 .body(reqBody) .execute().body(); }
關(guān)于http請求的常用信息,請求頭、參數(shù)、delete/put 等等其他方法,框架都是支持的,目前我只實現(xiàn)最基本的需求。
二、后端接口實現(xiàn)
測試過了上面的代碼,心里就有數(shù)了,在后端接口里就看怎么使用它了。
這個發(fā)送請求的接口,目前需要支持如下:
get、post 方法查詢參數(shù)(/list?id=3)、rest參數(shù)(/list/3)以及請求 body(json)
header暫時先不加,目前我項目里的接口都不需要傳指定的 header,后期實現(xiàn)了權(quán)限之后再對應完善代碼。
1. controller 層
ApiDefinitionController 類中繼續(xù)新增處理器方法。
@PostMapping("/apiTestRun") public Result apiTestRun(@RequestBody ApiRunTestRequest apiRunTestRequest) { return Result.success(apiDefinitionService.apiTestRun(apiRunTestRequest)); }
2. service 層
對應service層實現(xiàn),先放出全部代碼,目前還是以初期實現(xiàn)為主,代碼后續(xù)可能會進一步優(yōu)化:
public JSONObject apiTestRun(ApiRunTestRequest request) { // url 拼接 String url = request.getHost() + request.getPath(); // 判斷不同請求參數(shù)類型:0 query參數(shù),1 rest參數(shù), 2使用 body參數(shù) int queryType = request.getRequestType(); if (queryType == 0) { // query 參數(shù) HashMap<String, Object> paramMap = new HashMap<>(); JSONArray jsonArray = JSONArray.parseArray(request.getRequest()); for (int i=0; i<jsonArray.size(); i++) { paramMap.put(jsonArray.getJSONObject(i).get("queryKey").toString(), jsonArray.getJSONObject(i).get("value")); } if (request.getMethod().equals("get")) { String result = HttpRequest.get(url) .form(paramMap) .execute() .body(); return JSONObject.parseObject(result); } if (request.getMethod().equals("post")) { String result = HttpRequest.post(url) .form(paramMap) .execute() .body(); return JSONObject.parseObject(result); } } else if (queryType == 1) { // rest參數(shù) HashMap<String, Object> paramMap = new HashMap<>(); JSONArray jsonArray = JSONArray.parseArray(request.getRequest()); for (int i=0; i<jsonArray.size(); i++) { paramMap.put(jsonArray.getJSONObject(i).get("restKey").toString(), jsonArray.getJSONObject(i).get("value")); } // 去掉path后面的參數(shù),還原path List<String> list = Arrays.asList(request.getPath().split("/\\{")); String orginPath = list.get(0); // 解析path中的參數(shù),確認參數(shù)拼接順序 List<String> resultFindAll = ReUtil.findAll("(?<=\\{)(.+?)(?=\\})", request.getPath(), 0); String appendParamPath = ""; for (String i : resultFindAll) { appendParamPath = appendParamPath.concat("/" + paramMap.get(i)); } // 發(fā)送請求 if (request.getMethod().equals("get")) { String result = HttpRequest .get(request.getHost() + orginPath + appendParamPath) .execute() .body(); return JSONObject.parseObject(result); } if (request.getMethod().equals("post")) { String result = HttpRequest .post(request.getHost() + orginPath + appendParamPath) .execute() .body(); return JSONObject.parseObject(result); } } else if (queryType == 2) { // 請求體 if (request.getMethod().equals("post")) { String reqBody = request.getRequest(); String result = HttpRequest.post(url) .body(reqBody) .execute().body(); return JSONObject.parseObject(result); } // 請求體 if (request.getMethod().equals("get")) { String reqBody = request.getRequest(); String result = HttpRequest.get(url) .body(reqBody) .execute().body(); return JSONObject.parseObject(result); } } return null; }
乍一看比較多,其實分開看就好:
- 根據(jù)參數(shù)類型,分別對于 query、rest、body 的請求參數(shù)情況進行處理
- 在其中每種類型里,又區(qū)分了 get、post 方法
簡單介紹下其中各種的要點。
(1)query 參數(shù)
主要是前面的 2 步:
拿到前端的入?yún)?,解析?JSONArray,內(nèi)部元素類型又是 JSONObject
遍歷 JSONArray,通過jsonArray.getJSONObject(i)方法獲取各 JSONObject 的 key,對應前端入?yún)⒌膓ueryKey和value,就是參數(shù)名和參數(shù)值。
接著發(fā)送請求,拿到的返回是一個 String,解析成 JSONObject 返回給 controller
(2)rest 參數(shù)
處理 rest 參數(shù)稍微麻煩了些,比如:localhost:8080/bloomtest/module/list/3
,最后的3
才是參數(shù)。
處理過程就像我注視寫的:
獲取前端傳來的參數(shù)
首先跟上面一樣,獲取到前端的參數(shù)名和值,放到 HashMap 里,熟悉 python的童鞋就當作放到字典里了。
解析path中的參數(shù),確認參數(shù)拼接順序
因為參數(shù)名需要跟 url 里的拼接的值順序?qū)喜判?,接口里保存的url是這樣的:/bloomtest/module/list/{projectId}
,大括號里的就是參數(shù)。
所以這里使用了正則去匹配我要的內(nèi)容,表達式(?<=\{)(.+?)(?=\})
我搜的,具體我也不熟悉,后續(xù)再學習。
ReUtil.findAll
方法也是來自于 hutool 框架,可以查找到所有符合表達式的內(nèi)容,返回是一個數(shù)組。
然后遍歷這個數(shù)組,把里面的參數(shù)逐個拼接到一個空字符串里appendParamPath
:
String appendParamPath = ""; for (String i : resultFindAll) { appendParamPath = appendParamPath.concat("/" + paramMap.get(i)); }
去掉path后面的參數(shù),還原path
因為前端傳過來的 path 是/bloomtest/module/list/{projectId}
,需要去掉最后的/{projectId}
才可以使用。
List<String> list = Arrays.asList(request.getPath().split("/\\{")); String orginPath = list.get(0);
使用了字符串分割split
方法,返回的是一個String[]
數(shù)組,又通過Arrays.asList
進一步做了轉(zhuǎn)化,就可以使用get(0)
獲取第一個使用了,也就是/bloomtest/module/list
。
前面都齊了,就可以發(fā)送請求了,注意最終請求的 url 還是要拼接一下:request.getHost() + orginPath + appendParamPath
(3)請求體
這個最簡單,前端傳過來的 json 字符串直接傳入即可:
if (request.getMethod().equals("post")) { String reqBody = request.getRequest(); String result = HttpRequest.post(url) .body(reqBody) .execute().body(); return JSONObject.parseObject(result); }
要注意的是,這里用的 JSONObject 是來自fastjson
,之前用 hutool 帶的處理,會有報錯,搞了好一會。
三、前端實現(xiàn)
我這里是整個功能開發(fā)完成后進行整理的,實際上,后端接口邏輯不是一次性寫完的。先寫好一個可以前端調(diào)得通的接口,然后一點點前后調(diào)試完成。
前端這里做的事情不多,在【發(fā)送】按鈕上綁定一個點擊實踐,調(diào)用后端開發(fā)好的接口。
方法apiTestRun
內(nèi)部,主要是處理請求入?yún)?,調(diào)用請求,處理返回即可:
紅框里是調(diào)用接口的部分,前面的是處理入?yún)?。這里的 3 個判斷是看目前點擊了哪個 tab,然后傳對應入?yún)㈩愋徒o接口。
接下來測試下功能OK。
四、修改遺留 bug
在測試功能的時候,發(fā)現(xiàn)了幾個問題。大概表現(xiàn)都是因為前端參數(shù)賦值,或者沒重置干凈導致的。
增加和修改了一些代碼,完整代碼更新
前端:
https://github.com/wessonlan/bloomtest-web
后端
https://github.com/wessonlan/bloomtest-backend
以上就是springboot+vue測試平臺接口定義及發(fā)送請求功能實現(xiàn)的詳細內(nèi)容,更多關(guān)于springboot+vue接口定義發(fā)送請求的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot異步調(diào)用方法實現(xiàn)場景代碼實例
這篇文章主要介紹了SpringBoot異步調(diào)用方法實現(xiàn)場景代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04關(guān)于JDK15的新特性之TextBlocks文本塊的引入和使用
這篇文章主要介紹了關(guān)于JDK15的新特性之文本塊的引入和使用,如果具有一種語言學機制,可以比多行文字更直觀地表示字符串,而且可以跨越多行,而且不會出現(xiàn)轉(zhuǎn)義的視覺混亂,那么這將提高廣泛Java類程序的可讀性和可寫性,需要的朋友可以參考下2023-07-07java序列化和serialVersionUID的使用方法實例
這篇文章主要介紹了java序列化和serialVersionUID的使用方法實例的相關(guān)資料,這里說明很詳細的使用方法讓你徹底學會,需要的朋友可以參考下2017-08-08為什么 Java 8 中不需要 StringBuilder 拼接字符串
java8中,編輯器對“+”進行了優(yōu)化,默認使用StringBuilder進行拼接,所以不用顯示的使用StringBuilder了,直接用“+”就可以了。下面我們來詳細了解一下2019-05-05ruoyi-springboot框架新增模塊調(diào)接口報404的解決方案
這篇文章主要介紹了ruoyi-springboot框架新增模塊調(diào)接口報404的解決方案,文中通過代碼示例給大家講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下2024-03-03Kotlin 語言中調(diào)用 JavaScript 方法實例詳解
這篇文章主要介紹了Kotlin 語言中調(diào)用 JavaScript 方法實例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06Java IO文件編碼轉(zhuǎn)換實現(xiàn)代碼
這篇文章主要介紹了Java IO文件編碼轉(zhuǎn)換實現(xiàn)代碼,有需要的朋友可以參考一下2013-12-12