在應用開發過程中經常需要對其他應用或者客戶端提供 RESTful API 介面,尤其是在版本快速迭代的開發過程中,修改介面的同時還需要同步修改對應的介面文件,這使我們總是做著重複的工作,並且如果忘記修改介面文件,就可能造成不必要的麻煩。
為了解決這些問題,Swagger 就孕育而生了,那讓我們先簡單瞭解下。
Swagger 簡介
Swagger 是一個規範和完整的框架,用於生成、描述、呼叫和視覺化 RESTful 風格的 Web 服務。
總體目標是使客戶端和檔案系統作為伺服器,以同樣的速度來更新。檔案的方法、引數和模型緊密整合到伺服器端的程式碼中,允許 API 始終保持同步。
下面我們在 Spring Boot 中整合 Swagger 來構建強大的介面文件。
Spring Boot 整合 Swagger
Spring Boot 整合 Swagger 主要分為以下三步:
- 加入 Swagger 依賴
- 加入 Swagger 文件配置
- 使用 Swagger 註解編寫 API 文件
加入依賴
首先建立一個專案,在專案中加入 Swagger 依賴,專案依賴如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
加入配置
接下來在 config
包下建立一個 Swagger 配置類 Swagger2Configuration
,在配置類上加入註解 @EnableSwagger2
,表明開啟 Swagger,注入一個 Docket 類來配置一些 API 相關資訊,apiInfo()
方法內定義了幾個文件資訊,程式碼如下:
@Configuration
@EnableSwagger2
public class Swagger2Configuration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// swagger 文件掃描的包
.apis(RequestHandlerSelectors.basePackage("com.wupx.interfacedoc.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("測試介面列表")
.description("Swagger2 介面文件")
.version("v1.0.0")
.contact(new Contact("wupx", "https://www.tianheyu.top", "wupx@qq.com"))
.license("Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
}
列舉其中幾個文件資訊說明下:
- title:介面文件的標題
- description:介面文件的詳細描述
- termsOfServiceUrl:一般用於存放公司的地址
- version:API 文件的版本號
- contact:維護人、維護人 URL 以及 email
- license:許可證
- licenseUrl:許可證 URL
編寫 API 文件
在 domain
包下建立一個 User
實體類,使用 @ApiModel
註解表明這是一個 Swagger 返回的實體,@ApiModelProperty
註解表明幾個實體的屬性,程式碼如下(其中 getter/setter 省略不顯示):
@ApiModel(value = "使用者", description = "使用者實體類")
public class User {
@ApiModelProperty(value = "使用者 id", hidden = true)
private Long id;
@ApiModelProperty(value = "使用者姓名")
private String name;
@ApiModelProperty(value = "使用者年齡")
private String age;
// getter/setter
}
最後,在 controller
包下建立一個 UserController
類,提供使用者 API 介面(未使用資料庫),程式碼如下:
@RestController
@RequestMapping("/users")
@Api(tags = "使用者管理介面")
public class UserController {
Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
@GetMapping("/")
@ApiOperation(value = "獲取使用者列表", notes = "獲取使用者列表")
public List<User> getUserList() {
return new ArrayList<>(users.values());
}
@PostMapping("/")
@ApiOperation(value = "建立使用者")
public String addUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@GetMapping("/{id}")
@ApiOperation(value = "獲取指定 id 的使用者")
@ApiImplicitParam(name = "id", value = "使用者 id", paramType = "query", dataTypeClass = Long.class, defaultValue = "999", required = true)
public User getUserById(@PathVariable Long id) {
return users.get(id);
}
@PutMapping("/{id}")
@ApiOperation(value = "根據 id 更新使用者")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "使用者 id", defaultValue = "1"),
@ApiImplicitParam(name = "name", value = "使用者姓名", defaultValue = "wupx"),
@ApiImplicitParam(name = "age", value = "使用者年齡", defaultValue = "18")
})
public User updateUserById(@PathVariable Long id, @RequestParam String name, @RequestParam Integer age) {
User user = users.get(id);
user.setName(name);
user.setAge(age);
return user;
}
@DeleteMapping("/{id}")
@ApiOperation(value = "刪除使用者", notes = "根據 id 刪除使用者")
@ApiImplicitParam(name = "id", value = "使用者 id", dataTypeClass = Long.class, required = true)
public String deleteUserById(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
啟動專案,訪問 http://localhost:8080/swagger-ui.html
,可以看到我們定義的文件已經在 Swagger 頁面上顯示了,如下圖所示:
到此為止,我們就完成了 Spring Boot 與 Swagger 的整合。
同時 Swagger 除了介面文件功能外,還提供了介面除錯功能,以建立使用者介面為例,單擊建立使用者介面,可以看到介面定義的引數、返回值、響應碼等,單擊 Try it out
按鈕,然後點選 Execute
就可以發起呼叫請求、建立使用者,如下圖所示:
註解介紹
由於 Swagger 2 提供了非常多的註解供開發使用,這裡列舉一些比較常用的註解。
@Api
@Api
用在介面文件資源類上,用於標記當前類為 Swagger 的文件資源,其中含有幾個常用屬性:
- value:定義當前介面文件的名稱。
- description:用於定義當前介面文件的介紹。
- tag:可以使用多個名稱來定義文件,但若同時存在 tag 屬性和 value 屬性,則 value 屬性會失效。
- hidden:如果值為 true,就會隱藏文件。
@ApiOperation
@ApiOperation
用在介面文件的方法上,主要用來註解介面,其中包含幾個常用屬性:
- value:對API的簡短描述。
- note:API的有關細節描述。
- esponse:介面的返回型別(注意:這裡不是返回實際響應,而是返回物件的實際結果)。
- hidden:如果值為 true,就會在文件中隱藏。
@ApiResponse、@ApiResponses
@ApiResponses
和 @ApiResponse
二者配合使用返回 HTTP 狀態碼。@ApiResponses
的 value 值是 @ApiResponse
的集合,多個 @ApiResponse
用逗號分隔,其中 @ApiResponse
包含的屬性如下:
- code:HTTP狀態碼。
- message:HTTP狀態資訊。
- responseHeaders:HTTP 響應頭。
@ApiParam
@ApiParam
用於方法的引數,其中包含以下幾個常用屬性:
- name:引數的名稱。
- value:引數值。
- required:如果值為 true,就是必傳欄位。
- defaultValue:引數的預設值。
- type:引數的型別。
- hidden:如果值為 true,就隱藏這個引數。
@ApiImplicitParam、@ApiImplicitParams
二者配合使用在 API 方法上,@ApiImplicitParams
的子集是 @ApiImplicitParam
註解,其中 @ApiImplicitParam
註解包含以下幾個引數:
- name:引數的名稱。
- value:引數值。
- required:如果值為 true,就是必傳欄位。
- defaultValue:引數的預設值。
- dataType:資料的型別。
- hidden:如果值為 true,就隱藏這個引數。
- allowMultiple:是否允許重複。
@ResponseHeader
API 文件的響應頭,如果需要設定響應頭,就將 @ResponseHeader
設定到 @ApiResponse
的 responseHeaders
引數中。@ResponseHeader
提供了以下幾個引數:
- name:響應頭名稱。
- description:響應頭備註。
@ApiModel
設定 API 響應的實體類,用作 API 返回物件。@ApiModel
提供了以下幾個引數:
- value:實體類名稱。
- description:實體類描述。
- subTypes:子類的型別。
@ApiModelProperty
設定 API 響應實體的屬性,其中包含以下幾個引數:
- name:屬性名稱。
- value:屬性值。
- notes:屬性的註釋。
- dataType:資料的型別。
- required:如果值為 true,就必須傳入這個欄位。
- hidden:如果值為 true,就隱藏這個欄位。
- readOnly:如果值為 true,欄位就是隻讀的。
- allowEmptyValue:如果為 true,就允許為空值。
到此為止,我們就介紹完了 Swagger 提供的主要註解。
總結
Swagger 可以輕鬆地整合到 Spring Boot 中構建出強大的 RESTful API 文件,可以減少我們編寫介面文件的工作量,同時介面的說明內容也整合入程式碼中,可以讓我們在修改程式碼邏輯的同時方便的修改介面文件說明,另外 Swagger 也提供了頁面測試功能來除錯每個 RESTful API。
如果專案中還未使用,不防嘗試一下,會發現效率會提升不少。
本文的完整程式碼在 https://github.com/wupeixuan/SpringBoot-Learn 的 interface-doc
目錄下。
最好的關係就是互相成就,大家的在看、轉發、留言三連就是我創作的最大動力。
參考
https://github.com/wupeixuan/SpringBoot-Learn
《Spring Boot 2 實戰之旅》