今天技術(shù)總監(jiān)說:小明鹤啡,我們本次3.0改造蝇刀,使用swagger2.0作為前后端分離的接口規(guī)范善茎,它可以一鍵生成前后端的API,一勞永逸……小明:烫葬?意狠?拖吼?
Spring Boot 框架是目前非常流行的微服務(wù)框架腕窥,我們很多情況下使用它來提供 Rest API执隧,而對于 Rest API 來說很重要的一部分內(nèi)容就是文檔忌愚,Swagger 為我們提供了一套通過代碼和注解自動生成文檔的方法曲管,這一點對于保證 API 文檔的及時性將有很大的幫助。本文將使用 Swagger 2 規(guī)范的 Springfox 實現(xiàn)來了解如何在 Spring Boot 項目中使用 Swagger硕糊,主要包含了如何使用 Swagger 自動生成文檔院水、使用 Swagger 文檔以及 Swagger 相關(guān)的一些高級配置和注解。
Swagger 簡介
Swagger 是一套基于 OpenAPI 規(guī)范構(gòu)建的開源工具简十,可以幫助我們設(shè)計檬某、構(gòu)建、記錄以及使用 Rest API螟蝙。Swagger 主要包含了以下三個部分:
- Swagger Editor:基于瀏覽器的編輯器恢恼,我們可以使用它編寫我們 OpenAPI 規(guī)范。
- Swagger UI:它會將我們編寫的 OpenAPI 規(guī)范呈現(xiàn)為交互式的 API 文檔胰默,后文我將使用瀏覽器來查看并且操作我們的 Rest API场斑。
- Swagger Codegen:它可以通過為 OpenAPI(以前稱為 Swagger)規(guī)范定義的任何 API 生成服務(wù)器存根和客戶端 SDK 來簡化構(gòu)建過程漓踢。
為什么要使用 Swagger
當(dāng)下很多公司都采取前后端分離的開發(fā)模式,前端和后端的工作由不同的工程師完成漏隐。在這種開發(fā)模式下喧半,維持一份及時更新且完整的 Rest API 文檔將會極大的提高我們的工作效率。傳統(tǒng)意義上的文檔都是后端開發(fā)人員手動編寫的青责,相信大家也都知道這種方式很難保證文檔的及時性挺据,這種文檔久而久之也就會失去其參考意義,反而還會加大我們的溝通成本脖隶。而 Swagger 給我們提供了一個全新的維護 API 文檔的方式扁耐,下面我們就來了解一下它的優(yōu)點:
代碼變,文檔變产阱。只需要少量的注解做葵,Swagger 就可以根據(jù)代碼自動生成 API 文檔,很好的保證了文檔的時效性心墅。
跨語言性,支持 40 多種語言榨乎。
Swagger UI 呈現(xiàn)出來的是一份可交互式的 API 文檔怎燥,我們可以直接在文檔頁面嘗試 API 的調(diào)用,省去了準備復(fù)雜的調(diào)用參數(shù)的過程蜜暑。
還可以將文檔規(guī)范導(dǎo)入相關(guān)的工具(例如 SoapUI), 這些工具將會為我們自動地創(chuàng)建自動化測試铐姚。
以上這些優(yōu)點足以說明我們?yōu)槭裁匆褂?Swagger 了,您是否已經(jīng)對 Swagger 產(chǎn)生了濃厚的興趣了呢肛捍?下面我們就將一步一步地在 Spring Boot 項目中集成和使用 Swagger隐绵,讓我們從準備一個 Spring Boot 的 Web 項目開始吧。
準備 Spring Boot Web 項目
在這一步我們將準備一個基礎(chǔ)的 Spring Boot 的 Web 項目拙毫,并且提供后面所需要的所有 API依许。
創(chuàng)建一個空的 Spring Boot 項目
您可以通過 Spring Initializr 頁面生成一個空的 Spring Boot 項目,當(dāng)然也可以下載 springboot-pom.xml 文件缀蹄,然后使用 Maven 構(gòu)建一個 Spring Boot 項目峭跳。項目創(chuàng)建完成后,為了方便后面代碼的編寫您可以將其導(dǎo)入到您喜歡的 IDE 中缺前,我這里選擇了 Intelli IDEA 打開蛀醉。
添加依賴
由于創(chuàng)建的是一個 Web 項目,所以我們需要依賴 Spring Boot 的 Web 組件衅码,只需要在 pom.xml 增加如下內(nèi)容即可:
清單 1. 添加 Web 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
編寫接口
- 首先我們創(chuàng)建三個包:cn.itweknow.sbswagger.controller拯刁、cn.itweknow.sbswagger.testcontroller 以及 cn.itweknow.sbswagger.model。
- 在 controller 包下新建 UserController.java 類逝段,在 testcontroller 包下新建 TestController.java 類垛玻,在 model 包下新建 User.java 類割捅。
- UserController 提供用戶的增、刪夭谤、改棺牧、查四個接口,TestContrller 提供一個測試接口朗儒,這里粘上 UserController.java 的代碼颊乘,其余代碼可以查看源碼。
清單 2. UserController.java 代碼
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/add")
public boolean addUser(@RequestBody User user) {
return false;
}
@GetMapping("/find/{id}")
public User findById(@PathVariable("id") int id) {
return new User();
}
@PutMapping("/update")
public boolean update(@RequestBody User user) {
return true;
}
@DeleteMapping("/delete/{id}")
public boolean delete(@PathVariable("id") int id) {
return true;
}
}
集成 Swagger2
經(jīng)過上面的步驟醉锄,我們已經(jīng)擁有了五個接口乏悄,分別是:
- /user/add:新增用戶。
- /user/find/{id}:根據(jù) id 查詢用戶恳不。
- /user/update:更新用戶檩小。
- /user/delete/{id}:根據(jù) id 刪除用戶。
- /test/test:測試接口烟勋。
下面我們將通過集成 Swagger2规求,然后為這 5 個 Rest API 自動生成接口文檔。
添加依賴
首先要做的自然是添加 Swagger2 所需要的依賴包:
清單 3. 添加 Swagger 依賴
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
Java 配置
Springfox 提供了一個 Docket 對象卵惦,讓我們可以靈活的配置 Swagger 的各項屬性阻肿。下面我們新建一個 cn.itweknow.sbswagger.conf.SwaggerConfig.java 類,并增加如下內(nèi)容:
清單 4. Swagger Java 配置
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
注意: @Configuration 是告訴 Spring Boot 需要加載這個配置類沮尿,@EnableSwagger2 是啟用 Swagger2丛塌,如果沒加的話自然而然也就看不到后面的驗證效果了。
驗證
至此畜疾,我們已經(jīng)成功的在 Spring Boot 項目中集成了 Swagger2赴邻,啟動項目后,我們可以通過在瀏覽器中訪問 http://localhost:8080/ v2/api-docs 來驗證啡捶,您會發(fā)現(xiàn)返回的結(jié)果是一段 JSON 串姥敛,可讀性非常差。幸運的是 Swagger2 為我們提供了可視化的交互界面 SwaggerUI瞎暑,下面我們就一起來試試吧徒溪。
集成 Swagger UI
添加依賴
和之前一樣,集成的第一步就是添加相關(guān)依賴金顿,在 pom.xml 中添加如下內(nèi)容即可:
清單 5. 添加 Swagger UI 依賴
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
訪問驗證
其實就只需要添加一下依賴就可以了臊泌,我們重新啟動一下項目,然后在瀏覽器中訪問 http://localhost:8080/swagger-ui.html 就可以看到如下的效果了:
圖 1. Swagger UI
可以看到雖然可讀性好了一些揍拆,但對接口的表述還不是那么的清楚渠概,接下來我們就通過一些高級配置,讓這份文檔變的更加的易讀。
高級配置
文檔相關(guān)描述配置
- 通過在控制器類上增加@Api 注解播揪,可以給控制器增加描述和標(biāo)簽信息贮喧。
清單 6. 給 Controller 添加描述信息
@Api(tags = "用戶相關(guān)接口", description = "提供用戶相關(guān)的 Rest API")
public class UserController
- 通過在接口方法上增加 @ApiOperation 注解來展開對接口的描述,當(dāng)然這個注解還可以指定很多內(nèi)容猪狈,我們在下面的相關(guān)注解說明章節(jié)中詳細解釋箱沦。
清單 7. 給接口添加描述信息
@ApiOperation("新增用戶接口")
@PostMapping("/add")
public boolean addUser(@RequestBody User user) {
return false;
}
- 實體描述,我們可以通過 @ApiModel 和 @ApiModelProperty 注解來對我們 API 中所涉及到的對象做描述雇庙。
清單 8. 給實體類添加描述信息
@ApiModel("用戶實體")
public class User {
@ApiModelProperty("用戶 id")
private int id;
}
- 文檔信息配置谓形,Swagger 還支持設(shè)置一些文檔的版本號、聯(lián)系人郵箱疆前、網(wǎng)站寒跳、版權(quán)、開源協(xié)議等等信息竹椒,但與上面幾條不同的是這些信息不是通過注解配置童太,而是通過創(chuàng)建一個 ApiInfo 對象,并且使用 Docket.appInfo() 方法來設(shè)置胸完,我們在 SwaggerConfig.java 類中新增如下內(nèi)容即可书释。
清單 9. 配置文檔信息
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfo(
"Spring Boot 項目集成 Swagger 實例文檔",
"我的博客網(wǎng)站:https://itweknow.cn,歡迎大家訪問赊窥。",
"API V1.0",
"Terms of service",
new Contact("名字想好沒", "https://itweknow.cn", "gancy.programmer@gmail.com"),
"Apache", "http://www.apache.org/", Collections.emptyList());
}
經(jīng)過上面的步驟征冷,我們的文檔將會變成下圖的樣子,現(xiàn)在看起來就清楚很多了誓琼。
圖 2. 補全信息后的 Swagger 文檔界面
接口過濾
有些時候我們并不是希望所有的 Rest API 都呈現(xiàn)在文檔上,這種情況下 Swagger2 提供給我們了兩種方式配置肴捉,一種是基于 @ApiIgnore 注解腹侣,另一種是在 Docket 上增加篩選。
- @ApiIgnore 注解齿穗。
如果想在文檔中屏蔽掉刪除用戶的接口(user/delete)傲隶,那么只需要在刪除用戶的方法上加上 @ApiIgnore 即可。
清單 10. @ApiIgnore 使用實例
@ApiIgnore
public boolean delete(@PathVariable("id") int id)
- 在 Docket 上增加篩選窃页。Docket 類提供了 apis() 和 paths()兩 個方法來幫助我們在不同級別上過濾接口:
apis():這種方式我們可以通過指定包名的方式跺株,讓 Swagger 只去某些包下面掃描。
paths():這種方式可以通過篩選 API 的 url 來進行過濾脖卖。
在集成 Swagger2 的章節(jié)中我們這兩個方法指定的都是掃描所有乒省,沒有指定任何過濾條件。如果我們在我們修改之前定義的 Docket 對象的 apis() 方法和 paths() 方法為下面的內(nèi)容畦木,那么接口文檔將只會展示 /user/add 和 /user/find/{id} 兩個接口袖扛。
清單 11. 使用 Docket 配置接口篩選
.apis(RequestHandlerSelectors.basePackage("cn.itweknow.sbswagger.controller"))
.paths(Predicates.or(PathSelectors.ant("/user/add"),
PathSelectors.ant("/user/find/*")))
圖 3. 經(jīng)過篩選過后的 Swagger 文檔界面
自定義響應(yīng)消息
Swagger 允許我們通過 Docket 的 globalResponseMessage() 方法全局覆蓋 HTTP 方法的響應(yīng)消息,但是首先我們得通過 Docket 的 useDefaultResponseMessages 方法告訴 Swagger 不使用默認的 HTTP 響應(yīng)消息,假設(shè)我們現(xiàn)在需要覆蓋所有 GET 方法的 500 和 403 錯誤的響應(yīng)消息蛆封,我們只需要在 SwaggerConfig.java 類中的 Docket Bean 下添加如下內(nèi)容:
清單 12. 自定義響應(yīng)消息
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET, newArrayList(
new ResponseMessageBuilder()
.code(500)
.message("服務(wù)器發(fā)生異常")
.responseModel(new ModelRef("Error"))
.build(),
new ResponseMessageBuilder()
.code(403)
.message("資源不可用")
.build()
));
添加如上面的代碼后唇礁,如下圖所示,您會發(fā)現(xiàn)在 SwaggerUI 頁面展示的所有 GET 類型請求的 403 以及 500 錯誤的響應(yīng)消息都變成了我們自定義的內(nèi)容惨篱。
圖 4. 自定義響應(yīng)消息
Swagger UI 的使用
接口查看
SwaggerUI 會以列表的方式展示所有掃描到的接口盏筐,初始狀態(tài)是收縮的,我們只需要點擊展開就好砸讳,而且會在左邊標(biāo)識接口的請求方式(GET琢融、POST、PUT绣夺、DELETE 等等)吏奸。
圖 5. Swagger 接口列表界面
接口調(diào)用
如下圖所示,點擊接口展開后頁面右上角的 Try it out 按鈕后陶耍,頁面會變成如圖所示:
圖 6. 接口詳情界面
SwaggerUI 會給我們自動填充請求參數(shù)的數(shù)據(jù)結(jié)構(gòu)奋蔚,我們需要做的只是點擊 Execute 即可發(fā)起調(diào)用
圖 7. 接口調(diào)用界面
Model
如下圖所示,SwaggerUI 會通過我們在實體上使用的 @ApiModel 注解以及@ApiModelProperty 注解來自動補充實體以及其屬性的描述和備注烈钞。
圖 8. 實體界面
相關(guān)注解說明
在本章節(jié)中我將給出一些 Swagger 中常用的注解以及其常用的屬性泊碑,并對其一一解釋,方便您查看毯欣。
Controller 相關(guān)注解
@Api: 可設(shè)置對控制器的描述馒过。
表 1. @Api 主要屬性
注解屬性 | 類型 | 描述 |
---|---|---|
tags | String[] | 控制器標(biāo)簽。 |
description | String | 控制器描述(該字段被申明為過期)酗钞。 |
接口相關(guān)注解
- @ApiOperation: 可設(shè)置對接口的描述腹忽。
表 2. @ApiOperation 主要屬性
注解屬性 | 類型 | 描述 |
---|---|---|
value | String | 接口說明。 |
notes | String | 接口發(fā)布說明砚作。 |
tags | Stirng[] | 標(biāo)簽窘奏。 |
response | Class<?> | 接口返回類型。 |
httpMethod | String | 接口請求方式葫录。 |
@ApiIgnore: Swagger 文檔不會顯示擁有該注解的接口着裹。
@ApiImplicitParams: 用于描述接口的非對象參數(shù)集。
@ApiImplicitParam: 用于描述接口的非對象參數(shù)米同,一般與 @ApiImplicitParams 組合使用骇扇。
表 3. @ApiImplicitParam 主要屬性
注解屬性 | 描述 |
---|---|
paramType | 查詢參數(shù)類型,實際上就是參數(shù)放在那里面粮。取值:path:以地址的形式提交數(shù)據(jù)少孝,根據(jù) id 查詢用戶的接口就是這種形式傳參。query:Query string 的方式傳參熬苍。header:以流的形式提交韭山。form:以 Form 表單的形式提交。 |
dataType | 參數(shù)的數(shù)據(jù)類型。取值:Long钱磅、String |
name | 參數(shù)名字梦裂。 |
value | 參數(shù)意義的描述。 |
required | 是否必填盖淡。取值:true:必填參數(shù)年柠。false:非必填參數(shù)。 |
Model 相關(guān)注解
- @ApiModel: 可設(shè)置接口相關(guān)實體的描述褪迟。
- @ApiModelProperty: 可設(shè)置實體屬性的相關(guān)描述冗恨。
表 4. @ApiModelProperty 主要屬性
注解屬性 | 類型 | 描述 |
---|---|---|
value | String | 字段說明。 |
name | String | 重寫字段名稱味赃。 |
dataType | Stirng | 重寫字段類型掀抹。 |
required | boolean | 是否必填。 |
example | Stirng | 舉例說明心俗。 |
hidden | boolean | 是否在文檔中隱藏該字段傲武。 |
allowEmptyValue | boolean | 是否允許為空。 |
allowableValues | String | 該字段允許的值城榛,當(dāng)我們 API 的某個參數(shù)為枚舉類型時揪利,使用這個屬性就可以清楚地告訴 API 使用者該參數(shù)所能允許傳入的值。 |
結(jié)束語
在本教程中狠持,我們學(xué)會了如何使用 Swagger 2 來生成 Spring Boot REST API 的文檔疟位。我們還研究了如何過濾 API、自定義 HTTP 響應(yīng)消息以及如何使用 SwaggerUI 直接調(diào)用我們的 API喘垂。您可以在 Github 上找到本教程的完整實現(xiàn)甜刻,這是一個基于 IntelliJ IDEA 的項目,因此它應(yīng)該很容易導(dǎo)入和運行正勒,當(dāng)然如果您想對本教程做補充的話歡迎發(fā)郵件給我 (mynamecoder@163.com) 或者直接在 GitHub 上提交 Pull Request得院。
參考資源
Spring 指南
Spring 主頁
Spring Boot 參考指南
Swagger 主頁
本文源碼地址