可配置规则
支持的规则
基础配置
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
folder.name | method | 1.1.11+ | 设置 api 所属文件夹 |
class.prefix.path | class | 1.1.11+ | 设置 API 请求前缀 |
ignore | class/method | 1.1.11+ | 忽略 API |
module | class | 1.1.11+ | 为 api 分组 |
API 配置
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
api.name | method | 1.1.11+ | 设置 api 的名称 |
api.tags | method | 1.1.24+ | 设置 api 的标签 |
api.status | method | 1.1.24+ | 设置 api 的状态 |
method.description | method | 1.1.24+ | 方法(api)的额外注释 |
method.defaultContentType | - | 1.1.24+ | 用以设置 API 请求的 content-type |
method.default.http.method | method | 1.1.11+ | 设置默认的 api 的 HttpMethod |
method.request.replace | method | 1.1.29+ | 设置默认的 api 的入参命名转换 |
method.response.replace | method | 1.1.29+ | 设置默认的 api 的返回值命名转换 |
method.additional.header | method | 1.1.11+ | API 需要额外的 header, |
{name: "header name",value: "",desc: "",required:false, example:""} | |||
method.additional.param | method | 1.1.11+ | API 需要额外的参数 |
{name: "param name",value: "defaultValue",desc: "",required:false} | |||
☆method.return | method | 1.1.11+ | 设置返回值的类型 |
☆method.return.main | method | 1.1.11+ | 设置返回值的核心主体 |
☆method.return.body.type | method | 1.1.28+ | 设置返回值的返回类型 |
path.multi | - | 1.1.11+ | 设置返回值的核心主体 |
请求参数
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
param.defaultValue | arg | 1.1.11+ | API 参数的默认值 |
param.description | arg | 1.1.11+ | 参数的额外注释 |
param.type | arg | 1.1.11+ | 用于设置 API 参数在 HTTP 请求中的类型 |
param.ignore | arg | 1.1.11+ | 忽略 API 参数 |
param.required | arg | 1.1.11+ | API 参数是否为必须(即不可为空) |
数据模型字段
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
field.order | - | 1.1.27+ | 用以设置字段的排序 |
field.order.with | - | 1.1.27+ | 用以设置字段的排序,通过比较器 |
field.defaultValue | - | 1.1.11+ | 用以设置字段的默认值 |
field.example | - | 1.1.11+ | 用以设置字段的示例值 |
☆field.description | field | 1.1.11+ | 字段的额外注释 |
field.ignore | field | 1.1.11+ | 忽略字段(设置某些字段不出现在 json 中,或不需要请求时给出) |
☆field.mock | field | 1.1.11+ | 生成 mock 信息 |
field.mock.resolveProperty | - | 1.1.11+ | 用以开关是否解析field.mock 规则结果中的占位符 |
field.name | field | 1.1.11+ | 设置输出的字段名(用于 json 中字段名与类中字段名不一致) |
field.required | field | 1.1.11+ | 字段是否为必须(即不可为空) |
constant.field.ignore | field | 1.1.11+ | 忽略常量字段 |
field.schema.title | field | 1.1.27+ | 用以设置字段的数据模型的中文名 |
field.schema.min.length | field | 1.1.27+ | 用以设置字段的数据模型的最小长度 |
field.schema.max.length | field | 1.1.27+ | 用以设置字段的数据模型的最大长度 |
field.schema.format | field | 1.1.27+ | 用以设置字段的数据模型格式format |
field.schema.pattern | field | 1.1.27+ | 用以设置字段的数据正则表达式 |
field.schema.const | field | 1.1.27+ | 用以设置字段的数据模型常量 |
field.schema.read.only | field | 1.1.27+ | 数据模型作为请求参数时,该字段将被隐藏 |
field.schema.write.only | field | 1.1.27+ | 数据模型作为返回结构时,该字段将被隐藏 |
field.schema.permit.null | field | 1.1.29+ | 数据模型字段是否允许为 null,默认允许为 null |
枚举
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
enum.use.custom | class | 1.1.11+ | 用于设置使用 @see 枚举类型时的默认取值字段, 优先级高于enum.use.by.type |
enum.use.by.type | class | 1.1.11+ | 用于设置使用 @see 枚举类型时的默认使用类型一致的字段, 优先级低于enum.use.custom |
enum.use.ordinal | class | 1.1.11+ | 用于设置使用 @see 枚举类型时的默认使用 ordinal 作为取值 |
enum.use.name | class | 1.1.11+ | 用于设置使用 @see 枚举类型时的默认使用 name 作为取值 |
JSON 配置
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
☆json.rule.convert | - | 1.1.11+ | 用于设置某些类型转换为其他类型处理, 通常用于使用了 Spring 的自定义类型转换器的情况 |
json.rule.enum.convert | class | 1.1.11+ | 用于枚举类型的特殊转换 |
~json.rule.field.ignore~ | field | 1.1.11+ | 忽略字段(设置某些字段不出现在 json 中,或不需要请求时给出) 已废弃, 使用field.ignore代替 |
~json.rule.field.name~ | field | 1.1.11+ | 设置输出的字段名(用于 json 中字段名与类中字段名不一致) |
json.rule.class.description | field | 1.1.29+ | 设置数据模型的描述 |
methodDoc
规则的 key | 规则目标(上下文 it) | 版本 | 规则描述 |
---|---|---|---|
mdoc.class.filter | class | 1.1.11+ | 选择哪些类可以导出方法文档(rpc) |
mdoc.method.path | method | 1.1.11+ | 设置方法文档(rpc)的路径 |
mdoc.method.http.method | method | 1.1.11+ | 设置方法文档(rpc)HTTP 请求方式 |
支持的简单配置
简单配置无上下文
规则的 key | 版本 | 配置类型 | 规则描述 | 示例 |
---|---|---|---|---|
dev | 1.1.11+ | bool | 启动开发模式,打印更详细的日志 | dev=true |
max.deep | 1.1.11+ | int | 解析json 时最大深度,默认 6 | max.deep=8 |
max.elements | 1.1.11+ | int | 解析json 时最大字段数,默认 256 | max.elements=512 |
json.cache.disable | 1.1.11+ | bool | 禁用json 解析缓存 | json.cache.disable=true |
http.timeOut | 1.1.11+ | int | http 请求的超时时间(s),优先级高于setting | http.timeOut=5 |
auto.format.url | 1.1.11+ | bool | 导入时是否格式化url ,确保url 以/ 开始,且将[a-zA-Z0-9-/_:.{}?=!]之外的字符替换为/ | auto.format.url=false |
field.mock.resolveProperty | 1.1.11+ | bool | 是否处理mock 信息中的占位符${xxx} | field.mock.resolveProperty=true |
api.tags.delimiter | 1.1.24+ | string | tags 的分割符, 默认为, | api.tags.delimiter=,# |
支持的回调
部分回调方法中可能没有it
, 但可能会有附加的上下文供使用
规则的 key | 规则目标(上下文 it) | 附加上下文 | 版本 | 规则描述 |
---|---|---|---|---|
api.class.parse.before | class | 无 | 1.1.11+ | 解析api 前回调 |
api.class.parse.after | class | 无 | 1.1.11+ | 解析api 后回调 |
api.method.parse.before | method | 无 | 1.1.11+ | 解析api 方法前回调 |
api.method.parse.after | method | 无 | 1.1.11+ | 解析api 方法后回调 |
api.param.parse.before | param | 无 | 1.1.11+ | 解析api 参数前回调 |
api.param.parse.after | param | 无 | 1.1.11+ | 解析api 参数后回调 |
export.after | method | api | 1.1.11+ | 每个 api 导出完成后回调 |
http.call.before | 无 | request | 1.1.11+ | http 请求前回调 |
http.call.after | 无 | request, response | 1.1.11+ | http 请求后回调 |
json.class.parse.before | class | 无 | 1.1.11+ | 解析类型前回调 |
json.class.parse.after | class | 无 | 1.1.11+ | 解析类型后回调 |
json.field.parse.before | field | 无 | 1.1.11+ | 解析类型字段前回调 |
json.field.parse.after | field | 无 | 1.1.11+ | 解析类型字段后回调 |
json.method.parse.before | method | 无 | 1.1.11+ | 解析类型方法 (getter/setter ) 前回调 |
json.method.parse.after | method | 无 | 1.1.11+ | 解析类型方法 (getter/setter ) 后回调 |
NOTES: 项目内文件配置
规则语法
简单规则
# 读取注释上的 tag
如
#fake
对应取的注释如下:/**
* @fake
*/
@ 读取注解
@xxx 读取方法或字段上的注解,如
@org.springframework.web.bind.annotation.RequestMapping
@RequestMapping("path")
public class FakeClass{...}@xxx#yyy 读取方法或字段上的注解中的 attr 值,如
@org.springframework.web.bind.annotation.RequestMapping#value
@RequestMapping(value = "path")
public class FakeClass{...}
字面量
- string 如:
api.status=done
- string 如:
高级脚本规则
- 由于
JDK11
后js
引擎可能缺失, 故推荐使用groovy
作为首选 groovy
规则为groovy:groovyScript
js
规则为js:jsScript
基础配置
folder.name
用于设置 API 所属文件夹的名称。
默认情况下, 默认使用 API 所在类作为所属文件夹。
示例
配置如下:
# 使用 tag `folder` 设置接口所在目录
folder.name=#folder
使用如下:
/**
* 用户相关
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @folder 一级目录/二级目录
*/
@GetMapping("/string")
public String userDetail() {
return Result.success("***");
}
/**
* @folder 用户相关/一级目录/二级目录
*/
@GetMapping("/string")
public String userDetailRoot() {
return Result.success("***");
}
}
默认情况下(无配置)上述接口会归属到文件夹用户相关
, 加上注释 @folder 一级目录/二级目录
后归属到一级目录/二级目录
,如果希望成为用户相关
的子目录,加上注释 @folder 用户相关/一级目录/二级目录
后归属到用户相关/一级目录/二级目录
多级目录使用斜杠/
分隔。其中\
和/
为特殊字符,需要转义,\/
表示字符/
,\\
表示字符\
。
class.prefix.path
设置 API 请求前缀
默认推荐配置(例如.apifox-helper.properties)
#[import_spring_properties]
#Import spring properties
###set ignoreNotFoundFile = true
###set ignoreUnresolved = true
properties.additional=${module_path}/src/main/resources/application.properties
properties.additional=${module_path}/src/main/resources/application.yml
properties.additional=${module_path}/src/main/resources/application.yaml
properties.additional=${module_path}/src/main/resources/bootstrap.yaml
properties.additional=${module_path}/src/main/resources/bootstrap.properties
properties.additional=${module_path}/src/main/resources/bootstrap.yml
###set ignoreUnresolved = false
###set ignoreNotFoundFile = false
#[resolve_spring_properties]
#Resolve spring properties
###set ignoreUnresolved = true
class.prefix.path=${server.servlet.context-path}
###set ignoreUnresolved = false
使用推荐配置后,可识别如下 spring 配置
spring application.properties/bootstrap.properties
server.servlet.context-path=/demo
spring application.yaml/application.yml/bootstrap.yaml/bootstrap.yml
server:
servlet:
context-path: /demo
.apifox-helper.properties
class.prefix.path=${server.servlet.context-path}
如果 springCloud 每个模块的前缀 url 互不相同,在每个微服务的 application.properties 配置即可
自定义 demo
class.prefix.path=/demo
ignore
用于忽略
class
/method
, 不进行解析
注释在
class
上时,整个类将被忽略
注释在
method
上时,当前方法将被忽略
默认推荐配置
ignore=#ignore
示例
- 在类上注释
@ignore
忽略当前类
/**
* Mock Apis
*
* @ignore
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
}
- 在方法上注释
@ignore
忽略当前 API
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
* @ignore
*/
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
module
要将 API 导入到多个 Apifox 项目时才需要配置每个
module
对应一个 Apifox 项目
默认推荐配置
module=#module
示例
/**
* Mock Apis
* @module mock
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
}
API 配置
api.name
用于设置 API 接口名称默认情况下, 使用 api 注释的第一行作为 API 的名称
示例
配置如下:
# read api name from tag `api.name`
api.name=#api.name
使用如下:
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @api.name Mock String
* @undone
*/
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
示例
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
* @api.folder 宠物店/订单
*/
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
api.tags
用于设置 Apifox 的请求标签,默认情况下用
,
分割
在1.1.24版本之前使用api.tag
,如需使用最新配置,请更新插件
示例
配置如下:
api.tags=#tags
使用如下:
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @tags tag1,tag2
*/
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
api.status
用于设置的请求状态,默认有
designing
,pending
,developing
,integrating
,testing
,tested
,released
,deprecated
,exception
,obsolete
示例
配置如下:
api.status[#obsolete]=obsolete
使用如下:
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @obsolete
*/
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
method.description
API 接口说明,方法(API)的额外注释
在1.1.24版本之前使用method.doc
,如需使用最新配置,请更新插件
默认推荐配置
#deprecated info(java)
method.description[#deprecated]=groovy:"\n「已废弃」" + it.doc("deprecated")
method.description[@java.lang.Deprecated]=「已废弃」
method.description[groovy:it.containingClass().hasDoc("deprecated")]=groovy:"\n「已废弃」" + it.containingClass().doc("deprecated")
method.description[groovy:it.containingClass().hasAnn("java.lang.Deprecated")]=「已废弃」
#deprecated info(kotlin)
method.description[@kotlin.Deprecated]=groovy:"\n「已废弃」" + it.ann("kotlin.Deprecated","message")
method.description[groovy:it.containingClass().hasAnn("kotlin.Deprecated")]=groovy:"\n「已废弃」 " + it.containingClass().ann("kotlin.Deprecated","message")
添加对 swagger @ApiOperation 支持
method.description=@io.swagger.annotations.ApiOperation#value
示例
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
*/
@ApiOperation(value = "mock string")
@GetMapping("/string")
public String mockString() {
return Result.success("mock string");
}
}
method.defaultContentType
在1.1.24版本之前使用
method.content.type
,如需使用最新配置,请更新插件
用于设置 API 请求默认的
content-type,
插件依然会在必要的时候强行覆盖掉
如当遇到
@RequestBody
时, 将被强行覆盖为application/json
默认情况下, 插件优先使用application/x-www-form-urlencoded
, 如希望优先使用multipart/form-data
配置如下:
method.defaultContentType=multipart/form-data
method.default.http.method
设置默认的 api 的 HttpMethod
默认情况下, 当 API 上未指定 HttpMethod, 且无特殊参数时默认使用
GET
如希望默认使用POST
配置如下:
method.default.http.method=POST
method.request.replace
传入参数命名方式转换规则有
小驼峰 camelCase
,大驼峰 pascalCase
,下划线 snakeCase
,全小写 flatcase
,全大写 uppercase
,全大写下划线 macroCase
,大驼峰下划线 titleCase
。此规则小于全局配置,如果想要使用请设置参数命名方式转换为保持原样
配置如下:
method.request.replace[#requestUppercase]=uppercase
示例
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @requestUppercase
*/
@ApiOperation(value = "mock string")
@GetMapping("/string")
public String mockString(String requestUppercase1,Integer requestUppercase2) {{
return "mock string";
}
}
导出结果如下:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
REQUESTUPPERCASE1 | string | ||||
REQUESTUPPERCASE2 | integer |
method.response.replace
返回参数命名方式转换规则有
小驼峰 camelCase
,大驼峰 pascalCase
,下划线 snakeCase
,全小写 flatcase
,全大写 uppercase
,全大写下划线 macroCase
,大驼峰下划线 titleCase
。此规则小于全局配置,如果想要使用请设置参数命名方式转换为保持原样
配置如下:
method.response.replace[#responseUppercase]=uppercase
示例
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @responseUppercase
*/
@ApiOperation(value = "mock string")
@GetMapping("/string")
public String mockString(String requestUppercase1,Integer requestUppercase2) {{
return "mock string";
}
}
导出结果如下:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
MOCK STRING | string |
method.additional.header
API 需要额外的
header
如 JWT, 所有的接口都需要在 header 中携带 token
method.additional.header={name: "Authorization",value: "",description: "认证 Token",required:true, example:""}
如果需要排除指定开放的接口不需要 token 可以这样配置
- 假定有如下注解:
package com.apifox.common.annotation;
/**
* 声明接口为公开接口
*/
@Documented
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Public {
}
- 则可如此配置
method.additional.header[!@com.apifox.common.annotation.Public]={name: "Authorization",value: "",description: "认证 Token",required:true}
- 等价于
method.additional.header[groovy:!it.hasAnn("com.apifox.common.annotation.Public")]={name: "Authorization",value: "",description: "认证 Token",required:true}
示例
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* public api
* Token is not required
*/
@Public
@GetMapping("/apiWithoutToken")
public Result<String> apiWithoutToken() {
return Result.success("no token");
}
/**
* private api
* Token is required
*/
@GetMapping("/apiWithToken")
public Result<String> apiWithToken() {
return Result.success("wow,you got a token");
}
}
如果需要针对指定包下添加 header
method.additional.header[groovy:it.containingClass().name().startsWith("com.test.api")]={name: "Authorization",value: "",description: "认证 Token",required:true}
同理如果指定包下不需要添加 header 则取反就行了
method.additional.header[groovy:!it.containingClass().name().startsWith("com.test.api")]={name: "Authorization",value: "",description: "认证 Token",required:true}
支持添加多个 header
method.additional.header[groovy:it.containingClass().name().startsWith("com.test.api")]={name: "a",value: "",description: "",required:true}
method.additional.header[groovy:it.containingClass().name().startsWith("com.test.api")]={name: "b",value: "",description: "",required:true}
method.additional.param
API 需要额外的
param
仅适用于 url 参数,不支持
form
/body
例如接口都需要在param
中携带 token
method.additional.param={name: "Authorization",value: "",description: "认证 Token",required:true}
如果需要排除指定开放的接口不需要 token 可以这样配置:
- 假定有如下注解:
package com.apifox.common.annotation;
/**
* 声明接口为公开接口
*/
@Documented
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Public {
}
- 则可如此配置
method.additional.param[!@com.apifox.common.annotation.Public]={name: "Authorization",value: "",description: "认证 Token",required:true, example:""}
- 等价于
method.additional.param[groovy:!it.hasAnn("com.apifox.common.annotation.Public")]={name: "Authorization",value: "",description: "认证 Token",required:true, example:""}
示例
/**
* Mock Apis
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* public api
* Token is not required
*/
@Public
@GetMapping("/apiWithoutToken")
public Result<String> apiWithoutToken() {
return Result.success("no token");
}
/**
* private api
* Token is required
*/
@GetMapping("/apiWithToken")
public Result<String> apiWithToken() {
return Result.success("wow,you got a token");
}
}
method.return
设置方法的返回值
常用于以下情况:
- 方法返回 Object
- 方法返回类型中的泛型类型未明确
<Object>
/<?>
/<*>
- 方法返回类型与实际响应无关, 例如通过操作 HttpServletResponse 来返回响应
如以下 API
API:
/**
* 通过`HttpServletResponse`写入响应
*/
@RequestMapping(value = "/writeByResponse", method = RequestMethod.GET)
public void writeByResponse(HttpServletResponse response)throws IOException{
UserInfo userInfo=new UserInfo();
userInfo.setId(1l);
userInfo.setName("Tom");
userInfo.setAge(25);
response.getOutputStream().write(new Gson().toJson(Result.success(userInfo)).getBytes(Charsets.UTF_8));
}
- 这个方法返回的是
void
,但实际响应的是Result<UserInfo>
, 所以需要通过额外的途径来表明此API
的实际响应.
简单的,可做如下配置:
method.return=#response
使用方法:
/**
* @response com.apifox.common.dto.Result<com.apifox.common.model.UserInfo>
*/
为了方便书写, 我们可以尝试使用{@link}
来设置实际响应类型, 利用helper.resolveLink
来解析
例如做如下配置:
method.return[#response]=groovy: helper.resolveLink(it.doc("response"))
使用方法:
/**
* @response {@link Result<UserInfo>}
*/
更进一步的, 如果所有的响应都由com.apifox.common.dto.Result
包装
做如下配置:
method.return[#response]=groovy: "com.apifox.common.dto.Result<" + helper.resolveLink(it.doc("response")) +">"
使用方法:
/**
* @response {@link UserInfo}
*/
method.return.main
此配置仅设置返回值的核心主体, 使得
@return
的注释落在主体属性上,不影响返回类型及字段.
示例
Result.java
package com.apifox.common.dto;
public class Result<T> implements IResult {
private Integer code;//响应码
private String msg;//响应消息
private T data;//响应数据
//constructors...
//getters...
}
可做如下配置
method.return.main[groovy:it.returnType().isExtend("com.apifox.common.dto.Result")]=data
接口示例 1:
- 接口代码:
/**
* 获取当前用户类型
*
* @return 当前用户类型,{@link com.apifox.common.constant.UserTypeConstant}
*/
@GetMapping("/type")
public Result<Integer> currUserType(){
return Result.success(UserType.values()[new Random(System.currentTimeMillis()).nextInt(UserType.values().length)].getType());
}
- 导出 API 的响应:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
msg | string | 非必须 | 响应消息 | mock: | |
code | integer | 非必须 | 响应码 | mock: 0 | |
data | integer | 非必须 | 响应数据 当前用户类型,[用户类型] | 枚举: 1,2,3 枚举备注: 1:管理员 2: 成员 3: 游客 |
接口示例 2:
- 接口代码:
/**
* 获取所有用户类型
*
* @return {@link com.apifox.common.constant.UserType#getType()}
*/
@GetMapping("/types")
public Result<List<Integer>>types(){
final List<Integer> types=Stream.of(UserType.values()).map(UserType::getType).collect(Collectors.toList());
return Result.success(types);
}
- 导出 API 的响应:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
msg | string | 非必须 | 响应消息 | mock: | |
code | integer | 非必须 | 响应码 | mock: 0 | |
+data | integer[] | 非必须 | item 类型: integer | ||
integer | 枚举: 1,2,3 枚举备注: 1:管理员 2: 成员 3: 游客 |
附:
UserTypeConstant.java
/**
* 用户类型
*/
public class UserTypeConstant implements Serializable {
private static final long serialVersionUID = -4607862808303533196L;
public static final int ADMIN = 1; //管理员
public static final int MEMBER = 2; //成员
public static final int GUEST = 3; //游客
}
UserType.java
package com.apifox.common.constant;
/**
* 用户类型
*/
public enum UserType {
// 管理员
ADMIN(1, "管理员"),
// 成员
MEMBER(2, "成员"),
// 游客
GUEST(3, "游客");
private int type; //用户类型
private String description;
//constructors...
//getters...
}
method.return.body.type
控制返回值类型,返回值类型有
raw/json/xml/html/binary/msgpack/eventStream
,默认返回json
可做如下配置
method.return.body.type[#returnXml]=xml
接口示例 :
- 接口代码:
/**
* @returnXml
* @return
*/
@GetMapping(value = "/exampleXml")
@ResponseBody
public CaseData getExampleXml(HttpServletResponse response) throws IOException {
// 创建一个简单的POJO对象
CaseData caseData = new CaseData();
caseData.setName("chineseName");
caseData.setAge("11");
return caseData;
}
path.multi
用于当 API 有多个可用路径时如何处理目前可用策略(策略不区分大小写):
可用策略 | 策略描述 |
---|---|
FIRST | 选择第一个可用路径 |
LAST | 选择最后一个可用路径 |
LONGEST | 选择最长的可用路径 |
SHORTEST | 选择最短的可用路径 |
ALL | 为每一个可用路径生成一个 api |
可能的配置如下:
- 选择第一个可用路径
path.multi=first
- 选择最后一个可用路径
path.multi=last
- 选择最长的可用路径
path.multi=longest
- 选择最短的可用路径
path.multi=shortest
- 为每一个可用路径生成一个 api
path.multi=all
也可以由 api 自行决定选择策略
path.multi=#multi
使用如下:
/**
* 一些 Mock 相关的 API
*/
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* @multi all
*/
@GetMapping(value = {"/string", "string2"})
public String mockString() {
return Result.success("mock string");
}
}
请求参数
param.defaultValue
用于设置 API 参数的默认值
在1.1.24版本之前使用param.default.value
,如需使用最新配置,请更新插件
添加对 swagger @ApiParam 支持
param.defaultValue=@io.swagger.annotations.ApiParam#defaultValue
示例
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
*/
@GetMapping("/string")
public String mockString(
@ApiParam(value = "seed for mock", defaultValue = "666") long seed) {
return Result.success("mock string");
}
}
param.description
参数的额外注释
在1.1.24版本之前使用param.doc
,如需使用最新配置,请更新插件
在注释中给出参数类型
param.description=js:"类型:"+it.type().name()
在注释中给出参数类型并去掉 java 包名
param.description=groovy:"类型:"+tool.uncapitalize(it.type().name().replace("java.lang.",""))
示例 API
/**
* 更新用户名
*
* @param id 用户 id
* @param newName 新的用户名
* @param slogon 个人签名
* @deprecated 改用{@link #update(UserInfo)}
*/
@RequestMapping(value = "/set", method = RequestMethod.PUT)
public Object set(long id,
@RequestParam String newName,
@RequestParam(required = false, defaultValue = "haha") String slogon,
@RequestParam(required = false, defaultValue = "10") long times){
...
}
导出结果如下:
请求参数:
参数名称 | 是否必须 | 示例 | 备注 |
---|---|---|---|
id | 是 | 用户 id 类型: long | |
newName | 是 | 新的用户名 类型: string | |
slogan | 是 | 个人签名 类型: string | |
times | 是 | 类型: long |
param.type
用于设置 API 参数在 HTTP 请求中的类型(位置:body/form/query)
@RequestBody
/@ModelAttribute
/@RequestHeader
/@PathVariable
等忽略此规则
参数注解有
@RequestParam
且HttpMehotd
为GET
也忽略此规则
其他不满足规则的参数在规则缺省的情况下, 优先采取
query
模式
在1.1.24版本之前使用
param.http.type
,如需使用最新配置,请更新插件
配置示例
全设置为 form, 优先使用表单进行提交:
param.type=form
RequestParam 作为 query, 其他做为 form:
param.type[@org.springframework.web.bind.annotation.RequestParam]=query
param.type=form
param.ignore
忽略 API 参数
添加对 swagger @ApiParam 支持
param.ignore=@io.swagger.annotations.ApiParam#hidden
示例
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
*/
@GetMapping("/string")
public String mockString(
@ApiParam(value = "seed for mock", hidden = true) long seed) {
return Result.success("mock string");
}
}
高级示例
如果你希望自定义忽略
param
参数,或者使用注释的方式来忽略参数,可以使用如下配置
api.method.parse.before=groovy:```
def ig = it.doc("paramIngoreData")
def ab = tool.split(ig,",")
for(a in ab){
session.set("json-ignore", a, true)
}
```
api.method.parse.after=groovy:```
def ig = it.doc("paramIngoreData")
def ab = tool.split(ig,",")
for(a in ab){
session.remove("json-ignore", a)
}
```
param.ignore=groovy:```
return session.get("json-ignore", it.name())
```
/**
* @paramIngoreData data1,data3
*/
@PostMapping("/testApiIgnoreTest")
public String testApiIgnore(String data1, String data2, String data3, JBCtr jbCtr){
return "testParamIgnore";
}
param.required
用于标记 API 参数是否为必须(即不可为空)
默认推荐配置
#Support for javax.validation annotations
param.required=@javax.validation.constraints.NotBlank
param.required=@javax.validation.constraints.NotNull
param.required=@javax.validation.constraints.NotEmpty
添加对 swagger @ApiParam 支持
param.required=@io.swagger.annotations.ApiParam#required
示例
MockCtrl.java
@RestController
@RequestMapping(value = "mock")
public class MockCtrl {
/**
* Mock String
*/
@GetMapping("/string")
public String mockString(
@ApiParam(value = "seed for mock", required = true, defaultValue = "666666") long seed) {
return Result.success("mock string");
}
}
导出结果如下
请求参数:
参数名称 | 是否必须 | 示例 | 备注 |
---|---|---|---|
seed | 是 | 666666 | seed for mock |
数据模型字段
field.order
用于设置
字段
的排序
配置如下:
field.order=@com.fasterxml.jackson.annotation.JsonProperty#index
示例
TestJsonFieldBean.java
public class TestJsonFieldBean {
@JsonProperty(value = "a", index = 99)
private Long propertyA;
private Long propertyB;
@JsonProperty(value = "c", index = 0)
private Long propertyC;
//constructors...
//getters...
}
导出结果如下:
name | type |
---|---|
c | integer |
propertyB | integer |
a | integer |
field.order.with
用于设置
字段
的排序,与比较器类似,它通过比较两个字段返回-1、0或1,以指示结果中两个比较字段的顺序。其优先级高于field.order,一般不建议同时使用
配置如下:
- 通过注解 JsonPropertyOrder 控制顺序
#[Jackson_JsonPropertyOrder]
#Support for Jackson annotation JsonPropertyOrder
field.order=@com.fasterxml.jackson.annotation.JsonProperty#index
json.class.parse.before[@com.fasterxml.jackson.annotation.JsonPropertyOrder]=groovy:```
def properties = it.annValue("com.fasterxml.jackson.annotation.JsonPropertyOrder")
properties.each { property ->
session.push("JsonPropertyOrder-properties-"+it.name(), property)
}
session.set("JsonPropertyOrder-alphabetic"+it.name(),
it.annValue("com.fasterxml.jackson.annotation.JsonPropertyOrder","alphabetic") ?: false)
```
json.class.parse.after[@com.fasterxml.jackson.annotation.JsonPropertyOrder]=groovy:```
session.remove("JsonPropertyOrder-properties-"+it.name())
session.remove("JsonPropertyOrder-"+it.name())
```
field.order=groovy:```
def index = session.get("JsonPropertyOrder-properties-"+ it.containingClass().name())?.indexOf(it.name())
if (index == -1) {
return null
}else{
return index
}
```
field.order.with=groovy:```
def orderedProperties = session.get("JsonPropertyOrder-properties-"+ a.containingClass().name())
if(a.name() in orderedProperties) {
if(b.name() in orderedProperties){
return orderedProperties.indexOf(a.name()) - orderedProperties.indexOf(b.name())
}else{
return -1
}
} else if(b.name() in orderedProperties){
return 1
} else if(session.get("JsonPropertyOrder-alphabetic"+a.containingClass().name())){
return a.name().compareTo(b.name())
} else {
return null
}
```
- 子类字段优先
# child fields first
field.order.with=groovy:```
def aDefineClass = a.defineClass()
def bDefineClass = b.defineClass()
if(aDefineClass==bDefineClass){
return null
}else if(aDefineClass.isExtend(bDefineClass.name())){
return -1
}else{
return 1
}
```
- 父类字段优先
# parent fields first
field.order.with=groovy:```
def aDefineClass = a.defineClass()
def bDefineClass = b.defineClass()
if(aDefineClass==bDefineClass){
return null
}else if(aDefineClass.isExtend(bDefineClass.name())){
return 1
}else{
return -1
}
```
- 按字母升序排列
# fields alphabetically ordered
field.order.with=groovy:```
return a.name().compareTo(b.name())
```
- 按字母降序排列
# fields descending alphabetically ordered
field.order.with=groovy:```
return -a.name().compareTo(b.name())
```
示例
UserInfo.java
@JsonPropertyOrder(value = {"name", "birthDay"}, alphabetic = true)
public class UserInfo {
private Long id;//user id
/**
* @see com.itangcent.common.constant.UserType
*/
private int type;//user type
/**
* @mock tangcent
* @order 1
*/
@NotBlank
private String name;//user name
/**
* age
*
* @mock 1${digit}
*/
@NotNull
private Integer age;
/**
* @deprecated It's a secret
*/
private Integer sex;
//birthday
private LocalDate birthDay;
//registration time
private LocalDateTime regtime;
}
导出结果如下:
{
"name": "",
"birthDay": "", //birthday
"age": 0, //age
"id": 0, //user id
"regtime": "", //registration time
"sex": 0, //「Deprecated」It's a secret
/**
* 1 :Administrator
* 2 :Member
* 3 :Guest
*/
"type": 0
}
field.defaultValue
用于设置
字段
的默认值
在1.1.24版本之前使用field.default.value
,如需使用最新配置,请更新插件
原生编码支持
默认的所有含有默认初始值的字段, 取其默认初始值. 如:
private Integer code = 200;//响应码
额外的配置
配置如下:
field.defaultValue=#default
DemoDto.java
public class DemoDto {
/**
* 价格
* @default 666
*/
@NotNull
private Float price;
...
}
导出结果如下:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
price | number | 必须 | 666 | 价格 |
field.example
字段示例信息
在1.1.24版本之前使用field.demo
,如需使用最新配置,请更新插件
示例
配置如下:
field.example=#example
使用如下:
/**
* @example tangcent
*/
private String name;// 用户名
field.description
字段的额外注释
默认推荐配置
#deprecated info(java)
field.description[#deprecated]=groovy:"\n「已废弃」" + it.description("deprecated")
field.description[@java.lang.Deprecated]=「已废弃」
#deprecated info(kotlin)
field.description[@kotlin.Deprecated]=groovy:"\n「已废弃」" + it.ann("kotlin.Deprecated","message")
添加对 swagger @ApiModelProperty 支持
field.description=@io.swagger.annotations.ApiModelProperty#value
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @deprecated 不再使用
*/
@ApiModelProperty(value = "字段 A", required = true)
private String a;
//constructors...
//getters...
}
作为 API 返回值导出
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
a | string | 非必须 | 666 | 字段 A「已废弃」不再使用 |
field.ignore
忽略字段(设置某些字段不出现在 json 中,或不需要请求时给出)
默认推荐配置
#Support for Jackson annotations
field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value
#Support for Gson annotations
field.ignore=!@com.google.gson.annotations.Expose#serialize
示例
TestJsonIgnoreBean.java
public class TestJsonIgnoreBean {
@Expose(serialize = true)
private Long shouldNotIgnoreForGson;
@Expose(serialize = false)
private Long shouldIgnoreForGson;
@JsonIgnore(false)
private Long shouldNotIgnoreForJackson;
@JsonIgnore
private Long shouldIgnoreForJackson;
//constructors...
//getters...
}
作为 API 返回值导出
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
shouldNotIgnoreForGson | integer | 非必须 | mock: @natural(0,10000) | ||
shouldNotIgnoreForJackson | integer | 非必须 | mock: @natural(0,10000) |
定制化配置示例
- 忽略指定名称的字段:
配置如下:
# ignore field 'log'
field.ignore=log
将忽略如下字段:
private String log;
- 忽略指定类型的字段:
配置如下:
# ignore field 'log' typed xxx.xxx.Log
field.ignore=groovy:it.type().name()=="xxx.xxx.Log"
将忽略如下字段:
private Log xxx;
- 忽略指定
modifier
的字段:
配置如下:
#ignore transient field
field.ignore=groovy:it.hasModifier("transient")||it.hasModifier("protected")
将忽略如下字段:
private transient Int xxx;
protected Long yyy;
field.mock
用于生成
apifox
相关 mock 信息
默认推荐配置有三部分
允许通过注释@mock
定义mock
规则
#apifox mock
field.mock=#mock
示例
DemoDto.java
public class DemoDto {
/**
* @mock tangcent
*/
@NotBlank
private String name;//用户名
/**
* 年龄
* @mock 1@natural(0,9)
*/
@NotNull
private Integer age;
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
name | string | 非必须 | 用户名 | mock: tangcent | |
age | integer | 非必须 | 年龄 | mock: 1@natural(0,9) |
通用 mock
#mock for date
###set resolveMulti = first
java_date_types=["java.util.Date","java.sql.Timestamp","java.time.LocalDate","java.time.LocalDateTime"]
field.mock[groovy:${java_date_types}.contains(it.type().name())&&it.jsonType().name()=="java.lang.String"] = groovy:"@date"
field.mock[groovy:${java_date_types}.contains(it.type().name())&&it.jsonType().name()=="java.lang.Long"] = groovy:"@timestamp@string(\"number\", 3)"
###set resolveMulti = error
示例
DemoDto.java
public class DemoDto {
//生日
private LocalDate birthDay;
//注册时间
private LocalDateTime regtime;
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
birthDay | string | 非必须 | 生日 | mock: @date | |
regtime | string | 非必须 | 注册时间 | mock: @date |
javax.validation
相关 mock
# mock for javax.validation
###set resolveMulti = first
# define var
number_min=-9999
number_max=9999
float_dmin=2
java_integer_types=["java.lang.Integer","int","java.lang.Long","long","java.lang.Short","short","java.math.BigInteger"]
java_float_types=["java.lang.Float","float","java.lang.Double","double","java.math.BigDecimal"]
# mock_integer_or_float=${java_integer_types}.contains(it.type().name())?"@integer":"@float"
# AssertTrue|AssertFalse|Email
field.mock[@javax.validation.constraints.AssertTrue]=true
field.mock[@javax.validation.constraints.AssertFalse]=false
field.mock[@javax.validation.constraints.Email]=groovy:"@email"
# Positive&PositiveOrZero
field.mock[groovy:it.hasAnn("javax.validation.constraints.Positive")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(1,${number_max})"
field.mock[groovy:it.hasAnn("javax.validation.constraints.PositiveOrZero")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(0,${number_max})"
field.mock[groovy:it.hasAnn("javax.validation.constraints.Positive")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0.01,${number_max},${float_dmin})"
field.mock[groovy:it.hasAnn("javax.validation.constraints.PositiveOrZero")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0,${number_max},${float_dmin})"
# Negative&NegativeOrZero
field.mock[groovy:it.hasAnn("javax.validation.constraints.Negative")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(${number_min},-1)"
field.mock[groovy:it.hasAnn("javax.validation.constraints.NegativeOrZero")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(${number_min},0)"
field.mock[groovy:it.hasAnn("javax.validation.constraints.Negative")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(${number_min},0.01,${float_dmin})"
field.mock[groovy:it.hasAnn("javax.validation.constraints.NegativeOrZero")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(${number_min},0,${float_dmin})"
# Max+Min
field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&it.hasAnn("javax.validation.constraints.Min")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.Min")+","+it.ann("javax.validation.constraints.Max")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&it.hasAnn("javax.validation.constraints.Min")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.Min")+","+it.ann("javax.validation.constraints.Max")+",${float_dmin})"
# Max|Min
field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(0,"+it.ann("javax.validation.constraints.Max")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.Min")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.Min")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0,"+it.ann("javax.validation.constraints.Max")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.Min")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.Min")+")"
# DecimalMax+DecimalMin
field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.DecimalMin")+","+it.ann("javax.validation.constraints.DecimalMax")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.DecimalMin")+","+it.ann("javax.validation.constraints.DecimalMax")+",${float_dmin})"
# DecimalMax|DecimalMin
field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(0,"+it.ann("javax.validation.constraints.DecimalMax")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.DecimalMin")+")"
field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0,"+it.ann("javax.validation.constraints.DecimalMax")+",${float_dmin})"
field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.DecimalMin")+",${float_dmin})"
###set resolveMulti = error
示例
ValidationDemoDto.java
public class ValidationDemoDto {
@NotNull
private String str;
@Min(666)
private Integer minInt;
@Max(999)
private Integer maxInt;
@Min(666)
private Double minDouble;
@Max(999)
private double maxDouble;
@Min(666)
@Max(999)
private Integer rangeInt;
@Min(66)
@Max(9999)
private float rangeFloat;
@Negative
private Integer negative;
@NegativeOrZero
private Integer negativeOrZero;
@Positive
private Integer positive;
@PositiveOrZero
private Integer positiveOrZero;
@Positive
private Float positiveFloat;
@PositiveOrZero
private float positiveOrZeroFloat;
@Email
private String email;
@AssertTrue
private boolean assertTrue;
@AssertFalse
private boolean assertFalse;
//getter&setter
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
rangeInt | integer | 非必须 | mock: @integer(666,999) | ||
positiveOrZeroFloat | number | 非必须 | mock: @float(0,88888888,6) | ||
maxInt | integer | 非必须 | mock: @integer(0,999) | ||
minInt | integer | 非必须 | mock: @integer(666) | ||
assertFalse | boolean | 非必须 | mock: false | ||
maxDouble | number | 非必须 | mock: @float(0,999) | ||
minDouble | number | 非必须 | mock: @float(666) | ||
positive | integer | 非必须 | mock: @integer(1,88888888) | ||
positiveOrZero | integer | 非必须 | mock: @integer(0,88888888) | ||
str | string | 必须 | |||
negative | integer | 非必须 | mock: @integer(-888888888,-1) | ||
rangeFloat | number | 非必须 | mock: @float(66,9999,6) | ||
assertTrue | boolean | 非必须 | mock: true | ||
negativeOrZero | integer | 非必须 | mock: @integer(-888888888,0) | ||
positiveFloat | number | 非必须 | mock: @float(0.01,88888888,6) | ||
string | 非必须 | mock: @email |
field.mock.resolveProperty
用以开关是否解析
field.mock
规则结果中的占位符如${float_with_two}
默认为
true
,如果不希望解析, 可以设置为关闭
field.mock.resolveProperty=false
使用示例
配置如下:
#apifox mock
field.mock=#mock
#小数点后两位
float_with_two=@natural(0,10000).@natural(0,100)
DemoDto.java
public class DemoDto {
/**
* 价格
* @mock ${float_with_two}
*/
@NotNull
private Float price;
}
导出结果
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
price | number | 必须 | 价格 | mock: @natural(0,10000).@natural(0,100) |
field.name
用于设置输出/输入的字段名(用于 json 中字段名与类中字段名不一致)
默认推荐配置
#Support for Jackson annotations
field.name=@com.fasterxml.jackson.annotation.JsonProperty#value
#Support for Gson annotations
field.name=@com.google.gson.annotations.SerializedName#value
示例
TestJsonFieldBean.java
public class TestJsonFieldBean {
@JsonProperty("a")
private Long propertyA;
@SerializedName("b")
private Long propertyB;
//constructors...
//getters...
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
a | integer | 非必须 | mock: @natural(0,10000) | ||
b | integer | 非必须 | mock: @natural(0,10000) |
配置驼峰转下划线
#convert camel to underline
field.name=groovy:tool.camel2Underline(it.name())
field.required
用于标记字段是否为必须(即不可为空)
默认推荐配置
#Support for javax.validation annotations
field.required=@javax.validation.constraints.NotBlank
field.required=@javax.validation.constraints.NotNull
field.required=@javax.validation.constraints.NotEmpty
添加对 swagger @ApiModelProperty 支持
field.required=@io.swagger.annotations.ApiModelProperty#required
示例
SwaggerModel.java
public class SwaggerModel {
@ApiModelProperty(value = "字段 A", required = true)
private String a;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
a | integer | 必须 | mock: @natural(0,10000) |
constant.field.ignore
忽略常量字段
默认推荐配置
#ignore serialVersionUID
constant.field.ignore=serialVersionUID
使用如下配置代替:
#ignore serialVersionUID
constant.field.ignore=groovy:it.name()=="serialVersionUID"
示例
/**
* 用户类型
*/
public class UserTypeConstant implements Serializable {
private static final long serialVersionUID = -4607862808303533196L;
public static final int ADMIN = 1;//管理员
public static final int MEMBER = 2;//成员
public static final int GUEST = 3;//游客
}
对于如下注释
@see com.apifox.common.constant.UserTypeConstant
或者
{@link com.apifox.common.constant.UserTypeConstant}
将被解析为
枚举: 1,2,3
枚举备注: 1 :管理员 2 :成员 3 :游客
field.schema.title
数据模型中文名称
推荐配置
field.schema.title=#chineseName
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @chineseName 年龄
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 中文名 | 备注 | 其他信息 |
---|---|---|---|---|---|
a | integer | 年龄 |
field.schema.min.length
数据模型高级设置最小长度
推荐配置
field.schema.min.length=#minLength
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @minLength 6
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | format |
---|---|---|---|---|---|---|
a | integer | 6 |
field.schema.max.length
数据模型高级设置最大长度
推荐配置
field.schema.max.length=#maxLength
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @maxLength 6
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | format |
---|---|---|---|---|---|---|
a | integer | 6 |
field.schema.format
数据模型高级设置format
推荐配置
field.schema.format=#format
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @format long
*/
private Long age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | format |
---|---|---|---|---|---|---|
a | integer | integer<long> |
field.schema.pattern
数据模型高级设置用正则表达式约束字符串
推荐配置
field.schema.pattern=#pattern
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @pattern ^\d{3}$
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | format |
---|---|---|---|---|---|---|
a | string | ^\d{3}$ |
field.schema.const
数据模型高级设置常量
推荐配置
field.schema.const=#const
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @const test
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | 常量 |
---|---|---|---|---|---|---|
a | string | test |
field.schema.read.only
数据模型高级设置只读行为,数据模型用作请求参数时,该字段将会被隐藏
推荐配置
field.schema.read.only=#readOnly
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @readOnly
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | 常量 |
---|---|---|---|---|---|---|
a | string | Read Only |
field.schema.write.only
数据模型高级设置只读行为,数据模型用作返回结构时,该字段将会被隐藏
推荐配置
field.schema.write.only=#writeOnly
示例
SwaggerModel.java
public class SwaggerModel {
/**
* @writeOnly
*/
private String age;
}
作为 API 返回值导出:
名称 | 类型 | 最小长度 | 最大长度 | 行为 | pattern | 常量 |
---|---|---|---|---|---|---|
a | string | Write Only |
field.schema.permit.null
数据模型高级设置是否允许为 null,默认允许为 null
推荐配置
field.schema.permit.null=@javax.validation.constraints.NotBlank
public class SwaggerModel {
/**
* @NotBlank
*/
private String age;
}
枚举
enum.use.custom
用于设置使用
@see
枚举类型时的默认取值字段
假定有如下枚举类
public enum UserType {
// 管理员
ADMIN(1),
// 成员
MEMBER(2),
// 游客
GUEST(3);
private int code;
public int getCode() {
return code;
}
UserType(int code) {
this.code = code;
}
}
对于如下字段
/**
* 用户类型
*
* @see UserType
*/
private int type;
默认情况
- 由于 UserType 中不存在字段 type, 默认情况下这里的@see UserType 会被忽略掉
增加配置
- 做如下配置,设置
@see UserType
时默认使用code
字段作为取值
enum.use.custom[com.apifox.common.constant.UserType]=code
- 则上述注释将等价于
/**
* 用户类型
* @see UserType#code
*/
private int type;
- 导出 API 结果为:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
type | integer | 非必须 | 用户类型 | 枚举: 1,2,3 枚举说明: 1: 管理员 2: 成员 3: 游客 |
统一处理
- 特殊的, 声明如下接口:
package com.apifox.common.constant;
public interface BaseEnum {
Long getCode();
}
- 改造
UserType
,使其继承BaseEnum
public enum UserType implements BaseEnum {
...
}
- 则可做如下配置,将所有继承
BaseEnum
的类默认使用code
字段作为取值
enum.use.custom[groovy:it.isExtend("com.apifox.common.constant.BaseEnum")]=code
enum.use.by.type
默认使用类型一致的字段, 优先级低于
enum.use.custom
假定有如下枚举类
public enum UserType {
// 管理员
ADMIN(1),
// 成员
MEMBER(2),
// 游客
GUEST(3);
private int code;
public int getCode() {
return code;
}
UserType(int code) {
this.code = code;
}
}
对于如下字段
/**
* 用户类型
*
* @see UserType
*/
private int type;
推荐配置中有
enum.use.by.type=true
- 上述注释将被处理为:
/**
* 用户类型
* @see UserType#code
*/
private int type;
- 导出 API 结果为:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
type | integer | 非必须 | 用户类型 | 枚举: 1,2,3 枚举说明: 1: 管理员 2: 成员 3: 游客 |
enum.use.ordinal
用于设置使用
@see
枚举类型时的默认使用ordinal
作为取值
优先级低于
enum.use.custom
和enum.use.by.type
所以要使用
enum.use.ordinal
需要先在推荐配置中取消enum.use.by.type
假定有如下枚举类
public enum UserType {
// 管理员
ADMIN(1),
// 成员
MEMBER(2),
// 游客
GUEST(3);
private int code;
public int getCode() {
return code;
}
UserType(int code) {
this.code = code;
}
}
对于如下字段
默认情况
- 由于 UserType 中不存在字段 type, 默认情况下这里的
@see UserType
会被忽略掉
增加配置
- 做如下配置, 设置
@see UserType
时默认使用ordinal
字段作为取值
enum.use.ordinal[com.apifox.common.constant.UserType]=true
- 则上述注释将等价于
/**
* 用户类型
* @see UserType#ordinal()
*/
private int type;
- 导出 API 结果为:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
type | integer | 非必须 | 用户类型 | 枚举: 1,2,3 枚举说明: 1: 管理员 2: 成员 3: 游客 |
统一处理
- 特殊的, 声明如下接口:
package com.apifox.common.constant;
public interface BaseEnum {
}
- 改造
UserType,
使其继承BaseEnum
public enum UserType implements BaseEnum {
...
}
- 则可做如下配置, 将所有继承
BaseEnum
的类默认使用ordinal
作为取值
enum.use.ordinal[groovy:it.isExtend("com.apifox.common.constant.BaseEnum")]=true
整个项目所有 {#整个项目所有}@see {#see}
枚举类都默认使用 {#枚举类都默认使用}ordinal {#ordinal}
作为取值
enum.use.ordinal=true
enum.use.name
用于设置使用
@see
枚举类型时的默认使用name
作为取值
优先级低于
enum.use.custom
和enum.use.by.type
所以要使用
enum.use.name
需要先在推荐配置中取消enum.use.by.type
假定有如下枚举类
public enum UserType {
// 管理员
ADMIN(1),
// 成员
MEMBER(2),
// 游客
GUEST(3);
private int code;
public int getCode() {
return code;
}
UserType(int code) {
this.code = code;
}
}
对于如下字段
/**
* 用户类型
*
* @see UserType
*/
private int type;
默认情况
- 由于 UserType 中不存在字段 type, 默认情况下这里的
@see UserType
会被忽略掉
增加配置
- 做如下配置, 设置
@see UserType
时默认使用name
字段作为取值
enum.use.name[com.apifox.common.constant.UserType]=true
- 则上述注释将等价于
/**
* 用户类型
* @see UserType#name()
*/
private String type;
- 导出 API 结果为:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
type | string | 非必须 | 用户类型 | 枚举: ADMIN, MEMBER, GUEST 枚举备注: ADMIN: 管理员 MEMBER: 成员 GUEST: 游客 |
统一处理
- 特殊的, 声明如下接口:
package com.apifox.common.constant;
public interface BaseEnum {
}
- 改造
UserType
,使其继承BaseEnum
public enum UserType implements BaseEnum {
...
}
- 则可做如下配置,将所有继承
BaseEnum
的类默认使用name
作为取值
enum.use.name[groovy:it.isExtend("com.apifox.common.constant.BaseEnum")]=true
整个项目所有 {#整个项目所有}@see {#see}
枚举类都默认使用 {#枚举类都默认使用}name {#name}
作为取值
enum.use.name=true
JSON 配置
json.rule.convert
用于设置某些类型转换为其他类型处理, 通常用于使用了 Spring 的自定义类型转换器的情况
默认推荐配置
#The ObjectId and Date are parsed as strings
json.rule.convert[org.bson.types.ObjectId]=java.lang.String
json.rule.convert[java.util.Date]=java.lang.String
json.rule.convert[java.sql.Timestamp]=java.lang.String
json.rule.convert[java.time.LocalDateTime]=java.lang.String
json.rule.convert[java.time.LocalDate]=java.lang.String
#resolve HttpEntity/RequestEntity/ResponseEntity
###set resolveProperty = false
json.rule.convert[#regex:org.springframework.http.HttpEntity]=java.lang.Object
json.rule.convert[#regex:org.springframework.http.HttpEntity<(.*?)>]=${1}
json.rule.convert[#regex:org.springframework.http.RequestEntity<(.*?)>]=${1}
json.rule.convert[#regex:org.springframework.http.RequestEntity]=java.lang.Object
json.rule.convert[#regex:org.springframework.http.ResponseEntity<(.*?)>]=${1}
json.rule.convert[#regex:org.springframework.http.ResponseEntity]=java.lang.Object
###set resolveProperty = true
json.rule.enum.convert
用于设置枚举类型的转换 优先级低于
json.rule.convert
假定有如下枚举类
public enum UserType {
// 管理员
ADMIN(1),
// 成员
MEMBER(2),
// 游客
GUEST(3);
private int code;
public int getCode() {
return code;
}
UserType(int code) {
this.code = code;
}
}
对于如下字段
/**
* 用户类型
*/
private UserType type;
默认情况
默认将枚举类型转换为
String
处理,给出可用值为枚举中的实例名上述字段将被处理为
/**
* 用户类型
* @see UserType
*/
private String type;
- 导出 API 结果为:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
type | string | 非必须 | 用户类型 | 枚举: ADMIN,MEMBER,GUEST 枚举备注: ADMIN :管理员 MEMBER :成员 GUEST :游客 |
增加配置
- 做如下配置,将其转换为
int
处理,给出可用值为枚举中的type
字段
json.rule.enum.convert[com.apifox.common.constant.UserType]=~#type
- 则上述字段将被处理为
/**
* 用户类型
* @see UserType#type
*/
private int type;
- 导出 API 结果为:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
type | integer | 非必须 | 用户类型 | 枚举: 1,2,3 枚举备注: 1 :管理员 2 :成员 3 :游客 |
统一处理
- 特殊的, 声明如下接口:
package com.apifox.common.constant;
public interface TypeAble {
int getType();
}
- 改造
UserType
,使其继承TypeAble
public enum UserType implements TypeAble {
...
}
- 则可做如下配置,将所有继承
TypeAble
的类转换为int
处理,给出可用值为枚举中的type
字段
json.rule.enum.convert[groovy:it.isExtend("com.apifox.common.constant.TypeAble")]=~#type
json.rule.field.ignore
忽略字段(设置某些字段不出现在 json 中,或不需要请求时给出)
deprcated
, seefield.ignore
默认推荐配置
#Support for Jackson annotations
json.rule.field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value
#Support for Gson annotations
json.rule.field.ignore=!@com.google.gson.annotations.Expose#serialize
示例
TestJsonIgnoreBean.java
public class TestJsonIgnoreBean {
@Expose(serialize = true)
private Long shouldNotIgnoreForGson;
@Expose(serialize = false)
private Long shouldIgnoreForGson;
@JsonIgnore(false)
private Long shouldNotIgnoreForJackson;
@JsonIgnore
private Long shouldIgnoreForJackson;
//constructors...
//getters...
}
作为 API 返回值导出:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
shouldNotIgnoreForGson | integer | 非必须 | mock: @natural(0,10000) | ||
shouldNotIgnoreForJackson | integer | 非必须 | mock: @natural(0,10000) |
定制化配置示例
- 忽略指定名称的字段: 配置如下:
# ignore field 'log'
json.rule.field.ignore=log
将忽略如下字段:
private String log;
- 忽略指定类型的字段:
配置如下:
# ignore field 'log' typed xxx.xxx.Log
json.rule.field.ignore=groovy:it.type().name()=="xxx.xxx.Log"
将忽略如下字段:
private Log xxx;
- 忽略指定 modifier 的字段:
配置如下:
#ignore transient field
json.rule.field.ignore=groovy:it.hasModifier("transient")||it.hasModifier("protected")
将忽略如下字段:
private transient Int xxx;
protected Long yyy;
json.rule.field.name
用于设置输出/输入的字段名(用于 json 中字段名与类中字段名不一致)
默认推荐配置
#Support for Jackson annotations
json.rule.field.name=@com.fasterxml.jackson.annotation.JsonProperty#value
#Support for Gson annotations
json.rule.field.name=@com.google.gson.annotations.SerializedName#value
示例
TestJsonFieldBean.java
public class TestJsonFieldBean {
@JsonProperty("a")
private Long propertyA;
@SerializedName("b")
private Long propertyB;
//constructors...
//getters...
}
作为 API 返回值导出
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
a | integer | 非必须 | mock: @natural(0,10000) | ||
b | integer | 非必须 | mock: @natural(0,10000) |
json.rule.class.description
用于设置类的描述信息
推荐配置
json.rule.class.description[#class.desc]=@io.swagger.annotations.ApiModel#description
示例
User.java
@ApiModel(value = "User", description = "User model")
public class User {
private Long propertyA;
private Long propertyB;
//constructors...
//getters...
}
methodDoc
mdoc.class.filter
用于选择哪些类可以导出方法(rpc)文档, 根据当前项目情况
示例
- 如果所有的 RPC 接口类都以
Client
结尾, 则可配置:
mdoc.class.filter=groovy:it.name().endsWith("Client")
- 如果所有的 RPC 接口类包都在
a.b.c.client
, 则可配置:
mdoc.class.filter=groovy:it.name().startsWith("a.b.c.client")
mdoc.method.path
用于设置方法文档(rpc)的路径
为了防止重载方法覆盖,默认生成的 path 后加上了参数信息:
$className/$methodName/$args
根据项目情况, 可自行配置以简化路径长度
修改默认行为
假设有如下类
package com.apifox.dubbo.demo.client;
/**
* 用户相关 Client
*
* @module user_dubbo
*/
public interface UserClient {
/**
* 更新用户名
*
* @param id 用户 id
* @param newName 新的用户名
* @param slogon 个人签名
* @deprecated 改用{@link #update(UserInfo)}
*/
public UserInfo set(long id, String newName,
String slogon,
long times);
}
默认情况下
- 导出的路径为:
/com.apifox.dubbo.demo.client.UserClient/set/long/java.lang.String/java.lang.String/long/
如果确认无重载方法, 可以尝试去掉参数信息:
- 配置如下:
mdoc.method.path=groovy:it.containingClass().name()+"/"+it.name()
- 导出的接口路径为:
/com.apifox.dubbo.demo.client.UserClient/set
可以尝试去掉包名:
- 配置如下:
mdoc.method.path=groovy:it.containingClass().getSimpleName()+"/"+it.name()
- 导出的接口路径为:
/UserClient/set
可以进一步将类名转换为小写:
- 配置如下:
mdoc.method.path=groovy:it.containingClass().getSimpleName().toLowerCase()+"/"+it.name()
- 导出的接口路径为:
/userclient/update
mdoc.method.http.method
设置方法文档(rpc)HTTP 请求方式, 默认
POST
修改默认行为
将无参方法设置为GET
- 配置如下:
mdoc.method.http.method=groovy:it.argCnt()==0?"GET":null
支持的回调
export.after
每个 api 导出完成后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
method | api |
示例
增加接口描述信息
export.after=groovy:api.appendDesc("\n 这个接口已废弃\n")
header 中 token 不需要显示传参
export.after=groovy:api.removeHeader("token")
修改 url
export.after=groovy:api.setPath("/pre"+api.path())
response 的 header 中会返回当前用户会员等级
export.after=groovy:api.addResponseHeader("level","","true","当前用户会员等级")
将 method 上的@version xxx
加入到url
中
export.after[#version]=groovy:```
def tag = it.doc("version")
def url = api.path()
if(url.contains("?")){
url = url +"&version=" + tag
}else{
url = url +"?version=" + tag
}
api.setPath(url)
```
http.call.after
http 请求后回调
注意:插件所有的
http
请求都将触发此回调
规则目标(上下文 it) | 附加上下文 |
---|---|
无 | request, response |
示例
记录插件所有的请求的响应
http.call.after=groovy:logger.info("response:"+response.string())
某个接口请求成功后执行其他接口
http.call.after=groovy:```
//判断是不是指定接口
if(request.code()==200&&request.url().endsWith("/xxx")){
httpClient.post("http://xxx/xxx")
.contentType("application/json")
.body({"xxx":"xxx","xxx":"xxx"})
.call()
}
```
Call
自动登录(Cookie)
http.call.after=groovy:```
//判断是不是需要登录的接口
if(response.code()==401){
httpClient.post("http://xxx/login")
.contentType("application/json")
.body({"username":"xxx","passwd":"xxx"})
.call()
response.discard()//丢弃这一次的请求结果
}
```
Call
自动登录(Token)
http.call.after=groovy:```
//判断是不是需要登录的接口
if(response.code()==401){
def loginResponse = httpClient.post("http://xxx/login")
.contentType("application/json")
.body({"username":"xxx","passwd":"xxx"})
.call()
def token = loginResponse.firstHeader("token")
localStorage.set("token",token)
response.discard()//丢弃这一次的请求结果
}
```
http.call.before=groovy:```
//从 localStorage 取 token
request.header("token",localStorage.get("token"))
```
host
不固定
//可以尝试通过正则获取当前请求的 host
def host = regex.getGroup1("(https?://.+?)/.*?",request.url());
x-www-form-urlencoded
提交
httpClient.post("http://xxx/login")
.contentType("application/x-www-form-urlencoded")
.param("username","name")
.param("password","pwd")
.call();
http.call.before
http 请求前回调
注意:插件所有的
http
请求都将触发此回调
规则目标(上下文 it) | 附加上下文 |
---|---|
无 | request |
示例
记录插件所有的请求
http.call.before=groovy:logger.info("call:"+request.url())
自动加入指定 token
http.call.before=groovy:```
request.header("token","xxxxxxxxxxxxx")
```
自动加入从 localStorage 获取的 token
http.call.before=groovy:```
//从 localStorage 取 token
request.header("token",localStorage.get("token"))
```
api.class.parse.before
- 解析 controller 类前回调
规则目标(上下文 it) | 附加上下文 |
---|---|
class | 无 |
示例
增加 log
api.class.parse.before=groovy:logger.info("开始解析 controller:"+it.name())
api.class.parse.after
- 解析 controller 类后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
class | 无 |
示例
增加 log
api.class.parse.after=groovy:logger.info("controller:"+it.name()+"解析完成")
api.method.parse.before
- 解析 api 方法前回调
规则目标(上下文 it) | 附加上下文 |
---|---|
method | 无 |
示例
增加 log
api.method.parse.before=groovy:logger.info("开始解析 api:"+it.name())
api.method.parse.after
- 解析 api 方法后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
method | 无 |
示例
增加 log
api.method.parse.after=groovy:logger.info("api:"+it.name()+"解析完成")
api.param.parse.before
- 解析 api 参数前回调
规则目标(上下文 it) | 附加上下文 |
---|---|
param | 无 |
示例
增加 log
api.method.parse.before=groovy:logger.info("开始解析 api 参数:"+it.name())
api.param.parse.after
- 解析 api 参数后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
param | 无 |
示例
增加 log
api.param.parse.after=groovy:logger.info("api 参数:"+it.name()+"解析完成")
json.class.parse.before
- 解析类型前回调
规则目标(上下文 it) | 附加上下文 |
---|---|
class | 无 |
示例
增加 log
api.class.parse.before=groovy:logger.info("开始解析类:"+it.name())
json.class.parse.after
- 解析类型后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
class | 无 |
示例
增加 log
api.class.parse.after=groovy:logger.info("类:"+it.name()+"解析完成")
json.field.parse.before
- 解析属性(字段)前回调
规则目标(上下文 it) | 附加上下文 |
---|---|
field | 无 |
示例
增加 log
json.field.parse.before=groovy:logger.info("开始解析属性:"+it.name())
json.field.parse.after
- 解析属性(字段)后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
field | 无 |
示例
增加 log
json.field.parse.after=groovy:logger.info("属性:"+it.name()+"解析完成")
json.method.parse.before
- 解析 getter/setter 方法前回调
规则目标(上下文 it) | 附加上下文 |
---|---|
method | 无 |
示例
增加 log
json.method.parse.before=groovy:logger.info("开始解析方法:"+it.name())
json.method.parse.after
- 解析 getter/setter 方法后回调
规则目标(上下文 it) | 附加上下文 |
---|---|
method | 无 |
示例
增加 log
json.method.parse.after=groovy:logger.info("方法:"+it.name()+"解析完成")