前言
隨着前後端分離架構和微服務架構的流行,我們使用Spring Boot來構建RESTful API項目的場景越來越多。通常我們的一個RESTful API就有可能要服務於多個不同的開發人員或開發團隊:IOS開發、Android開發、Web開發甚至其他的後端服務等。爲了減少與其他團隊平時開發期間的頻繁溝通成本,傳統做法就是創建一份RESTful API文檔來記錄所有接口細節,然而這樣的做法有以下幾個問題:
- 由於接口衆多,並且細節複雜(需要考慮不同的HTTP請求類型、HTTP頭部信息、HTTP請求內容等),高質量地創建這份文檔本身就是件非常喫力的事,下游的抱怨聲不絕於耳;
- 隨着時間推移,不斷修改接口實現的時候都必須同步修改接口文檔,而文檔與代碼又處於兩個不同的媒介,除非有嚴格的管理機制,不然很容易導致不一致現象;
爲了解決上面這樣的問題,Swagger2應運而生,通過將Swagger2整合到我們的Spring Boot應用中,我們可以快速的組織出強大RESTful API文檔,Swagger2大量的減少了我們創建文檔的工作量,同時通過簡單的Annotation將API說明內容整合入實現代碼中,讓維護文檔和修改代碼整合爲一體,可以讓我們在修改代碼邏輯的同時方便的修改文檔說明,進一步減少了我們維護文檔的成本。
本文將要介紹的是一個GitHub上的一個開源項目spring-boot-starter-swagger
。該項目主要利用Spring Boot的自動化配置特性,對Swagger2進行了進一步的封裝,更加簡化了我們在Spring Boot應用中整合Swagger2的步驟。
Swagger2 簡介
Swagger2是一款業界比較流行的實現RESTful API的文檔在線自動生成及RESTful API在線調試的工具。優點有:
- Swagger2可以輕鬆的整合到Spring Boot工程中,並與Spring MVC程序配合組織出強大RestFul接口文檔,通過在項目中引入Swagger,可以使用簡單的Annotation,就實現了接口文檔化;
- Swagger2既可以減少我們創建文檔的工作量,同時說明內容又整合入實現代碼中,讓維護文檔和修改代碼整合爲一體,可以讓我們在修改代碼邏輯的同時方便的修改文檔說明;
- Swagger2提供標準的json或yaml文檔,方便做進一步解析,典型應用是接口自動化測試;
- Swagger2也提供了強大的頁面測試功能來調試每個RESTful API,Swagger2頁面可以直接進行測試(try-it-out功能,部分替代Postman);
- Swagger還提供類似於github的SwaggerHub,相當於公共的API文檔集散地
Swagger2項目主頁:https://swagger.io/
spring-boot-starter-swagger 簡介
spring-boot-starter-swagger是一個GitHub上的一個開源項目,該項目主要利用Spring Boot的自動化配置特性來實現快速的將swagger2引入spring boot應用來生成API文檔,簡化原生使用swagger2的整合代碼。
- 源碼地址
- Demo地址:https://github.com/dyc87112/swagger-starter-demo
版本基礎
- SpringBoot版本:1.5.x
- Swagger版本:2.8.x
集成步驟
- 在
pom.xml
中引入依賴:
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
說明
1. 當前最新版本 1.9.0.RELEASE
;
2. 從1.6.0
版本開始,artifactId修改爲swagger-spring-boot-starter
,1.6.0
之前的版本不做修改,依然爲spring-boot-starter-swagger
;
- 在應用主類中增加
@EnableSwagger2Doc
註解
/**
*
* @ClassName: DemoApplication
* @Description: Demo應用啓動類
* @author YuanXu
* @date 2019年10月31日 上午10:53:23
*
*/
@EnableSwagger2Doc
@SpringBootApplication
public class DemoApplication {
/**
* @Title main
* @Description 測試應用啓動入口
* @author YuanXu
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
默認情況下就能產生所有當前Spring MVC加載的請求映射文檔。
參數配置
全局配置說明
swagger:
base-package: swagger掃描的基礎包,默認:全掃描
base-path: 需要處理的基礎URL規則,默認:/**
contact:
email: 維護人email
name: 維護人
url: 維護人URL
description: 描述
enabled: 是否啓用swagger,默認:true
exclude-path: 需要排除的URL規則,默認:空
globalOperationParameters:
- description: 描述信息
modelRef: 指定參數類型
name: 參數名
parameterType: 指定參數存放位置,可選header,query,path,body.form
required: 指定參數是否必傳,true,false
host: 文檔的host信息,默認:空
license: 許可證
licenseUrl: 許可證URL
termsOfServiceUrl: 服務條款URL
title: 標題
version: 版本
全局配置示例
swagger:
apply-default-response-messages: false # 取消使用默認預定義的響應消息,並使用自定義響應消息
base-package: com.yuanx
base-path: /**
contact:
email: [email protected]
name: YuanXu
url: https://blog.csdn.net/yx_222
description: Starter for swagger 2.x
enabled: true
exclude-path: /error, /ops/**
global-response-message:
get:
- code: 401
message: 頁面不存在
- code: 500
message: 系統內部錯誤
modelRef: ERROR
post:
- code: 500
message: 系統內部錯誤
modelRef: ERROR
globalOperationParameters:
- description: some description one
modelRef: string
name: name one
parameterType: header
required: true
- description: some description two
modelRef: string
name: name two
parameterType: body
required: false
license: Apache License, Version 2.0
licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.html
termsOfServiceUrl: https://github.com/dyc87112/spring-boot-starter-swagger
title: spring-boot-starter-swagger
version: 1.9.0.RELEASE
path規則說明
swagger.base-path
和swagger.exclude-path
使用ANT規則配置。
我們可以使用swagger.base-path
來指定所有需要生成文檔的請求路徑基礎規則,然後再利用swagger.exclude-path
來剔除部分我們不需要的。
例如:
management:
context-path: /ops
swagger:
base-path: /**
exclude-path: /ops/**, /error
上面的設置將解析所有除了/ops/開始以及spring boot自帶/error請求路徑。
其中,exclude-path
可以配合management.context-path=/ops
設置的spring boot actuator的context-path來排除所有監控端點。
分組配置說明
當我們一個項目的API非常多的時候,我們希望對API文檔實現分組。從1.2.0.RELEASE開始,將支持分組配置功能,具體配置內容如下:
swagger:
docket:
<name>:
base-package: swagger掃描的基礎包,默認:全掃描
base-path: 需要處理的基礎URL規則,默認:/**
contact:
email: 維護人email
name: 維護人
url: 維護人URL
description: 描述
exclude-path: 需要排除的URL規則,默認:空
globalOperationParameters:
- description: 描述信息
modelRef: 指定參數存放位置,可選header,query,path,body.form
name: 參數名
parameterType: 指定參數是否必傳,true,false
license: 許可證
licenseUrl: 許可證URL
modelRef: 指定參數類型
name: 參數名
parameterType: 指定參數存放位置,可選header,query,path,body.form
required: true=指定參數是否必傳,true,false
termsOfServiceUrl: 服務條款URL
title: 標題
version: 版本
<name>
爲swagger文檔的分組名稱,同一個項目中可以配置多個分組,用來劃分不同的API文檔。
分組配置示例
swagger:
docket:
group-a:
contact:
email: [email protected]
name: YuanXu
url: https://blog.csdn.net/yx_222
description: Starter for swagger 2.x
excludePath: /ops/**, /error
globalOperationParameters:
- description: some description three override
modelRef: string
name: name three
parameterType: header
termsOfServiceUrl: https://gitee.com/didispace/spring-boot-starter-swagger
title: group-a
basePackage: com.yuanxu.aaa
version: 1.3.0.RELEASE
group-b:
title: group-b
basePackage: com.yuanxu.bbb
version: 1.3.0.RELEASE
默認配置與分組配置可以一起使用。在分組配置中沒有配置的內容將使用默認配置替代,所以默認配置可以作爲分組配置公共部分屬性的配置。swagger.docket.aaa.globalOperationParameters[0].name
會覆蓋同名的全局配置。
公共參數配置說明
像每個接口都需要鑑權這種參數,可以在配置文件中統一定義,這樣省去每個接口再寫的麻煩,也能兼顧頁面的測試。
swagger:
global-operation-parameters:
- name: TOKEN
description: 鑑權
modelRef: string
parameterType: header
required: true # 公共參數寫成requierd, 對於不需要登錄的接口隨便寫一個字符串即可
忽略參數類型配置說明
基礎配置
swagger:
ignored-parameter-types:
- com.didispace.demo.User
- com.didispace.demo.Product
分組配置
swagger:
group-a:
ignored-parameter-types:
- com.didispace.demo.User
- com.didispace.demo.Product
自定義全局響應消息配置說明(1.6.0 + 支持)
支持 POST,GET,PUT,PATCH,DELETE,HEAD,OPTIONS,TRACE 全局響應消息配置,具體配置內容如下:
swagger:
apply-default-response-messages: false # 取消使用默認預定義的響應消息,並使用自定義響應消息
global-response-message:
get:
- code: 401
message: 401get
- code: 500
message: 500get
modelRef: ERROR
post:
- code: 500
message: 500post
modelRef: ERROR
UI功能配置說明(1.6.0 + 支持)
調試按鈕的控制(try it out)
swagger:
ui-config:
submit-methods: get,delete
該參數值爲提供調試按鈕的HTTP請求類型,多個用逗號分割,如果不想開啓調試功能,只需要如下設置即可:
swagger:
ui-config:
submit-methods:
其他配置
swagger:
ui-config:
json-editor: false # json編輯器
request-timeout: 5000 # 頁面調試請求的超時時間
show-request-headers: true # 顯示請求頭
更多配置說明見官方說明:https://github.com/SpringForAll/spring-boot-starter-swagger
使用Annotation添加API文檔內容
在整合完Swagger之後,在http://localhost:8080/swagger-ui.html
頁面中可以看到,關於各個接口的描述還都是英文或遵循代碼定義的名稱產生的。這些內容對用戶並不友好,所以我們需要自己增加一些說明來豐富文檔內容。我們通過@Api
,@ApiOperation
註解來給API增加說明、通過@ApiImplicitParam
、@ApiModel
、@ApiModelProperty
註解來給參數增加說明。
如下所示:
UserController.java 類
/**
*
* @ClassName: UserController
* @Description: 用戶管理Controller
* @author YuanXu
* @date 2019年10月31日 下午4:49:00
*
*/
@Api(tags = "用戶管理")
@RestController
@RequestMapping(value = "/users") // 通過這裏配置使下面的映射都在/users下
public class UserController {
/**
* 創建線程安全的Map,模擬users信息的存儲
*/
static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
@GetMapping("/")
@ApiOperation(value = "獲取用戶列表")
public List<User> getUserList() {
List<User> r = new ArrayList<>(users.values());
return r;
}
@PostMapping("/")
@ApiOperation(value = "創建用戶", notes = "根據User對象創建用戶")
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@GetMapping("/{id}")
@ApiOperation(value = "獲取用戶詳細信息", notes = "根據url的id來獲取用戶詳細信息")
public User getUser(@PathVariable Long id) {
return users.get(id);
}
@PutMapping("/{id}")
@ApiImplicitParam(paramType = "path", dataType = "Long", name = "id", value = "用戶編號", required = true, example = "1")
@ApiOperation(value = "更新用戶詳細信息", notes = "根據url的id來指定更新對象,並根據傳過來的user信息來更新用戶詳細信息")
public String putUser(@PathVariable Long id, @RequestBody User user) {
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return "success";
}
@DeleteMapping("/{id}")
@ApiOperation(value = "刪除用戶", notes = "根據url的id來指定刪除對象")
public String deleteUser(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
User.java 類
/**
*
* @ClassName: User
* @Description: 用戶 實體
* @author YuanXu
* @date 2019年10月31日 下午4:53:23
*
*/
@Data
@ApiModel(description = "用戶實體")
public class User {
@ApiModelProperty("用戶編號")
private Long id;
@ApiModelProperty("用戶姓名")
private String name;
@ApiModelProperty("用戶年齡")
private Integer age;
}
完成上述代碼添加後,啓動Spring Boot程序,訪問:http://localhost:8080/swagger-ui.html
,就能看到中文說明的文檔了。
API效果查看
打開API文檔頁面地址:http://localhost:8080/swagger-ui.html
API文檔JSON數據獲取地址:http://localhost:8080/v2/api-docs
Zuul整合Swagger2彙總API接口文檔
Zuul工程pom.xml
引入依賴
<!-- 引入 springboot parent ,幫我們實現了很多jar包的依賴管理 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 引入spring-cloud-starter-zuul的依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- 引入spring-cloud-starter-netflix-eureka-client的依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入swagger-spring-boot-starter的依賴 -->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
</dependencies>
添加DocumentationConfig.java
類
通過遍歷eureka路由方式自動添加所有微服務 API 文檔,SwaggerResourcesProvider 是資源提供者,我們重寫他,把各個微服務的API文檔資源路徑返回,註釋部分爲手動添加的方式。
/**
*
* @ClassName: DocumentationConfig
* @Description: Zuul整合Swagger2彙總API接口文檔
* @author YuanXu
* @date 2019年11月1日 上午10:30:37
*
*/
@Primary
@Component
public class DocumentationConfig implements SwaggerResourcesProvider {
private final RouteLocator routeLocator;
public DocumentationConfig(RouteLocator routeLocator) {
this.routeLocator = routeLocator;
}
/*
* (非 Javadoc)
* <p>Title: get </p>
* <p>遍歷eureka路由方式自動添加所有微服務API文檔</p>
* <p>Author: YuanXu </p>
* @return
* @see com.google.common.base.Supplier#get()
*/
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<SwaggerResource>();
List<Route> routes = routeLocator.getRoutes();
routes.forEach(route -> {
resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs"), "1.0"));
});
return null;
}
/*
* (非 Javadoc)
* <p>Title: get </p>
* <p>手動添加微服務API文檔</p>
* <p>Author: YuanXu </p>
* @return
* @see com.google.common.base.Supplier#get()
*/
/*
* @Override
* public List<SwaggerResource> get() {
* List resources = new ArrayList<>();
* resources.add(swaggerResource("基礎服務API文檔", "/yx-base-service/v2/api-docs", "1.0"));
* resources.add(swaggerResource("文件服務API文檔", "/yx-file-service/v2/api-docs", "1.0"));
* return resources;
* }
*/
private SwaggerResource swaggerResource(String name, String location, String version) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion(version);
return swaggerResource;
}
}
查看API整合效果
運行相關服務和zuul網關服務
瀏覽器輸入:http://localhost:8090/swagger-ui.html
可查看API文檔整合後的效果