SpringBoot第十一集:整合Swagger3.0與RESTful介面整合返回值(2020最新最易懂)
SpringBoot第十一集:整合Swagger3.0與RESTful介面整合返回值(2020最新最易懂)
一,整合Swagger3.0
隨著Spring Boot、Spring Cloud等微服務的流行,在微服務的設計下,小公司微服務工程jar小的幾十個,大公司大的工程拆分jar多則幾百上萬個,這麼多的微服務必定產生了大量的介面呼叫。而介面的呼叫就必定要寫介面文件(由開發人員編寫)。
存在的問題:(面對多個開發人員或多個開發團隊)
- 專案開發介面眾多,細節,複雜,且多樣化,高質量地建立介面文件費時,費力。
- 隨著專案的進行,不可避免整改和優化,需要不斷的修改介面實現,伴隨著也需要同時修改介面文件,管理不方便不說,還容易出現不一致的情況。
概述
Swagger 是一個規範和完整的框架,用於生成、描述、呼叫和視覺化 RESTful 風格的 Web 服務。
實際開發過程中Swagger能夠完美的與Spring Boot程式整合,組織出強大RESTful API文件,它既可以減少我們建立文件的工作量,同時也整合了說明內容在實現程式碼中,讓維護文件和修改程式碼融為一體,可以讓我們在修改程式碼邏輯的同時方便的修改文件說明。另外Swagger2還提供了強大的頁面測試功能,讓開發者能快速的除錯每個RESTful API。
1.整合實現
1,引入pom依賴。
Swagger3.0的更新還是有很大變化的(詳情參考),首先在依賴jar問題上,它新增了springfox-boot-starter,修復了2.x版本的衝突,移除了guava。另外Swagger3.0還移除了註解@EnableSwagger2,增加註解@EnableOpenApi。
<!-- SpringBoot整合springfox-swagger3 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
啟動SpringBoot主程式,可以直接測試訪問:
測試地址:http://localhost:8080/swagger-ui/index.html (訪問後提供的有預設的錯誤呼叫介面文件)
需要注意的是,Swagger3.0還更新了UI頁面地址,如上,而Swagger2.x的訪問地址是這樣的:http://localhost:8080/swagger-ui.html
2,自定義SwaggerConfig類
新增SwaggerConfig類,並將其載入到Spring IOC中。需要注意:自定義Swagger配置類,Swagger3.0移除註解@EnableSwagger2,增加註解@EnableOpenApi。@EnableOpenApi可以在Config類中應用,也可以在SpringBoot主啟動類上使用(選其一即可),表示啟用自定義API介面。
1 @EnableOpenApi // 開啟Swagger自定義介面文件 2 @Configuration // 相當於Spring配置中的<beans> 3 public class SwaggerConfig { 4 @Bean // 相當於Spring 配置中的<bean> 5 public Docket createRestApi() { 6 return new Docket(DocumentationType.OAS_30) 7 .apiInfo(apiInfo()) 8 .select() 9 .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) 10 .paths(PathSelectors.any()) 11 .build(); 12 } 13 // API基礎資訊定義(就是更新Swagger預設頁面上的資訊) 14 private ApiInfo apiInfo() { 15 return new ApiInfoBuilder() 16 .title("Swagger3介面文件測試") 17 .description("文件描述:更多問題,請聯絡開發者") 18 .contact(new Contact("xsge123(name)", "作者網站(url)", "[email protected](email)")) 19 .version("1.0") 20 .build(); 21 } 22 23 }
3,編寫Controller提供RESTful風格的介面API
編寫Controller前,先看看一些註解的意思吧!
@Api:用在控制器類上,表示對類的說明
tags="說明該類的作用,可以在UI介面上看到的說明資訊的一個好用註解"
value="該引數沒什麼意義,在UI介面上也看到,所以不需要配置"
@ApiOperation:用在請求的方法上,說明方法的用途、作用
value="說明方法的用途、作用"
notes="方法的備註說明"
@ApiImplicitParams:用在請求的方法上,表示一組引數說明
@ApiImplicitParam:用在@ApiImplicitParams註解中,指定一個請求引數的各個方面(標註一個指定的引數,詳細概括引數的各個方面,例如:引數名是什麼?引數意義,是否必填等)
name:屬性值為方法引數名
value:引數意義的漢字說明、解釋
required:引數是否必須傳
paramType:引數放在哪個地方
· header --> 請求引數的獲取:@RequestHeader
· query --> 請求引數的獲取:@RequestParam
· path(用於restful介面)--> 請求引數的獲取:@PathVariable
· div(不常用)
· form(不常用)
dataType:引數型別,預設String,其它值dataType="Integer"
defaultValue:引數的預設值
@ApiResponses:用在請求的方法上,表示一組響應
@ApiResponse:用在@ApiResponses中,一般用於表達一個錯誤的響應資訊
code:狀態碼數字,例如400
message:資訊,例如"請求引數沒填好"
response:丟擲異常的類
@ApiModel:用於響應類上(POJO實體類),描述一個返回響應資料的資訊(描述POJO類請求或響應的實體說明)
(這種一般用在post介面的時候,使用@RequestBody接收JSON格式的資料的場景,請求引數無法使用@ApiImplicitParam註解進行描述的時候)
@ApiModelProperty:用在POJO屬性上,描述響應類的屬性說明
@ApiIgnore
:使用該註解忽略這個API;
Spring Boot中包含了一些控制器方法RESTful介面註解,對應於HTTP協議中的方法:
-
@GetMapping
對應HTTP中的GET方法; -
@PostMapping
對應HTTP中的POST方法; -
@PutMapping
對應HTTP中的PUT方法; -
@DeleteMapping
對應HTTP中的DELETE方法; -
@PatchMapping
對應HTTP中的PATCH方法。
1 @Api(value = "測試SwaggerAPI Annotation", tags = "Swagger測試之使用者資訊管理API") 2 @RestController 3 @RequestMapping("/user") 4 public class SwaggerController { 5 6 @ApiIgnore // 忽略這個API 7 @GetMapping("/hello") 8 public String hello() { 9 return "hello"; 10 } 11 12 @GetMapping(value = "/swaggerGet/{name}") 13 @ApiOperation(value = "介面方法說明", notes = "介面的詳情描述") 14 @ApiImplicitParam(name = "name", value = "請傳遞一個使用者名稱引數",required = true, dataType = "String", paramType = "path") 15 public String swaggerGet(@PathVariable String name) { 16 return "name="+name; 17 } 18 19 @PostMapping(value = "/swaggerPost") 20 @ApiOperation(value = "新增使用者", notes = "Swagger測試RESTful之POST請求測試入參一個POJO(JSON格式)") 21 public User swaggerGet(@RequestBody User user) { 22 return user; 23 } 24 25 }
實體類
1 @ApiModel("使用者資訊實體類") 2 @Data 3 public class User { 4 // example:示例程式碼值 5 @ApiModelProperty(value = "使用者名稱",dataType="String",name="username",example="xsge") 6 private String username; 7 @ApiModelProperty(value = "賬戶密碼",dataType="String",name="password",example="123456") 8 private String password; 9 10 }
4,啟動SpringBoot工程,測試訪問
輸入地址:http://localhost:8080/swagger-ui/index.html 進入Swagger介面文件介面。
注意:Swagger2.x版本不一樣哦!關於2.x的配置版本也有些不同,這裡就不介紹了...
二,統一介面返回值
我們在應用中經常會涉及到 server 和 client 的互動,目前比較流行的是基於 json 格式的資料互動。但是 json 只是訊息的格式,其中的內容還需要我們自行設計。不管是 HTTP 介面還是 RPC 介面保持返回值格式統一很重要,這將大大降低 client 的開發成本。
一般定義Response的標準格式包含四部分:
- Integer code ;成功時返回 0 ,失敗時返回具體錯誤碼。(可以自定義錯誤碼,使用列舉類封裝)
- String message ;成功時返回 null ,失敗時返回具體錯誤訊息。(可以自定義錯誤訊息,使用列舉類封裝)
- T data ;成功時具體返回值,失敗時為 null 。
例如:
1 { 2 "code": 0, 3 "messages": "", 4 "data": "" 5 }
1.定義列舉類,封裝狀態碼和訊息
定義一些常見的成功與失敗的列舉常量。如下:(該列舉類可以作為工具使用了,有心的朋友可自行儲存一下)
1 public enum EnumCode { 2 // 定義成功的列舉常量,狀態碼,和描述 3 SUCCESS(0,"ok"),// 這裡的程式碼相當於:public static final DataEnumCode SUCCESS = new DataEnumCode(0,“ok”)呼叫類有參構造傳值 4 // 定義系統異常的列舉常量,狀態碼,和描述 5 SYSTEM_ERROR(5001,"伺服器系統異常,請稍後..."), 6 // 定義引數異常的列舉常量,狀態碼,和描述 7 PARAMETER_ERROR(5002,"引數異常,認證失敗..."), 8 // 定義使用者名稱存在異常的列舉常量,狀態碼,和描述 9 USER_HAS_ERROR(5003,"使用者名稱已存在....");// 注意上面的是逗號分隔,這裡結束是分號 10 11 // 定義的列舉常量屬性。 12 private int code;// 狀態碼 13 private String message;// 描述 14 15 /** 16 * 私有構造,防止被外部呼叫 17 */ 18 private EnumCode(int code, String message) { 19 this.code = code; 20 this.message = message; 21 } 22 /** 23 * 定義方法,返回描述,跟常規類的定義get沒區別 24 * @return 25 */ 26 public int getCode() { 27 return code; 28 } 29 public String getMessage() { 30 return message; 31 } 32 }
2.定義Response的標準格式POJO
為便於合理化實現標準格式的響應,新增POJO類,並新增封裝屬性(狀態碼,描述資訊,響應資料)。
為便於標準化的實施,類中提供的如下四個方法:(該解析響應類可以作為工具使用了,有心的朋友可自行儲存一下)
- 成功方法。請求成功,響應結果集資料,響應狀態碼,描述,狀態碼和描述從列舉常量中解析。
- 失敗方法。請求失敗,無結果集資料,響應狀態碼,描述保留,狀態碼和描述從列舉常量中解析。(列舉型別有限,不一定滿足所有異常)
- 失敗方法。請求失敗,無結果集資料,響應狀態碼,描述保留,該方法用於解決因為列舉常量的侷限性,不足以滿足所有需求的問題,實現允許自定義狀態碼和描述。
- 提供便於解析列舉常量的方法。
1 @Data 2 @NoArgsConstructor 3 @AllArgsConstructor 4 public class ResponseData<T> { 5 6 private int code;// 狀態碼 7 private String message;// 提示訊息 8 private T data;// 響應結果集資料 9 10 /**列舉類常量解析器 11 * 快速解析列舉類常量資訊,解析資料並放入到標準響應類ResponseData的屬性中 12 * @param enumCode 13 */ 14 public void parserEnum(EnumCode enumCode) { 15 this.code = enumCode.getCode();// 獲取列舉常量的狀態碼,賦值給屬性 16 this.message = enumCode.getMessage();// 獲取列舉常量的描述資訊 17 } 18 19 /**定義請求成功的:狀態碼,描述,結果集資料 20 * @param data 傳遞的響應結果集資料 21 * @return 有成功狀態碼,描述,結果集資料的標準格式物件 22 */ 23 public static<T> ResponseData<T> success(T data) { 24 // 建立響應標準格式物件 25 ResponseData<T> responseData = new ResponseData<T>(); 26 // 呼叫轉換器方法,將(成功)列舉常量解析,放入到標準響應資料中。 27 responseData.parserEnum(EnumCode.SUCCESS); 28 // 放入響應資料 29 responseData.setData(data); 30 return responseData; 31 } 32 33 34 /**定義請求失敗的:狀態碼,描述,不包含結果集資料 35 * @param enumCode 失敗時傳遞的常見錯誤列舉常量 36 * @return 有失敗狀態碼,描述,沒有結果集資料的標準格式物件 37 */ 38 public static<T> ResponseData<T> error(EnumCode enumCode) { 39 // 建立響應標準格式物件 40 ResponseData<T> responseData = new ResponseData<T>(); 41 // 呼叫轉換器方法,將(錯誤)列舉常量解析。 42 responseData.parserEnum(enumCode); 43 return responseData; 44 } 45 46 /** 有成功,有失敗,但是失敗的狀態描述不一定能全部滿足需求(列舉類有限),所以,自定義方法實現自定義資訊 47 * @param code 自定義的狀態碼 48 * @param message 自定義的錯誤資訊 49 * @return 有失敗自定義狀態碼,自定義描述,沒有結果集資料的標準格式物件 50 */ 51 public static<T> ResponseData<T> generator(int code,String message) { 52 // 建立響應標準格式物件 53 ResponseData<T> responseData = new ResponseData<T>(); 54 responseData.setCode(code); 55 responseData.setMessage(message); 56 return responseData; 57 } 58 59 }
溫馨提示:靜態方法定義泛型時,必須使用statc<T>定義,否則編譯失敗。
解惑:有人可能存在疑問,既然列舉類不能滿足所有響應要求,幹嘛定義列舉類,感覺有點多此一舉!直接自定義封裝多好,可以解決所有問題。但是,請記住,團隊開發,如果全部使用自定義封裝,那麼如何實現資訊的統一標準呢?當出現同一個錯誤時,有人提示系統錯誤,有人提示後臺錯誤,有人提示請聯絡管理員???這樣是不是很亂。所以常見的,基本的訊息定義,通過列舉類列舉,可以輕鬆實現統一管理。而不常見的錯誤,既然不常見,那麼又怎可能經常自定義?這就是簡易的架構設計優化。
3, 編寫Controller提供RESTful風格暴露介面
1 @Api(value = "測試SwaggerAPI Annotation", tags = "Swagger測試之使用者資訊管理API") 2 @RestController 3 @RequestMapping("/user") 4 public class SwaggerController { 5 6 @ApiIgnore // 忽略這個API 7 @GetMapping("/hello") 8 public String hello() { 9 return "hello"; 10 } 11 12 @GetMapping(value = "/swaggerGet/{name}") 13 @ApiOperation(value = "介面方法說明", notes = "介面的詳情描述") 14 @ApiImplicitParam(name = "name", value = "請傳遞一個使用者名稱引數",required = false,dataType = "String", paramType = "path") 15 public ResponseData<String> swaggerGet(@PathVariable String name) { 16 // 呼叫成功的解析方法,並傳遞響應資料 17 ResponseData<String> responseData = ResponseData.success(name); 18 return responseData; 19 } 20 21 @PostMapping(value = "/swaggerPost") 22 @ApiOperation(value = "新增使用者", notes = "Swagger測試RESTful之POST請求測試入參一個POJO(JSON格式)") 23 public ResponseData<User> swaggerGet(@RequestBody User user) { 24 // 呼叫成功的解析方法,並傳遞響應資料 25 ResponseData<User> responseData = ResponseData.success(user); 26 return responseData; 27 } 28 29 }
4.開啟瀏覽器測試訪問。
瀏覽器測試訪問:http://localhost:8080/swagger-ui/index.html (選擇測試一下,按照介面文件說明實施測試)
Postman測試訪問:(輸入介面URL,傳遞引數測試即可)
測試結果如下: