Swagger使用
一、Swagger介绍
1.1 swagger
Swagger3 是一套基于 OpenAPI 规范(OpenAPI Specification,OAS)构建的开源工具,后来成为了 Open API 标准的主要定义者。对于 Rest API 来说很重要的一部分内容就是文档,Swagger 为我们提供了一套通过代码和注解自动生成文档的方法,这一点对于保证API 文档的及时性将有很大的帮助。
swagger2于17年停止维护,现在最新的版本为17年发布的 Swagger3(Open Api3)。
swagger2需要两个依赖自动生成文档springfox-swagger2
和springfox-swagger-ui
-
springfox-swagger2:自动生成描述API的json文件
-
springfox-swagger-ui:将描述API的json文件解析出来,然后以ui界面的方式展示。
1.2 springfox
SpringFox是 spring 社区维护的一个项目(非官方)由于Spring的流行,Marty Pitt编写了一个基于Spring的组件swagger-springmvc,用于将swagger集成到springmvc中来,而springfox则是从这个组件发展而来。
二、Swagger2入门使用
2.1 创建项目
注意springboot版本,我这里选的2.5.6,版本太高启动会报错,后面会提到具体问题。
2.2 引入swagger2.9.2
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.3 创建SwaggerConfig
通过@EnableSwagger2
开启swagger,然后配置需要生成文档的包名,以及作者,描述信息等内容。
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket buildDocket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(buildApiInf())
.select()
//指定包下的类生成接口文档
.apis(RequestHandlerSelectors.basePackage("com.depart"))
//包含ApiOperation注解的类,才生成接口文档
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(setHeaderToken());//请求头中添加token,便于接口测试
}
private ApiInfo buildApiInf(){
return new ApiInfoBuilder()
.title("xxx系统")
.description("这是一个用于测试swagger2的项目")
.contact(new Contact("wangzhen", "", "214556924@qq.com"))
.version("1.0.0")
.build();
}
private List<Parameter> setHeaderToken() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name("Access-Token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
return pars;
}
}
2.4 创建对应测试类
User类
@Data
@ApiModel(value = "User", description = "账户")
public class User {
@ApiModelProperty(value = "用户ID")
private String userId;
@ApiModelProperty(value = "用户名")
private String userName;
}
Controller类
@Api(value = "user", tags="用户管理")
@RestController
@RequestMapping("/user")
public class UserController {
@ApiOperation(value = "根据用户ID获取用户信息", response = User.class, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@GetMapping(value = "getUserById")
public User getUserById(
@ApiParam(required = true, name = "userId", value = "用户ID")
@RequestParam(value = "userId", required = true) String userId,
@ApiParam(required = false, name = "userName", value = "用户名")
@RequestParam(value = "userName", required = false) String userName
){
return new User();
}
@ApiOperation(value = "根据用户ID获取用户信")
@PostMapping(value = "addUser")
public void addUser(User user){
}
@ApiOperation(value = "更新用户信息")
@PostMapping(value = "updateUser")
public void updateUser(User user){
}
@ApiOperation(value = "删除用户")
@PostMapping(value = "deleteUser")
@ApiImplicitParams({
@ApiImplicitParam(name="userId",value="用户ID",required=true)
})
public void deleteUser(String userId) {
}
}
2.5 查看接口文档
通过访问localhost:8080/swagger-ui.html
查看,可以看到分为两部分,一部分是接口,另一部分是Model层。
Models部分很简单,重点看一下接口部分,展开如下图,可以看到@ApiOperation的value对应这下边的描述。
接口测试,点击右上角Try it out
后,如下图,第一个参数Access-Token为请求头中的参数,这样测试会有点麻烦,如果不需要可以在SwaggerConfig
类中删除,当然也有更优雅的方式,后面会提到。由于我们给User类配置了@ApiModel,所以参数User类就变成了一个一个参数形式。
对于单个参数,可以通过@ApiParam来标记
单个或多个参数也可以使用@ApiImplicitParams
,@ApiImplicitParam
来统一标记。
2.6 小结与补充
以上部分是swagger常见的使用方式,以及常见swagger注解。
-
其中注解本身还有很多其他参数,其他参数说明可以参考这篇博客swagger2 注解说明_那年那些事儿-CSDN博客_swagger注解。
-
关于springboot版本问题,选用
springboot2.6.4
配上swagger2.9.2
会报错,错误如下,所以可以选择springboot2.5.6
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
-
从
swagger2.8.0
开始界面发生了较大的改变,但注解等关键内容变化不大。下面是swagger2.7.0
的样式。
三、Swagger3使用
3.1 创建项目
注意springboot版本,我这里选的2.5.6,版本太高启动会报错,后面会提到具体问题。
编写application.yml文件
spring:
application:
name: xxx系统
server:
port: 8081
# ===== 自定义swagger配置 ===== #
swagger:
enable: true
application-name: ${spring.application.name}
application-version: 1.0.0
application-description: 这是一个用于测试swagger2的项目
try-host: http://localhost:${server.port}
3.2 引入swagger3.0.0
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
3.3 创建Swagger配置类
通过@EnableOpenApi
或@EnableSwagger2
都可以开启swagger,然后配置需要生成文档的包名,以及作者,描述信息等内容。
@Configuration
//@EnableOpenApi//也可以不加,通过配置文件的enable参数控制
public class SwaggerConfig {
private final SwaggerProperties swaggerProperties;
public SwaggerConfig(SwaggerProperties swaggerProperties) {
this.swaggerProperties = swaggerProperties;
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30).pathMapping("/")
// 定义是否开启swagger,false为关闭,可以通过变量控制
.enable(swaggerProperties.getEnable())
// 将api的元信息设置为包含在json ResourceListing响应中。
.apiInfo(apiInfo())
// 接口调试地址
.host(swaggerProperties.getTryHost())
// 选择哪些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
// 支持的通讯协议集合
.protocols(newHashSet("https", "http"))
// 授权信息设置,必要的header token等认证信息
.securitySchemes(securitySchemes())
// 授权信息全局应用
.securityContexts(securityContexts());
}
/**
* API 页面上半部分展示信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title(swaggerProperties.getApplicationName() + " Api Doc")
.description(swaggerProperties.getApplicationDescription())
.contact(new Contact("wangzhen", null, "214556924@qq.com"))
.version("Application Version: " + swaggerProperties.getApplicationVersion() + ", Spring Boot Version: " + SpringBootVersion.getVersion())
.build();
}
/**
* 设置授权信息
*/
private List<SecurityScheme> securitySchemes() {
ApiKey apiKey = new ApiKey("ACCESS_TOKEN", "token", In.HEADER.toValue());
return Collections.singletonList(apiKey);
}
/**
* 授权信息全局应用
*/
private List<SecurityContext> securityContexts() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
.build()
);
}
@SafeVarargs
private final <T> Set<T> newHashSet(T... ts) {
if (ts.length > 0) {
return new LinkedHashSet<>(Arrays.asList(ts));
}
return null;
}
}
@Component
@ConfigurationProperties("swagger")
public class SwaggerProperties {
/**
* 是否开启swagger,生产环境一般关闭,所以这里定义一个变量
*/
private Boolean enable;
/**
* 项目应用名
*/
private String applicationName;
/**
* 项目版本信息
*/
private String applicationVersion;
/**
* 项目描述信息
*/
private String applicationDescription;
/**
* 接口调试地址
*/
private String tryHost;
//……省略getter和setter
}
3.4 查看接口文档
Controller还是原来的代码,通过访问localhost:8081/swagger-ui/index.html
查看,可以看到分为两部分,一部分是接口,另一部分是Schemas层。
效果差不多,不过3.0可以添加有全局token。
3.5 小结与补充
swagger3与swagger2的主要区别
-
配置类上添加的注解是@EnableOpenApi,swagger2是@EnableSwagger2
-
访问地址
http://localhost:8080/swagger-ui/index.html
,swagger2是http://localhost:8080/swagger-ui.html
-
pom引入只需
springfox-boot-starter
,swagger2有两个springfox-swagger2
和springfox-swagger-ui
四、版本问题和最佳实践
4.1 版本问题
在整合swagger时,经常会遇到版本问题,不过很好解决。这里记录一下之前遇到的一些版本问题。比如之前从swagger1升级到swagger2和学习过程中遇到的一些问题。
- spring 4.3.29 + swagger2.9.2
导包时swagger-models会有问题,需要使用swagger-models1.5.22
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<!-- 排除自带的1.5.20版本-->
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 使用1.5.22-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.22</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
- spring 4.1.16 + swagger2.6.1
使用tags会出现不能展开子接口详情问题
@Api(value = "user", tags = "用户管理")
@Controller
@RequestMapping("user")
public class UserController extends BaseController {}
description参数已被弃用,利用swagger2word导出之后的是接口名是英文
@Api(value = "user", description = "用户管理")
@Controller
@RequestMapping("apply")
public class UserController extends BaseController {}
- springboot2.6.x + swagger2.9.2问题
…………
4.2 最佳实践
就目前而言,使用SpringBoot 2.2.x - 2.5.x能很好整合swagger2和swagger3。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<swagger2.version>2.9.2</swagger2.version>
<swagger-models.version>1.6.0</swagger-models.version>
<swagger-annotations.version>1.6.0</swagger-annotations.version>
</properties>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<!--解决Swagger 2.9.2版本NumberFormatException-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger-models.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations.version}</version>
</dependency>
五、swagger文档转word
工作中经常会需要word形式的接口文档,这里推荐一个github地址和在线转换地址。
只需要获取文档接口json数据的地址就行。
swagger3:http://localhost:8081/v3/api-docs
swagger2:http://localhost:8081/v2/api-docs
Tips
注意这里只支持swagger2以上的版本,
GitHub - JMCuixy/swagger2word: 一个Swagger API 文档 转 Word 文档的工具项目