title: swagger接口文档同步yapi定义标准
date: 2021-08-07 13:18:29
tags:
- 接口文档
- swagger
- yapi
categories: - [接口文档,swagger,yapi]
前提
在与前端约定yapi接口后,后端可能会与前端私下沟通修改接口方案或者业务调整未同步至yapi,导致经常性会出现实际开发接口与yapi维护的接口不统一的情况。滞后的接口文档,给后续介入开发的人员会造成很大的困惑,这也是这块未统一规范的体现。所以文章旨在通过一种定义标准(选型:swagger),通过实际开发中的代码生成yapi接口文档。一般情况下,联调接口会先于开发定义出来,所以需要定义两套文档,一套用于与前端或业务系统联调,另一套生成用于业务系统实际的开发接口。
swagger使用
配置swagger
以Swagger2为例,添加jar包
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
定义配置SwaggerConfig
@Configuration
@EnableSwagger2
public class SwaggerConfig {
}
输入ip:port/swagger-ui.html,默认swagger页面的结构
接口分类信息:例如可以区分定义外部接口和内部接口,用Swagger Docket实例的groupName分组显示
项目基本信息:通过Swagger Docket实例的apiInfo方法描述
接口列表:Swagger Docket实例中指定过滤条件后,Controller层所有接口的展示与调用
定义Docket实例
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docker(){
// 构造函数传入初始化规范,这是swagger2规范
return new Docket(DocumentationType.SWAGGER_2)
//apiInfo: 添加api详情信息,参数为ApiInfo类型的参数,这个参数包含了项目基本信息的必要条件
.apiInfo(apiInfo())
//groupName 指定接口的分组信息
.groupName("groupTest")
//配置是否启用Swagger,如果是false,在浏览器将无法访问。生产环境需要置为false
.enable(true)
.select()
//apis: 添加过滤条件,
//.apis(RequestHandlerSelectors.basePackage("com.swagger.demo"))
//paths: 这里是控制哪些路径的api会被显示出来,比如下方的参数就是除了/test以外的其它路径都会生成api文档
//.paths((String test) -> !a.equals("/test"))
.build();
}
private ApiInfo apiInfo(){
Contact contact = new Contact("项目名称:name", "项目连接地址:http://xxx.xxx.com/", "联系人邮箱:XXX");
return new ApiInfo(
"标题内容",
"描述内容",
"版本内容:v1.0",
"链接:http://terms.service.url/",
contact,
"许可",
"许可链接",
// 扩展信息
new ArrayList<>()
);
}
}
实体类定义
@ApiModel 用于swagger标记实体类
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
value | String | 类名 | 类的备用名称 |
description | String | “” | 类的详细描述 |
parent | Class<?> | Void.class | 提供父类以允许描述继承关系 |
discriminator | String | “” | 支持模型继承和多态,使用鉴别器的字段的名称,可以断言需要使用哪个子类型 |
subTypes | Class<?>[] | {} | 继承该类的子类型数组 |
reference | String | “” | 指定对应类型定义的引用,覆盖指定的任何其他元数据 |
@ApiModelProperty用于swagger标记实体类属性
属性 | 描述 |
---|---|
value | 简洁的介绍字段描述 |
name | 如果设置这个字段,会覆盖原本属性的名字 |
allowableValues | 标明字段的取值范围,例如range[1, infinity] 就是大于等于1 |
access | 允许从API文档中过滤属性,参见 io.swagger.core.filter.SwaggerSpecFilter |
notes | 应该是预留字段,未被使用 |
dataType | 参数的数据类型 |
required | 表示的是当前字段是否是必须的,默认是false |
position | 属性在文档中的位置排序 |
hidden | 表示的是是否隐藏当前字段,默认是false |
example | 样例说明 |
readOnly | 过时,用accessMode代替 |
accessMode | 一个枚举AccessMode 的值,其中包括AUTO 、READ_ONLY 、READ_WRITE |
reference | 指定了属性的类型引用,如果设置了当前属性,会覆盖任何其他的元数据(不常使用 ) |
allowEmptyValue | 是否允许该字段为空,默认是false |
extensions | 该属性用于进行额外的描述。是一个可选项的数组组成 |
样例说明
@Data
@ApiModel(description = "用户信息")
public class InfoVO {
@ApiModelProperty(value = "名称",required = true)
private String name;
@ApiModelProperty(value = "价格",example = "1.0")
private BigDecimal price;
@ApiModelProperty(value = "状态 0-未删除 1-逻辑删除",allowableValues = "0,1",example = "0")
private String status;
@ApiModelProperty(value = "时间",allowEmptyValue = true)
private LocalDateTime localDateTime;
}
接口定义
@Api 注解用于标注类为swagger资源
属性 | 描述 |
---|---|
value | 无实义,官网推荐用tags替代 |
tags | tags标签用于将我们的请求分类 |
description | 弃用 |
basePath | 弃用 |
position | 弃用 |
produces | 指定返回的内容类型,仅当request 请求头中的(Accept )类型中包含该指定类型才返回,例如:application/json |
consumes | 指定处理请求的提交内容类型(Content-Type ),例如application/json |
protocols | 标识的是当前的请求支持的协议,例如:http 、https 、ws 、wss |
authorizations | 高级特性认证时配置 |
hidden | 配置为true 将在文档中隐藏。隐藏整个Controller 资源。作用与@ApiIgnore 类似,但是没有@ApiIgnore 功能强大 |
@ApiOperation注解一般用于方法上,用作一个HTTP请求的方法描述
属性 | 描述 |
---|---|
value | 表示的是这个方法的一个总结性的描述 |
notes | 标识的是对于一个方法的具体性的描述 |
tags | 和@Api的tags功能类似 |
response | 这个属性设置的是当前请求的返回值类型 |
responseContainer | 说明的是包装相应的容器。默认情况下,有效值为 List 、Set 、Map ,任何其它值都将被忽略 |
responseReference | 这里设置的是一个相应类型的引用。这个引用可以是本地的,也可以是远程的。如果设置了这个值,将会覆盖response 属性的值 |
httpMethod | 请求方式,例如GET 、HEAD 、POST 、PUT 、DELETE 、OPTIONS |
position | 弃用 |
nickname | 这个字段对应的是operationId 字段。第三方工具使用operationId 来唯一表示此操作.在Swagger2.0 之后的版本中,这个字段是不在强制的,如果没有,则系统默认为空 |
produces | 指定返回的内容类型,仅当request 请求头中的(Accept )类型中包含该指定类型才返回,例如:application/json |
consumes | 指定处理请求的提交内容类型(Content-Type ),例如application/json |
protocols | 标识的是当前的请求支持的协议,例如:http 、https 、ws 、wss |
authorizations | 高级特性认证时配置 |
hidden | 配置为true 将在文档中隐藏。隐藏整个Controller 资源。作用与@ApiIgnore 类似,但是没有@ApiIgnore 功能强大 |
responseHeaders | 指定response 中header 的信息列表 |
code | http返回状态码 |
extensions | 可选的扩展数组,举例:extensions = @Extension(properties ={@ExtensionProperty(name = "author", value = "test@xx.com")}) |
ignoreJsonView | 忽略JsonView 注解,主要的目的是为了做到向下兼容 |
样例说明
@Api(tags = "swaggger测试")
@RestController
public class TestController {
@ApiOperation(value = "总结性描述测试1")
@PostMapping("/test1")
public APIResult<String> test1(InfoVO infoVO){
//TODO save operation
...
return APIResult.ofSuccess("数据保存成功");
}
}
swagger页面显示结果
基于swagger同步yapi规范
因为swaggger对代码的浸入性很强,所以我们尽可能的定义yapi中所需要的接口信息,摒去无用的定义。
实体类定义
非代码生成器生成的与数据库表结构相关联的domain类,例如与前端交互的VO类、与外部服务进行数据交换的DTO类,需在类头加上@ApiModel注解,在类属性加上@ApiModelProperty注解,便于补全接口文档的同时又可替换类注释。
@ApiModel注解
@apiModel主要用于标记实体类,定义格式:
@ApiModel(description = "xxx")
public class XXX
属性 | 必填项 | 描述 |
---|---|---|
description | 是 | 定义为类的详细描述 |
该属性定义后,接口返回类型为Object时,yapi中会显示对象的备注
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugOBaC7J-1673502457803)(null)]
@ApiModelProperty注解
@ApiModelProperty用于标记swagger实体类属性,定义格式:
@ApiModelProperty(value = "xxx",required = true)
private String xxx;
属性 | 必填项 | 描述 |
---|---|---|
value | 是 | 定义为字段的详细描述 |
required | 否 | 如果字段为必填项,则需要定义required = true 默认为false |
定义该属性用于展示在yapi接口中请求参数、返回参数的字段备注、是否必须项信息
接口定义
@Api注解
@Api用于标注类为swagger资源,定义格式:
@Api(tags = "XXX")
@RestController
public class XXXController
属性 | 必填项 | 描述 |
---|---|---|
tags | 是 | 将接口请求分类 |
定义tags属性,主要用于维护yapi中的文档分类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3sOgv8Uv-1673502457709)(null)]
@ApiOperation注解
@ApiOperation用作一个HTTP请求的方法描述,定义格式:
@ApiOperation(value = "xxx")
@PostMapping("/xxx")
public APIResult<String> xxx(){}
属性 | 必填项 | 描述 |
---|---|---|
value | 是 | 一个方法总结性的描述 |
定义ApiOperation的value属性,主要用于维护yapi中主分类的接口信息
@ApiImplicitParams和@ApiImplicitParam
@ApiImplicitParams和@ApiImplicitParam组合使用作用于方法上,这里主要用于定义yapi中请求参数的header属性。如非必须尽量不要使用,代码侵入性太严重了。
定义格式:
@ApiImplicitParams({
@ApiImplicitParam(paramType = "header", name = "xxx", value = "xxx", dataType = "xxx", required = true),
...
})
属性 | 必填项 | 描述 |
---|---|---|
paramType | 是 | 定义为header,这里只用作生成yapi中入参的header属性 |
name | 是 | 参数名称 |
value | 是 | 参数的具体含义,用作生成yapi中的备注信息 |
dataType | 否 | 参数的数据类型 |
required | 否 | 如果字段为必填项,则需要定义required = true 默认为false |
yapi中显示结果以及定义方式:
注意事项
例如以下的几个接口,均不符合标准
//第一种情况 入参为JsonStr 出参为Map
@ApiOperation(value = "错误示范1")
@PostMapping("/errTest1")
public Map<String,Object> errTest1(@RequestBody String infoVo){
//TODO save operation
...
Map<String,Object> res = new HashMap<>();
res.put("msg","ok");
res.put("code",200);
res.put("data","1");
return res;
}
//第二种情况 使用javabean传参、出参,但javabean中包含Map、Object的情况
@Data
@ApiModel(description = "test4")
public class Test4 {
@ApiModelProperty(value = "名称",required = true)
private String name;
//object属性 swagger不能识别
@ApiModelProperty(value = "值")
private Object value;
//尽可能将map、object定义成新的javaBean
@ApiModelProperty(value = "用户信息")
private InfoVO infoVo;
}
@ApiOperation(value = "错误示范2")
@PostMapping("/errTest2")
public APIResult<Test4> errTest2(Test4 test4){
//TODO save operation
...
return APIResult.ofSuccess(test4);;
}
上方定义的接口生成的swagger文档示例如下
yapi中的接口展示:
错误示例定义出来的接口文档,增大了接口联调的测试难度。接口数据同步到yapi上,因为缺失了必要的字段信息,也会导致接口和代码的可阅读性较差。
所以在实际接口定义过程中,尽量使用javaBean,而不要使用Map、Object、JSON String等方式定义接口的出入参。如果是通用返回结果集,尽量使用泛型替换Object。