easyYapi生成文档
- 背景
- 1.安装配置
- 1.1 介绍
- 1.2 安装
- 1.3 配置
- 1.3.1 Export Postman
- 1.3.2 Export Yapi
- 1.3.3 Export Markdown
- 1.3.4 Export Api
- 1.3.6 常见问题补充
- 2. java注释规范
- 2.1 接口注释规范
- 2.2 出入参注释规范
- 3. 特定化支持
- 3.1 必填校验
- 3.2 忽略导出
- 3.3 返回不一致
- 3.4 设置header
- 3.5 设置tag
- 3.6 设置open
- 3.7 序列化相关
- 4. 自定义配置
- 5. 问题
背景
因为公司业务需要接口自动化测试,所以需要针对所有java项目的后端接口进行完整的文档梳理并同步到yapi接口管理平台,在使用swagger实操过程中,发现了一款比较好用的yapi生成工具,特别好用,不仅支持无侵入的方式生成文档,还支持定制化处理。下面一起来就通过笔者的这篇博文来了解EasyYapi这款插件的使用吧。
1.安装配置
1.1 介绍
基于java注释生成api接口文档的idea插件。
-
代码零侵入
-
通过注释生成api接口文档
-
实时生成并同步相关接口平台
-
灵活的配置规则适应项目特性
官方手册 easyYapi
1.2 安装
支持以下IDE
- 2017.3及以上版本。
从IDEA仓库中安装
Preferences(Settings)
-->Plugins
>Browse repositories
-->find"EasyYapi"
-->Install Plugin
手动下载安装:
- 下载插件 Jetbrains or Github ->
Preferences(Settings)
>Plugins
>Install plugin from disk...
下载地址: https://plugins.jetbrains.com/
重启IDE
1.3 配置
插件安装完成,可以直接通过在某个类或者某个文件夹下 右键
->easyYapi
->exportYapi
1.3.1 Export Postman
导出为postman支持的接口信息。
-
直接导出: 导出为json格式的api接口信息 可以导入Postman中
-
配置postman的token导出: 通过在
Preferences
—>Other Settings
—>EasyApi
中配置postman对应的token 会直接同步到postman上
配置token
postman token获取方式
https://martian-spaceship-950587.postman.co/integrations/service/pm_pro_api
效果
1.3.2 Export Yapi
导出并同步到yapi服务端。
- 直接导出
首次使用: 需要配置yapi服务端地址 ip+port 和对应yapi分类中的token
1). 配置服务地址
2) . 配置yapi对应分类的token
3). token来源获取
1.3.3 Export Markdown
导出为md文件、直接导出为md文件
1.3.4 Export Api
导出各种类型的请求信息,export api可以针对某个接口进行导出。
##### 1.3.5 call api
Call Api:生成调试工具 可以进行请求调试调用。
1.3.6 常见问题补充
- yapi、postman配置错误或者变更: 可通过
Preferences
—>Other Settings
—>EasyApi
修改。
- 导出yapi时 , 每个module需要配置相应的token, 即对应一个yapi中的项目
2. java注释规范
2.1 接口注释规范
[] 表示可选操作
/**
* 分类名称
* [分类备注/描述]
*
* [@module 归属项目]
*/
@RestController
@RequestMapping(value = "/pathOfCtrl")
public class MockCtrl {
/**
* api名称
* [api描述]
* [@param param1 参数1的名称或描述] 对于get请求有作用@RequestParam或者@PathVariable有效
* [@param param2 可以用`@link`来表示当前参数的取值是某个枚举{@link some.enum.or.constant.class}]
* [@param param3 当目标枚举字段与当前字段名不一致,额外指定{@link some.enum.or.constant.class#property1}]
* [@return 响应描述]
*/
@RequestMapping(value = "/pathOfApi1/${orderCode}")
public Result methodName1(long param1,
@RequestParam String param2,
@RequestParam(required = false, defaultValue = "defaultValueOfParam3") String param3){
...
}
/**
* 默认使用`application/x-www-form-urlencoded`,
* 对于`@RequestBody`将使用`application/json`
*
* 可以用注解`@Deprecated`来表示api废弃
* 也可以用注释`@deprecated`
* [@deprecated 改用{@link #methodName3(String)} 只能引用同一个方法]
* [@deprecated 改用{@link #yapi地址}或者{@see #yapi地址}]
*/
@Deprecated
@RequestMapping(value = "/pathOfApi2")
public Result methodName2(@RequestBody MockDtoOrVo jsonModel){
...
}
}
- GET请求的入参@RequestParam或者@PathVariable 中在注释上必须使用@param、出参使用@return。才能生成正常入参文档。
2.2 出入参注释规范
public class MockDtoOrVo {
/**
* 字段注释
*/
private Long field1;
/**
* 使用@see来说明当前字段的取值是某个枚举
* @see some.enum.or.constant.enum
*/
private int field3;
/**
* 当目标枚举字段与当前字段名不一致,额外指定
* @see some.enum.or.constant.enum#property1
*/
private int field4;
/**
* 可以用注解`@Deprecated`来表示字段被废弃
* 也可以用注释`@deprecated`
* @deprecated It's a secret
*/
@Deprecated
private int field5;
/**
* 如果使用javax.validation的话
* 可以使用@NotBlank/@NotNull表示字段必须
*/
@NotBlank
@NotNull
private String field6;
//序列化名称
@JSONField(name="aaa")
@JsonAlias("aaa")
@JsonProperty("aaa")
private String field7;
...
}
- 字段是常量或者枚举值、可以使用@see 引用枚举,注意枚举、常量对应的类也需要写对应的注释
3. 特定化支持
yapi有对应的通用配置能大致满足我们通用接口的生成,但是针对项目中一些特殊接口,yapi也提供了灵活的运用配置规则 通过自定义配配置来适应项目特性以减少代码侵入。
- 默认支持的通用配置:
Preferences
—>Other Settings
—>EasyApi
-->Recommend
3.1 必填校验
默认配置
field.required: 用于标记字段是否为必须。 默认支持javax.validation annotations。
param.required: 用于标记API参数是否为必须。 默认支持javax.validation annotations。
#get请求入参
param.required=@javax.validation.constraints.NotBlank
param.required=@javax.validation.constraints.NotNull
param.required=@javax.validation.constraints.NotEmpty
#post请求入参
field.required=@javax.validation.constraints.NotBlank
field.required=@javax.validation.constraints.NotNull
field.required=@javax.validation.constraints.NotEmpty
//get请求 入参
@GetMapping("/update/get")
public Map<String, Object> getHttp(Integer fileId) {}
//get请求 参数为path
@GetMapping("/update/get/{orderCode}")
public Map<String, Object> getHttpPath(@PathVariable(name = "orderCode") Integer orderCode) {
//@NotBlank @NotEmpty
//get请求 参数为path
@GetMapping("/update/get")
public Map<String, Object> getHttp(@NotNull Integer fileId) {}
//post请求入参属性生成必填
public class AreaUpdateDTO {
/**
* 区域对象数组
*/
@NotNull
//@NotBlank
//@NotEmpty
private List<AreaDTO> areaList;
}
get请求中@RequestParam、@PathVariable修饰的请求参数生成的文档都是必填
自定义配置
//open接口有这种方法使用 @Validated 如果继续使用@NotNull等注解会破坏现有接口
public ResultBody<ContractAddResultDTO4Open> chCarCorverContractAdd(@Validated @RequestBody CarCoverPromotionContractAddDto dto){
- 自定义注解
/**
* 字段必填注解标识
* @author xieqx
*/
@Target({ElementType.FIELD, ElementType.PARAMETER,ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface CrmFieldRequired {
}
- 添加自定义配置规则
#设置字段必填 且支持使用自定义注解
field.required=@com.yiche.crm.base.annotations.CrmFieldRequired
param.required=@com.yiche.crm.base.annotations.CrmFieldRequired
- 使用
//get请求
@GetMapping("/update/get")
public Map<String, Object> getHttp(@CrmRequired Integer fileId) {}
//post请求入参属性生成必填
public class AreaUpdateDTO {
/**
* 区域对象数组
*/
@CrmRequired
private List<AreaDTO> areaList;
}
3.2 忽略导出
ignore: 整个类或者接口方法不导出。
/**
* Mock Apis
* @ignore 忽略当前类
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
* @ignore 忽略当前api
*/
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
field.ignore:字段忽略不导出。
默认支持如下
#字段级别导出
field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value
field.ignore=!@com.google.gson.annotations.Expose#serialize
- 自定义注解
/**
* 字段忽略注解
* @author xieqx
*/
@Target({ElementType.FIELD, ElementType.PARAMETER,ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface CrmFieIdIgnore {
}
自定义配置
field.ignore=@com.yiche.crm.base.annotations.CrmFieIdIgnore
param.ignore=@com.yiche.crm.base.annotations.CrmFieIdIgnore
3.3 返回不一致
**method.return: ** 设置方法的返回值。
常用于以下情况:
- 方法响应统一封装
- 方法返回Object
- 方法返回类型中的泛型类型未明确
<Object>
/<?>
/<*>
- 方法返回类型与实际响应无关, 例如通过操作HttpServletResponse来返回响应
目前特殊接口
crm系统中大部分的请求出参情况如下:
//1.返回泛型未明确
public ResultBody getSpecialApprovalAttach();
//2.出参与响应不一致
@CommonResult
public String getHttpPath()
@CommonResult
public PageInfo<Student> getHttpPath()
@CommonResult
public List<Student> getHttpPath()
//3.下载导出
@CommonResult
public void download(HttpserveletResponse resp)
自定义配置规则
#该配置的意思是 无论返回值是怎样的只需在注释中使用@real_return 后引入真实的对象类型即可
#it.doc("real_return") 中real_return自定义字符串即可(最好项目统一)
method.return[#real_return] =
groovy: "com.yiche.crm.common.rest.ResultBody<" + helper.resolveLink(it.doc("real_return")) +">"
#对于只返回单个字段
#method.return.main[groovy:it.returnType().isExtend("com.yiche.crm.common.rest.ResultBody")]=data
- 使用
//1.返回泛型未明确
/**
* @real_return {@link String}
*/
public ResultBody getSpecialApprovalAttach(){
return ResultBody.ok("hello");
}
//2.出参与响应不一致
/**
* @real_return {@link String}
*/
@CommonResult
public String getHttpPath() {
return "hello"
}
/**
* @real_return {@link PageInfo<Student>}
*/
@CommonResult
public PageInfo<Student> getHttpPath()
/**
* @real_return {@link List<Student>}
*/
@CommonResult
public List<Student> getHttpPath()
//3.下载导出
/**
* @real_return {@link void}
* 或者
* @real_return {@link com.alibaba.excel.EasyExcel}
*/
@CommonResult
public void download(HttpserveletResponse resp)
3.4 设置header
method.additional.header: API需要额外的header
。
- 配置
#所有接口都需要设置如下header
#method.additional.header={name: "Authorization",value: "",desc: "认证Token",required:true, example:""}
api.tag=@open_header
# 特定的接口需要添加header
# 对于注释使用@open_header的接口 需要特定的header(主要针对crm系统open接口)
method.additional.header[groovy:it.hasDoc("open_header")]={name: "token",value: "",desc: "认证Token",required:true}
method.additional.header[groovy:it.hasDoc("open_header")]={name: "source",value: "",desc: "来源,接口调用方",required:true}
# 对于注释使用@open_yxs_header的接口 需要特定的header(主要针对crm系统open-yxs接口)
method.additional.header[groovy:it.hasDoc("open_yxs_header")]={name: "x-access-ework-token",value: "",desc: "鉴权token",required:true}
- 使用
/**
*
* @open_header 添加open_header配置的header
* @open_yxs_header 添加open_yxs_header配置的header
*/
@GetMapping("/update/download")
@CommonResult
public ResultBody download(HttpServletResponse response){}
3.5 设置tag
api.tag: 标记接口,脚本中可以使用it.getDoc(“tagNam”)获取到。
- 配置
#语法 [#标记的名字] --- 注释中写@tagLabel 在yapi的tag中显示tagName
api.tag[#tagLabel]=tagName
api.tag=@open_header
- 使用
/**
*
* @open_header 添加open_header配置的header
* @deprecated 注释中使用
*/
@Deprecated //java注解
@GetMapping("/update/download")
@CommonResult
public ResultBody download(HttpServletResponse response){}
3.6 设置open
api.tag: 标记接口是否公开,从yapi导出api的时候可以选择只导出开放接口的api。
- 配置
#配置方式
api.open=#open
api.open=#myTag
- 使用
/**
*
* @open
* 或者
* @myTag
*/
@GetMapping("/update/download")
public Map<String, Object> areaUpdateNotice(@RequestBody AreaUpdateDTO dto) {
3.7 序列化相关
字段名称与返回的类型不一致的问题
@JSONField(name="aaa")
@JsonAlias("aaa")
@JsonProperty("aaa")
private Integer status;
easyYapi默认支持@JsonProperty(“aaa”)的转换,其他转换需要配置
#支持@JSONField注解
field.name=@com.alibaba.fastjson.annotation.JSONField#name
#支持@JsonAlias注解
field.name=@com.fasterxml.jackson.annotation.JsonAlias#value
4. 自定义配置
设置字段必填 且支持使用自定义注解
field.required=@com.yiche.crm.base.annotations.YapiRequired
#是否开放接口 不设置默认 非开放
api.open=#open
api.open=#xiu
#设置标签
#api.tag[#xiu]=my_tag
api.tag=@open_header
api.tag=@open_yxs_header
# 对于注释使用@的接口 需要特定的header(主要针对crm系统open接口)
method.additional.header[groovy:it.hasDoc("open_header")]={name: "token",value: "",desc: "认证Token",required:true}
method.additional.header[groovy:it.hasDoc("open_header")]={name: "source",value: "",desc: "来源接口调用方",required:true}
# 对于注释使用@open的接口 需要特定的header(主要针对crm系统open_yxs接口)
method.additional.header[groovy:it.hasDoc("open_yxs_header")]={name: "x-access-ework-token",value: "",desc: "易小鲨认证Token",required:true}
#支持@JSONField注解
field.name=@com.alibaba.fastjson.annotation.JSONField#name
#支持@JsonAlias注解
field.name=@com.fasterxml.jackson.annotation.JsonAlias#value
5. 问题
-
Map、JsonObject问题处理
-
必填校验,如果多个接口使用同一个入参,必填字段不一样使用必填注解也是有问题的
-
返回单个字段 无法设置注释
-
Postman 调试添加用例
-
yapi整合测试、mock、生成测试报告