SpringBoot使用Swagger2實現接口API文檔
一、前言
前後端分離的項目開發中,後臺寫好的接口在跟前端對接測試的時候,往往很麻煩,需要自己編寫接口文檔,接口參數,響應數據等等。當接口更改後,又要手動去更改接口文檔,久而久之就會忘記或者搞得接口和文檔不一致。Swagger的誕生就是爲了解決這個痛點,本文基於SpringBoot搭建Swagger2,更多的Swagger的版本區別啊,原理啊這裏不多做贅述,直接上手。
本文檔是根據網上巨多網友的分享整理出來博主覺得有用和自己的意見,歡迎交流。
本文檔demo項目已在github,需要的朋友請訪問查看,歡迎star https://github.com/AggerChen/spring-boot-swagger2-demo
二、快速上手
2.1 pom依賴
只展示重要依賴,其他的信息省略,需要查看完整的pom.xml請訪問github下載源代碼查看。
pom.xml
<!--web依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--熱部署依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--lombok工具-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- apache工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<!--swagger依賴-->
<dependency><!--添加Swagger依賴 -->
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency><!--添加Swagger-UI依賴 -->
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.2 添加swagger配置類
在項目中創建一個swagger2配置來,用來填寫默認配置。
添加類註解@EnableSwagger2表示開始swagger2配置。
添加類註解@Configuration表示是springBoot配置類
Swagger2Config.java
package com.agger.swagger2Demo.config;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @program: Swagger2Config
* @description: swagger配置類
* @author: chenhx
* @create: 2019-11-25 14:14
**/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Value("${swagger2.enable}")
private boolean enable; // 配置文件參數注入,用來表示是否開啓API文檔
@Bean("userApis")
public Docket userApis() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("用戶模塊") // 分組
.select()
// .apis(RequestHandlerSelectors.basePackage("com.agger.swagger2Demo.controller")) // 匹配包路徑
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) // 匹配包含的指定註解
// .paths(PathSelectors.regex("/user.*"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.enable(enable); // 是否開啓API
}
@Bean("deptApis")
public Docket deptApis() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("部門模塊")
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.regex("/dept.*"))
.build()
.apiInfo(apiInfo())
.enable(enable);
}
/**
* 編寫apiInfo配置
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API接口接口文檔測試項目")
.description("描述:編寫一個基於springBoot的swagger2接口文檔測試demo")
.contact(new Contact("agger",null,null))
.version("1.0.0")
.build();
}
}
- 其中 @Value("${swagger2.enable}")表示從項目application.yml或application.properties中獲取配置數據,用來控制是否顯示API文檔,因爲我們一般只在開發和測試環境中需要文檔接口,生產環境則需要禁用。你還可以使用profile配置來做成不同的配置,這裏就簡單演示一下,如下:
application.yml
# 是否開啓swagger API文檔
swagger2:
enable: true
- 可以編寫多個@Bean(“deptApis”) 來注入多個分組文檔,在文檔的html右上角 Select a spec 可以分組查看。
2.3 編寫contoller
爲了將controller中的接口形成文檔,我們需要在controller類上、接口方法上、甚至model類上添加swagger相關注解。
其中最常用的註解有如下:
-
@Api : 作用在controller類上描述類作用
tags=“說明該類的作用,可以在UI界面上看到的描述信息”
value=“該參數沒什麼意義,不需要配置”示例:@Api(value=“用戶管理”,tags = “用戶管理控制”)
-
@ApiOperation :作用在接口方法上,用於描述接口說明,可以在UI上看到做區分
value=“方法標題”
notes=“方法的備註說明”示例:@ApiOperation(value=“新增用戶”)
-
@ApiImplicitParam:作用在接口方法上,用於描述接口參數信息(只適用於單一參數,不適用與多參數和model對象參數)
name=“參數名”
value=“參數的漢字說明、解釋”
required=“參數是否必須傳”
paramType=“參數放在哪個地方”
· header --> 請求參數的獲取:@RequestHeader
· query --> 請求參數的獲取:@RequestParam
· path(用於restful接口)–> 請求參數的獲取:@PathVariable
· body(不常用)
· form(不常用)
dataType=“參數類型,默認String,其它值dataType=Integer”
defaultValue=“參數的默認值”示例:@ApiImplicitParam(name = “userId”, value = “用戶id”,required=true)
-
@ApiImplicitParams:作用在接口方法上,用於描述多個參數信息,與@@ApiImplicitParam一起使用
示例:
@ApiImplicitParams({
@ApiImplicitParam(name=“mobile”,value=“手機號”,required=true),
@ApiImplicitParam(name=“password”,value=“密碼”,required=true),
@ApiImplicitParam(name=“age”,value=“年齡”,required=true,dataType=“Integer”)
}) -
@ApiModel:作用在model類上,用於接口參數是model對象時,使用@RequestBody場景,方便swagger解析成api文檔
value="model類名稱
description=“model類詳細描述”示例:@ApiModel(“用戶類”)
-
@ApiModelProperty:作用在model屬性上,用於描述屬性字段基本信息
value=“字段名稱”
notes=“字段具體描述”
required=“是否必須”
example=“示例值”示例:@ApiModelProperty(value = “用戶姓名”,required = true,example = “張三”,notes = “用戶姓名”)
-
@ApiResponse :作用在接口方法上,用於描述接口錯誤響應
code=“響應狀態碼,比如400”
message=“響應信息,比如’請求參數錯誤’”
response=“拋出異常的類”示例:@ApiResponse(code=400,message = “參數錯誤”)
-
@ApiResponses:作用在接口方法上,表示一組錯誤響應,與@ApiResponse結合使用
示例:
@ApiResponses({
@ApiResponse(code=400,message = “參數錯誤”),
@ApiResponse(code=405,message = “確實參數”)
}) -
@ApiParam :作用在接口參數上,用於描述接口參數信息。此註解對代碼入侵比較大,建議使用@ApiImplicitParam作用在方法上,來保持代碼的簡潔
name=“參數名稱”
value=“參數的說明”
required=true 是否必須
示例:
@ApiOperation("查詢用戶")
@PostMapping("queryUser")
public ResultVO<UserVO> queryUser(
@RequestBody
@ApiParam(name="用戶id",value="傳入用戶id",required=true) Long userId){
...
}
接下來展示一個完整的UserController.java
UserController.java
package com.agger.swagger2Demo.controller;
import com.agger.swagger2Demo.vo.ResultVO;
import com.agger.swagger2Demo.vo.UserVO;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @program: UserController
* @description: 用戶管理控制類
* @author: chenhx
* @create: 2019-11-25 14:20
**/
@Api(value="用戶管理",tags = "用戶管理控制")
@RestController
@RequestMapping("/user")
public class UserController {
private final static List<UserVO> userList = new ArrayList<>();
{
userList.add(new UserVO(1L,"張三",20,"[email protected]",new Date()));
userList.add(new UserVO(2L,"李四",25,"[email protected]",new Date()));
}
@ApiOperation("查詢用戶列表")
@GetMapping("/list")
public ResultVO<List<UserVO>> getUserList(){
ResultVO result = new ResultVO();
result.setCode(0);
result.setMsg("查詢成功");
result.setData(userList);
return result;
}
/**
* @Title: addUser
* @Description: 參數傳入一個model對象,不需要使用其他註解描述此類參數,只需要在model類中使用類註解
* @author chenhx
* @date 2019-11-26 17:12:18
*/
@ApiOperation("新增用戶")
@PostMapping("/add")
public ResultVO addUser(@RequestBody UserVO user){
if(user!=null){
userList.add(user);
}
ResultVO result = new ResultVO();
result.setCode(0);
result.setMsg("新增成功");
return result;
}
/**
* @Title: queryUserById
* @Description: 使用@ApiParam註解在方法參數上寫參數的說明,對代碼入侵比較高
* @author chenhx
* @date 2019-11-26 17:09:36
*/
@ApiOperation("通過id查詢用戶")
@PostMapping("/queryUserById")
public ResultVO<UserVO> queryUserById(
@RequestBody
@ApiParam(name="用戶id",value="傳入用戶id",required=true) Long userId){
UserVO u = null;
if(userId!=null){
for(UserVO user:userList){
if(user.getUserId()==userId){
u = user;
break;
}
}
}
ResultVO result = new ResultVO();
if(u==null){
result.setCode(-1);
result.setMsg("查詢的用戶不存在");
}else{
result.setCode(0);
result.setMsg("查詢成功");
result.setData(u);
}
return result;
}
/**
* @Title: queryUserByName
* @Description: 使用@ApiImplicitParam註解只在方法上描述參數,對源代碼沒有侵入,比較推薦
* @author chenhx
* @date 2019-11-26 17:09:36
*/
@ApiOperation("通過name查詢用戶")
@ApiImplicitParam(name = "用戶userName",value = "傳入用戶userName",required = true)
@PostMapping("/queryUserByName")
public ResultVO<UserVO> queryUserByName(@RequestBody String userName){
UserVO u = null;
if(StringUtils.isNotBlank(userName)){
for(UserVO user:userList){
if(userName.equals(user.getUserName())){
u = user;
break;
}
}
}
ResultVO result = new ResultVO();
if(u==null){
result.setCode(-1);
result.setMsg("查詢的用戶不存在");
}else{
result.setCode(0);
result.setMsg("查詢成功");
result.setData(u);
}
return result;
}
/**
* @Title: queryUserEmail
* @Description: 參數在路徑中的接口方法,需要指定@ApiImplicitParam屬性paramType爲path
* @author chenhx
* @date 2019-11-26 17:09:36
*/
@ApiOperation("查詢用戶的email")
@PostMapping("/queryUserEmail/{id}")
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "long", paramType = "path")
public ResultVO<String> queryUserEmail( @PathVariable("id") Long userId){
String email = null;
if(userId!=null){
for(UserVO user:userList){
if(user.getUserId()==userId){
email = user.getEmail();
break;
}
}
}
ResultVO result = new ResultVO();
if(StringUtils.isBlank(email)){
result.setCode(-1);
result.setMsg("查詢的用戶不存在");
}else{
result.setCode(0);
result.setMsg("查詢成功");
result.setData(email);
}
return result;
}
}
接口如果是多參數的話,示例如下:
/**
* @Title: addDept
* @Description: 接口多參數使用方式
* @author chenhx
* @date 2019-11-26 20:55:56
*/
@ApiOperation("新增部門")
@ApiImplicitParams({
@ApiImplicitParam(name = "deptId",value = "部門id",required = true),
@ApiImplicitParam(name = "deptName",value = "部門名稱",required = true)
})
@PostMapping("/add")
public ResultVO addDept(Long deptId,String deptName){
ResultVO result = new ResultVO();
if(deptId!=null&& StringUtils.isNotBlank(deptName)){
deptList.add(new DeptVO(deptId,deptName));
result.setCode(0);
result.setMsg("新增成功");
}else{
result.setMsg("新增失敗");
}
return result;
}
示例中有使用到響應類如下:
ResultVO.java
package com.agger.swagger2Demo.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: ResultVO
* @description: 接口響應類,也需要用@ApiModel修飾起來,才能在API中查看具體的返回值
* @author: chenhx
* @create: 2019-11-25 14:26
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("響應實體")
public class ResultVO<T> {
@ApiModelProperty("返回狀態碼")
private Integer code = -1; // 返回狀態碼
@ApiModelProperty("返回信息")
private String msg; // 返回信息
@ApiModelProperty("返回數據")
private T data; // 返回數據
}
2.4 訪問UI查看生成的API
啓動項目,訪問地址 http://localhost:8080/swagger-ui.html 就可以查看到我們的API文檔了。
- 如果在配置文件中配置了多個@Bean分組,則在右上角可以切換分組顯示接口API
- 接口參數爲model類型,如果model中有寫example字段,則可以方便的顯示請求示例。
- 點擊每個方法的 “Try it out” 按鈕,則可以立即測試接口
- 參數在路徑中方式的接口,也可以只管的查看到參數說明
- 在接口的最下面有個Models分類,裏面存放的是當前組中的model示例,方便前端人員查看字段。
- 接口多參數,分model方式的接口
2.5 注意事項
- 想要接口和接口的響應中有具體的字段,則你的model必須使用@ApiModel註解表示,包括響應實體ResultVO。
- 儘量不要在方法參數上使用註解@ApiParam來描述參數使用@ApiImplicitParam來替代,儘量保持原接口的整潔。
- 本示例使用的是Swagger2,所以請注意你的版本是否跟我一致。
三、github示例地址
本文檔是根據網上巨多網友的分享整理出來博主覺得有用和自己的意見,歡迎交流
本文檔所使用的demo已經在github中,需要的請下載查看,歡迎star
https://github.com/AggerChen/spring-boot-swagger2-demo