背景
我们公司接口管理工具用的是Yapi,但是Yapi还是需要后端开发人员分配较多额外的精力去维护接口文档的信息,于是就产生了这篇博客。
Swagger简介
Swagger是一个简单但功能强大的API表达工具。它具有地球上最大的API工具生态系统,数以千计的开发人员,使用几乎所有的现代编程语言,都在支持和使用Swagger。使用Swagger生成API,我们可以得到交互式文档,自动生成代码的SDK以及API的发现特性等。
Swagger原生的测试接口功能是和相应业务项目绑定的,对于我们公司来说测试环境有多台服务器,所以项目部署服务器可能会随时更换,这样Swagger测试UI地址也就随着经产变更了,这会对前端人员造成困惑。而且Yapi的接口测试功能要比Swagger要丰富,而且还支持mock。所以,我们只用Swagger的文档自动生成功能,然后把接口文档导入Yapi。
Swagger Demo
SpringBoot+Swagger
pom.xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
对于Java来说,目前springfox是最好的选择,它内部会自动解析Spring容器中Controller暴露出的接口,并且也提供了一个界面用于展示或调用这些API(由于我们不用Swagger的接口测试功能,所以并没有引用相应依赖)。
Swagger2配置类
package com.demo.hello;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author: 云若
* @date: 2018/8/30
*/
@Configuration
@EnableSwagger2
@ConfigurationProperties(prefix = "swagger")
public class Swagger2 {
private static final String BASE_PACKAGE = "com.demo";
@Value("${swagger.enable}")
private boolean enableSwagger;
@Bean
public Docket helloDocket() {
return new Docket(DocumentationType.SWAGGER_2)
//用于分组功能
.groupName("hello")
//注册整体api信息
.apiInfo(apiInfo())
//swagger功能是否启用
.enable(enableSwagger)
.select()
//指定扫描的包
.apis(RequestHandlerSelectors.basePackage(BASE_PACKAGE))
//设置此组只匹配hello/**的请求
.paths(PathSelectors.ant("/hello/**"))
.build();
}
@Bean
public Docket testDocket() {
return new Docket(DocumentationType.SWAGGER_2).groupName("test")
.apiInfo(apiInfo())
.enable(enableSwagger)
.select()
.apis(RequestHandlerSelectors.basePackage(BASE_PACKAGE))
.paths(PathSelectors.ant("/test/**"))
// .paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Spring Boot中使用Swagger2构建RESTful APIs")
.description("test")
.contact(new Contact("yunruo", "", ""))
.version("1.0.0")
.build();
}
}
本配置考虑了我们公司需要以及可能需要的功能
分组功能。开发新接口时可能已经有很多老接口,但是我们可能只想往Yapi上传本次新开发的接口信息。可以用Swagger的分组功能,指定某个分组只匹配我们新开发的接口路径,然后只获取这个分组的接口信息。比如说我想获得hello分组的接口信息(项目ip:端口/v2/api-docs?group=分组名):
http://localhost:8080/v2/api-docs?group=hello
动态开关Swagger接口功能。在生产环境出于安全角度考虑,我们需要关闭Swagger接口功能。在测试环境,我们需要开启以生成接口文档。
Swagger本身提供开关功能,再加上Spring Boot或者Maven的多环境配置功能就可以做到。
application.yml配置:
swagger:
enable: true
接口代码
HelloController
package com.demo.hello;
import com.demo.test.TestResp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
@RestController
@Api(value = "hello相关接口", description = "hello")
public class HelloController {
@ApiOperation(value = "欢迎接口", notes = "欢迎接口",response = TestResp.class)
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public TestResp hello(@ApiParam(value = "hello", required = true)
@RequestParam(required = true)String index,@ApiParam(value = "hello", required = true)
@RequestParam(required = true)String index2) {
return new TestResp();
}
}
TestController
package com.demo.test;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: 云若
* @date: 2018/8/30
*/
@RestController
@Api(value = "test相关接口", description = "test")
public class TestController {
@ApiOperation(value = "test接口", notes = "test接口", response = TestResp.class)
@RequestMapping(value = "/test", method = RequestMethod.POST)
public TestResp test(@RequestBody TestParam testParam) {
return new TestResp();
}
}
TestParam
package com.demo.test;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* @author: 云若
* @date: 2018/8/30
*/
@ApiModel(value = "test", description = "test参数")
public class TestParam {
@ApiModelProperty(value = "名字", required = true, dataType = "string")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
TestResp
package com.demo.test;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* @author: 云若
* @date: 2018/8/30
*/
@ApiModel(value = "test", description = "test响应")
public class TestResp {
@ApiModelProperty(value = "欢迎语",dataType = "string")
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
更多注解应用参考:https://github.com/swagger-api/swagger-core/wiki/annotations
到这里SpringBoot+Swagger的配置就完了。
SpringMVC+Swagger
公司有很多老项目还没用SpringBoot,所以也调研了一下SpringMVC+Swagger的配置方式。网上的教程有一些坑,很多是是而非的点,经测试以下应该是最简配置。
pom.xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
Swagger版本是最新版本,guava和jackson版本是依据Swagger的最新版本配置的。
Swagger2配置类
该配置类和上面的SpringBoot+Swagger的配置方式相同,只是类上注解不同,代码引用配置文件属性的方式也大同小异,在此只贴出注解配置。
@Configuration
@EnableWebMvc
@EnableSwagger2
@PropertySource(value = "classpath:sys.properties")
接口代码
注解的使用方式也和上面相同,略过。
Swagger数据导入Yapi
获取接口信息
经过上面的配置,调用http://localhost:8080/v2/api-docs?group=test,可以得到以下数据,把它保存在一个json文件里(我们目前的Yapi版本只支持文件上传)。
{
"swagger": "2.0",
"info": {
"description": "test",
"version": "1.0.0",
"title": "Spring Boot中使用Swagger2构建RESTful APIs",
"contact": {
"name": "yunruo"
}
},
"host": "localhost:8080",
"basePath": "/",
"tags": [
{
"name": "test-controller",
"description": "test"
}
],
"paths": {
"/test": {
"post": {
"tags": [
"test-controller"
],
"summary": "test接口",
"description": "test接口",
"operationId": "testUsingPOST",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"in": "body",
"name": "testParam",
"description": "testParam",
"required": true,
"schema": {
"$ref": "#/definitions/test"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/test"
}
},
"201": {
"description": "Created"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
},
"deprecated": false
}
}
},
"definitions": {
"test": {
"type": "object",
"required": [
"name"
],
"properties": {
"message": {
"type": "string",
"description": "欢迎语"
},
"name": {
"type": "string",
"description": "名字"
}
},
"title": "test",
"description": "test参数"
}
}
}
Yapi数据导入
下面还有个开启数据同步开关。建议更新以前的接口文档时开启,新增时关闭。
源代码地址
springmvc-swagger
之前虽然有简单使用过Swagger,但是并没有仔细研究过,所以文章描述可能有错或者不准确。文章中有错误欢迎指正,使用中有疑问欢迎讨论。