SpringBoot集成Swagger3,還想來份離線文檔?真酷炫
本文轉載自微信公眾號「程序新視界」,作者二師兄。轉載本文請聯系程序新視界公眾號。
前言
隨著項目架構的演化,前后端分離是不可阻擋的趨勢。這種模式的協作在實踐的過程中經常會遇到的一個問題就是文檔。
在《一位CTO告訴我,項目中至少需要這3類文檔》一文我們已經描述了文檔的重要性,而接口文檔便是其中之一,可以說是必不可少的。
但編寫接口文檔對開發人員來說是一大難題,而且接口還在不斷的變化,還要花費精力去維護接口文檔的更新。
既然存在痛點,那么必須會出現解決此痛點的產品,這就是Swagger,目前已經更新到Swagger3版本了。如果你還停留在Swagger2,建議升級到Swagger3,整體UI風格及交互友好了不少。
本篇將圍繞Swagger3與SpringBoot的集成和離線文檔的生成來進行講解。
Swagger簡介
Swagger是一個規范和完整的框架,用于生成、描述、調用和可視化RESTful風格的Web服務。總體目標是使客戶端和文件系統作為服務器以同樣的速度來更新。文件的方法,參數和模型緊密集成到服務器端的代碼,允許API來始終保持同步。
官網:https://swagger.io
Swagger解決的痛點
傳統方式提供文檔有以下痛點:
- 接口眾多,實現細節復雜,編寫文檔耗費費力,需要持續維護;
- 接口文檔需要隨時進行同步;
- 接口返回的結果不明確,得構造返回結構體等;
- 不能直接在線測試接口,通常需要額外的工具,比如PostMan等。
當引入Swagger之后,以上痛點迎刃而解,同時還帶來以下優點:
- 及時性 (接口變更后,前后端人員可實時看到最新版本)
- 規范性 (接口具體統一風格,如接口地址,請求方式,參數,響應格式和錯誤信息等)
- 一致性 (接口信息一致,不會因接口文檔版本問題出現分歧)
- 可測性 (可直接基于接口文檔進行測試)
Swagger3的改變
Swagger3.0的改動,官方文檔總結如下幾點:
- 刪除了對springfox-swagger2的依賴;
- 刪除所有@EnableSwagger2...注解;
- 添加了springfox-boot-starter依賴項;
- 移除了guava等第三方依賴;
- 文檔訪問地址改為http://ip:port/project/swagger-ui/index.html。
下面就來實戰使用一下吧。
SpringBoot集成Swagger3
SpringBoot集成Swagger3與SpringBoot集成其他框架的套路基本一致,通常包括:引入依賴、指定配置文件、創建配置類和使用。
引入依賴
在SpringBoot項目的pom.xml中引入Swagger3依賴:
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-boot-starter</artifactId>
- <version>3.0.0</version>
- </dependency>
指定配置文件
通常情況下swagger只能在開發環境或測試環境下開啟,生產環境下需要進行關閉的。而swagger的開啟與關閉可在application.properties中進行配置:
- # 生產環境需設置為false
- springfox.documentation.swagger-ui.enabled=true
配置類
通過@EnableOpenApi注解啟動用Swagger的使用,同時在配置類中對Swagger的通用參數進行配置。
- @Configuration
- @EnableOpenApi
- public class Swagger3Config {
- @Bean
- public Docket createRestApi() {
- //返回文檔摘要信息
- return new Docket(DocumentationType.OAS_30)
- .apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.withMethodAnnotation(Operation.class))
- .paths(PathSelectors.any())
- .build()
- .globalRequestParameters(getGlobalRequestParameters())
- .globalResponses(HttpMethod.GET, getGlobalResponseMessage())
- .globalResponses(HttpMethod.POST, getGlobalResponseMessage());
- }
- /**
- * 生成接口信息,包括標題、聯系人等
- */
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("Swagger3接口文檔")
- .description("如有疑問,可聯系二師兄,微信:zhuan2quan")
- .contact(new Contact("二師兄", "https://www.choupangxia.com/", "secbro2@gmail.com"))
- .version("1.0")
- .build();
- }
- /**
- * 封裝全局通用參數
- */
- private List<RequestParameter> getGlobalRequestParameters() {
- List<RequestParameter> parameters = new ArrayList<>();
- parameters.add(new RequestParameterBuilder()
- .name("uuid")
- .description("設備uuid")
- .required(true)
- .in(ParameterType.QUERY)
- .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
- .required(false)
- .build());
- return parameters;
- }
- /**
- * 封裝通用響應信息
- */
- private List<Response> getGlobalResponseMessage() {
- List<Response> responseList = new ArrayList<>();
- responseList.add(new ResponseBuilder().code("404").description("未找到資源").build());
- return responseList;
- }
- }
通過以上配置已經完成了Spring Boot與Swagger的集成,下面展示一下如何在業務邏輯中進行使用。
業務中使用
創建兩個實體類Goods(商品類)和CommonResult(通用返回結果類)。
Goods類:
- @ApiModel("商品模型")
- public class Goods {
- /**
- * 商品id
- */
- @ApiModelProperty("商品ID")
- Long goodsId;
- /**
- * 商品名稱
- */
- @ApiModelProperty("商品名稱")
- private String goodsName;
- /**
- * 商品價格
- */
- @ApiModelProperty("商品價格")
- private BigDecimal price;
- // 省略getter/setter
- }
CommonResult類:
- @ApiModel("API通用數據")
- public class CommonResult<T> {
- /**
- * 標識代碼,0表示成功,非0表示出錯
- */
- @ApiModelProperty("標識代碼,0表示成功,非0表示出錯")
- private Integer code;
- /**
- * 描述信息,通常錯時使用
- */
- @ApiModelProperty("錯誤描述")
- private String msg;
- /**
- * 業務數據
- */
- @ApiModelProperty("業務數據")
- private T data;
- public CommonResult(Integer status, String msg, T data) {
- this.code = status;
- this.msg = msg;
- this.data = data;
- }
- /**
- * 成功
- */
- public static <T> CommonResult<T> success(T data) {
- return new CommonResult<>(0, "成功", data);
- }
- public static <T> CommonResult<T> success(Integer code, String msg) {
- return new CommonResult<>(code, msg, null);
- }
- /**
- * 錯誤
- */
- public static <T> CommonResult<T> error(int code, String msg) {
- return new CommonResult<>(code, msg, null);
- }
- // 省略getter/setter
- }
下面針對Controller層的接口來使用Swagger對應的API。
GoodsController類:
- @Api(tags = "商品信息管理接口")
- @RestController
- @RequestMapping("/goods")
- public class GoodsController {
- @Operation(summary = "單個商品詳情")
- @GetMapping("/findGoodsById")
- public CommonResult<Goods> findGoodsById(
- @Parameter(description = "商品ID,正整數")
- @RequestParam(value = "goodsId", required = false, defaultValue = "0") Integer goodsId) {
- System.out.println("根據商品ID=" + goodsId + "查詢商品詳情");
- Goods goods = new Goods();
- goods.setGoodsId(1L);
- goods.setGoodsName("筆記本");
- goods.setPrice(new BigDecimal(8888));
- return CommonResult.success(goods);
- }
- }
OrderController類:
- @Api(tags = "訂單管理接口")
- @RestController
- @RequestMapping("/order")
- public class OrderController {
- @Operation(summary = "提交訂單")
- @PostMapping("/order")
- @ApiImplicitParams({
- @ApiImplicitParam(name = "userId", value = "用戶id", dataTypeClass = Long.class, paramType = "query", example = "123"),
- @ApiImplicitParam(name = "goodsId", value = "商品id", dataTypeClass = Integer.class, paramType = "query", example = "1")
- })
- public CommonResult<String> toBuy(@ApiIgnore @RequestParam Map<String, String> params) {
- System.out.println(params);
- return CommonResult.success("success");
- }
- }
展示效果
完成集成,啟動SpringBoot項目,在訪問地址:
http://127.0.0.1:8080/swagger-ui/index.html
從整體上可以看到如下效果:
具體的商品信息管理接口,可以看到請求參數、返回結果數據結構等信息,點擊“Try it out”,可輸入參數請求參數,進行接口的調用:
調用之后會返回對應的處理結果:
在最下面的Schemas中還可以看到對應返回結果數據和被Swagger注解的實體類信息。
Swagger3注解使用說明
經過上述實例之后,我們知道大多數API是如何使用的了,這了再匯總一下相關API的功能:
- @Api:用在請求的類上,表示對類的說明
- tags="說明該類的作用,可以在UI界面上看到的注解"
- value="該參數沒什么意義,在UI界面上也看到,所以不需要配置"
- @ApiOperation:用在請求的方法上,說明方法的用途、作用
- value="說明方法的用途、作用"
- notes="方法的備注說明"
- @ApiImplicitParams:用在請求的方法上,表示一組參數說明
- @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一個請求參數的各個方面
- name:參數名
- value:參數的漢字說明、解釋
- required:參數是否必須傳
- paramType:參數放在哪個地方
- · header --> 請求參數的獲取:@RequestHeader
- · query --> 請求參數的獲取:@RequestParam
- · path(用于restful接口)--> 請求參數的獲取:@PathVariable
- · body(不常用)
- · form(不常用)
- dataType:參數類型,默認String,其它值dataType="Integer"
- defaultValue:參數的默認值
- @ApiResponses:用在請求的方法上,表示一組響應
- @ApiResponse:用在@ApiResponses中,一般用于表達一個錯誤的響應信息
- code:數字,例如400
- message:信息,例如"請求參數沒填好"
- response:拋出異常的類
- @ApiModel:用于響應類上,表示一個返回響應數據的信息
- (這種一般用在post創建的時候,使用@RequestBody這樣的場景,
- 請求參數無法使用@ApiImplicitParam注解進行描述的時候)
- @ApiModelProperty:用在屬性上,描述響應類的屬性
集成knife4j導出離線文檔
Swagger為我們提供了方便的在線文檔支持,但某些場景下我們需要把接口文檔提供給合作人員,而不是直接給一個地址。此時,我們就需要將接口文檔導出為離線文檔。
這里我們集成增強文檔knife4j來實現離線文檔的導出。
添加knife4j依賴
在pom.xml中增加knife4j的依賴:
- <dependency>
- <groupId>com.github.xiaoymin</groupId>
- <artifactId>knife4j-spring-boot-starter</artifactId>
- <version>3.0.2</version>
- </dependency>
啟動knife4j
在上面配置Swagger的Swagger3Config中添加@EnableKnife4j注解,該注解可以開啟knife4j的增強功能。
- @EnableKnife4j
- @Configuration
- @EnableOpenApi
- public class Swagger3Config {
- // ...
- }
此時,如果依舊訪問http://localhost:8080/swagger-ui/index.html會發現顯示并沒有變化。這里我們需要訪問http://localhost:8088/doc.html。
整個項目源碼地址:https://github.com/secbr/springboot-all/tree/master/springboot-swagger3。
展示效果
此時啟動項目,訪問doc.html之后,你會發現現在文檔風格變得非常酷炫。展示幾個效果圖來看看:
其中在“離線文檔”一欄中可以看到四種形式的離線文檔下載:Markdown、HTML、Word、OpenAPI。
其中個人感覺HTML格式的文檔更具有沒敢,也更方便查看,來一張圖看看效果。
小結
文檔是項目中必須的,但隨著開源框架的發展,對技術人員來說文檔的痛點也在逐步解決。如果你還處于手寫文檔的階段,真的可以嘗試一下這類更友好的文檔展現形式。