Swagger使用————接口参数注解的使用缺陷
問題描述
在使用springboot開發web項目時,用到了swagger框架,來生成web api文檔。但是其中有一項是舉例說明參數的結構,如下圖:
但是,這個功能真的是非常方便,因為可以讓前端開發人員第一時間得知參數的內部結構是什么樣的,這尤其適用于那些json體結構的參數。網上的例子都是這樣的:
但是,我無論如何都弄不出來這個樣子,前前后后研究了有好幾個小時。
終于找出了問題。
問題原因
網上的api接口中,幾乎全是傳入一個完整的Java Bean對象,而不是傳JsonObject對象。
我的代碼是這樣:
@ApiOperation(value = "添加景區下的特價門票", notes = "{\"scenicIdArr\" : [53361,53356]}")@PostMapping(value = "/special_price/add")public JSONObject addSpecialPrice(@RequestBody JSONObject scenicIdArr) {return sprSvc.addSpecialPrice(scenicIdArr);}別人的代碼是這樣:
????@ApiOperation("更改用戶信息")@PostMapping("/updateUserInfo")public int updateUserInfo(@RequestBody @ApiParam(name="用戶對象",value="傳入json格式",required=true) User user){int num = userService.updateUserInfo(user);return num;}經過比較,很容易就發現了問題,我的接口中的參數是無法得知內部數據結構的JSONObject類型,而別人的參數是一個已知其內部數據結構的User對象。
既然知道了原因,那我也將接口進行了一些修改:
創建一個符合我業務要求的數據結構實體類,然后將這個實體類作為參數傳入接口中:
@ApiOperation(value = "添加景區下的特價門票", notes = "{\"scenicIdArr\" : [53361,53356]}")@PostMapping(value = "/special_price/add")public JSONObject addSpecialPrice(@RequestBody ScenicIdArr scenicIdArr) {return null;}@ApiModelclass ScenicIdArr {@ApiModelProperty(value = "景區id數組")int[] scenicIdArr;}上述代碼中,我定義了一個成員內部類,并將實體類以@ApiModel進行注解。效果如下:
呵呵,沒有一丁點效果!我陷入了沉思... ...
于是我大膽的猜想:swagger框架可能是自動調用了get或set方法,并完成頁面渲染。
于是我又修改了代碼:
@ApiOperation(value = "添加景區下的特價門票", notes = "{\"scenicIdArr\" : [53361,53356]}")@PostMapping(value = "/special_price/add")public JSONObject addSpecialPrice(@RequestBody ScenicIdArr scenicIdArr) {return null;}@ApiModelclass ScenicIdArr {@ApiModelProperty(value = "景區id數組")int[] scenicIdArr;public int[] getScenicIdArr() {return scenicIdArr;}}我加了一個get方法,來獲取實體類中的屬性,看一下效果:
上圖中可以看到,不論是整體的實體類結構,還是字段上的注釋“景區id數組”都很好的顯示了出來。這樣,我們在頁面點擊小黃框的時候,就可以將數據自動的加載到參數填寫的白框內。
這樣,我們省去了手動書寫結構和key值的過程,而只需要我們輸入具體的value值即可。
由于本篇博客并不是教你如何使用spring-boot-starter-swagger自動依賴配置模塊中的各種注解如何使用,因此,此處只是簡單解析了一下接口參數的模板生成方式。
但是,題目中既然提到了這個功能的缺陷,就不得不回過頭來吐槽一下這個破JB玩意兒!
吐槽一下
這個在小黃框顯示對外接口參數結構的功能真的應該說是非常實用的一個功能,我并不知道這個功能具體的名稱是什么,暫且就稱它為“參數樣例功能”。
為什么說這個功能非常實用?
首先,書寫簡便。REST接口風格的參數多以json結構體傳輸數據,而這樣一個自動生成結構體的功能,可以為我們免去書寫大量括號、冒號、逗號、引號、空格等json體的必須元素,而且自動排版,避免手寫出錯,達到零錯誤。在真正通過頁面的api接口測試的時候,只需要簡單輸入幾個value值就可以“try it out”了,著實提高了不少效率。
其次,方便前端開發。我們都知道,不論是傳入JavaBean對象,還是傳入沒有在后端強制類型約束的Json字符串,前端調用controller中的接口時,僅僅是傳入一個key-value的結構,才不會管你什么JavaBean。對于springboot,其一系列內嵌的HttpMessageConverter會將json結構轉化成對應的JavaBean,再交給Controller。前端開發人員甚至可以將小黃框內的內容,直接拷貝過來,稍作修改(value賦值)即可完成對后端接口對接的全部編碼。
第三,覆蓋了其他部分注解。個人認為,swagger中的注解關于參數注釋方面,有些重復,這一點不做展開討論,且僅僅是個人觀點,可以參考官方api文檔體會一下。另外關于response一類的注解,完全沒有必要。返回值是什么結構的,完全可以通過“try it out”調用一次接口即可了解到。估計swagger開發團隊考慮到功能的完整性,或者在后端由于某種原因導致接口不可用而做的一種補足方案(比如,數據庫中暫無數據等原因)。
雖然這個功能實用,但是依然存在一個很別扭的情況。
那就是,我們不得不因為要在“參數樣例功能”中展示我們的參數結構而創建一個Java Bean。不論這個Java Bean在后臺邏輯中有無實際意義。
就比方說我之前的那個接口:
????@ApiOperation(value = "添加景區下的特價門票", notes = "{\"scenicIdArr\" : [53361,53356]}")@PostMapping(value = "/special_price/add")public JSONObject addSpecialPrice(@RequestBody JSONObject scenicIdArr)我需要拿到一個有景區id組成的json體的數據結構,然后跑到service中去處理,可能我的這種api結構并不規范,但是不可能不存在這樣一種情況:僅僅規定一個json結構,而不是Java Bean來作為參數進行處理。(抱歉,最近在看《Thinking In Java》句子寫起來有那么一點模仿布魯斯??藸柕那徽{)
我查找了很多資料,包括官方的API說明,并沒有很好解決方案。于是,才有了后面的成員內部類的出現。但是這種代碼除了方便測試以外完全沒有實際意義。如果為每個以json結構體作為參數的接口另起一個class文件去明確傳入參數的結構,就顯得有些愚蠢。它會使你的代碼非常的臃腫和凌亂。
這就是我說的swagger的這個缺陷,以純json結構體作為參數的接口,無法實現非常重要的“參數樣例功能”。
綜上,就是我對swagger框架的一點看法和總結,如有疑問,歡迎文末留言。
總結
以上是生活随笔為你收集整理的Swagger使用————接口参数注解的使用缺陷的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c 语言运算符号大全,c语言运算符号详细
- 下一篇: oracle用户密码复杂度查询,11gR