<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
繼續更新
新增的介面,我要來偵錯確定是否是通的,那麼要傳送介面請求,今天來實現這個功能,先預覽一下:
捋一下思路,分為三步走:
點選傳送按鈕,呼叫後端介面後端介面處理內部,傳送http介面請求後端介面把響應返回給前端展示
為了更方便快捷的開發功能,直接選用 hutool 框架中封裝好的 http使用者端。
官方介紹:Hutool-http 針對JDK 的HttpUrlConnection做一層封裝,簡化了HTTPS請求、檔案上傳、Cookie記憶等操作,使Http請求變得無比簡單。
Hutool-http的核心集中在兩個類:
HttpRequest
HttpResponse
同時針對大部分情境,封裝了HttpUtil工具類。根據Hutool的“便捷性與靈活性並存”原則,HttpUtil 的存在體現了便捷性,那 HttpRequest物件的使用則體現了靈活性,使用此物件可以自定義更多的屬性給請求,以適應Http請求中的不同場景(例如自定義header、自定義cookie、自定義代理等等)。
看過介紹,我瀏覽了下原始碼,然後測試了一下,發現可以滿足我使用需求。
// 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); }
比如,傳送get請求,HttpUtil 其實是基於 HttpRequest 的進一步分裝,我這裡還是直接統一使用 HttpRequest 。
另外,傳送 post 請求也很簡單,可以直接傳入 json 字串:
@Test void testPost() { String reqBody = "{n" + " "projectName": "專案zzz1",n" + " "description": "測試新增專案"n" + "}"; //鏈式構建請求 String result3 = HttpRequest.post("http://localhost:8080/bloomtest/project/add") // .header(Header.CONTENT_TYPE, "application/json")//頭資訊,多個頭資訊多次呼叫此方法即可 // .timeout(20000)//超時,毫秒 .body(reqBody) .execute().body(); }
關於http請求的常用資訊,請求頭、引數、delete/put 等等其他方法,框架都是支援的,目前我只實現最基本的需求。
測試過了上面的程式碼,心裡就有數了,在後端介面裡就看怎麼使用它了。
這個傳送請求的介面,目前需要支援如下:
get、post 方法查詢引數(/list?id=3)、rest引數(/list/3)以及請求 body(json)
header暫時先不加,目前我專案裡的介面都不需要傳指定的 header,後期實現了許可權之後再對應完善程式碼。
ApiDefinitionController 類中繼續新增處理器方法。
@PostMapping("/apiTestRun") public Result apiTestRun(@RequestBody ApiRunTestRequest apiRunTestRequest) { return Result.success(apiDefinitionService.apiTestRun(apiRunTestRequest)); }
對應service層實現,先放出全部程式碼,目前還是以初期實現為主,程式碼後續可能會進一步優化:
public JSONObject apiTestRun(ApiRunTestRequest request) { // url 拼接 String url = request.getHost() + request.getPath(); // 判斷不同請求引數型別:0 query引數,1 rest引數, 2使用 body引數 int queryType = request.getRequestType(); if (queryType == 0) { // query 引數 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引數 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後面的引數,還原path List<String> list = Arrays.asList(request.getPath().split("/\{")); String orginPath = list.get(0); // 解析path中的引數,確認引數拼接順序 List<String> resultFindAll = ReUtil.findAll("(?<=\{)(.+?)(?=\})", request.getPath(), 0); String appendParamPath = ""; for (String i : resultFindAll) { appendParamPath = appendParamPath.concat("/" + paramMap.get(i)); } // 傳送請求 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; }
乍一看比較多,其實分開看就好:
簡單介紹下其中各種的要點。
(1)query 引數
主要是前面的 2 步:
拿到前端的入參,解析成 JSONArray,內部元素型別又是 JSONObject
遍歷 JSONArray,通過jsonArray.getJSONObject(i)方法獲取各 JSONObject 的 key,對應前端入參的queryKey和value,就是引數名和引數值。
接著傳送請求,拿到的返回是一個 String,解析成 JSONObject 返回給 controller
(2)rest 引數
處理 rest 引數稍微麻煩了些,比如:localhost:8080/bloomtest/module/list/3
,最後的3
才是引數。
處理過程就像我注視寫的:
獲取前端傳來的引數
首先跟上面一樣,獲取到前端的引數名和值,放到 HashMap 裡,熟悉 python的童鞋就當作放到字典裡了。
解析path中的引數,確認引數拼接順序
因為引數名需要跟 url 裡的拼接的值順序對應上才行,介面裡儲存的url是這樣的:/bloomtest/module/list/{projectId}
,大括號裡的就是引數。
所以這裡使用了正則去匹配我要的內容,表示式(?<={)(.+?)(?=})
我搜的,具體我也不熟悉,後續再學習。
ReUtil.findAll
方法也是來自於 hutool 框架,可以查詢到所有符合表示式的內容,返回是一個陣列。
然後遍歷這個陣列,把裡面的引數逐個拼接到一個空字串裡appendParamPath
:
String appendParamPath = ""; for (String i : resultFindAll) { appendParamPath = appendParamPath.concat("/" + paramMap.get(i)); }
去掉path後面的引數,還原path
因為前端傳過來的 path 是/bloomtest/module/list/{projectId}
,需要去掉最後的/{projectId}
才可以使用。
List<String> list = Arrays.asList(request.getPath().split("/\{")); String orginPath = list.get(0);
使用了字串分割split
方法,返回的是一個String[]
陣列,又通過Arrays.asList
進一步做了轉化,就可以使用get(0)
獲取第一個使用了,也就是/bloomtest/module/list
。
前面都齊了,就可以傳送請求了,注意最終請求的 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 帶的處理,會有報錯,搞了好一會。
我這裡是整個功能開發完成後進行整理的,實際上,後端介面邏輯不是一次性寫完的。先寫好一個可以前端調得通的介面,然後一點點前後偵錯完成。
前端這裡做的事情不多,在【傳送】按鈕上繫結一個點選實踐,呼叫後端開發好的介面。
方法apiTestRun
內部,主要是處理請求入參,呼叫請求,處理返回即可:
紅框裡是呼叫介面的部分,前面的是處理入參。這裡的 3 個判斷是看目前點選了哪個 tab,然後傳對應入參型別給介面。
接下來測試下功能OK。
在測試功能的時候,發現了幾個問題。大概表現都是因為前端引數賦值,或者沒重置乾淨導致的。
增加和修改了一些程式碼,完整程式碼更新
前端:
https://github.com/wessonlan/bloomtest-web
後端
https://github.com/wessonlan/bloomtest-backend
以上就是springboot+vue測試平臺介面定義及傳送請求功能實現的詳細內容,更多關於springboot+vue介面定義傳送請求的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45