跳到主要内容

可配置规则

支持的规则

基础配置

     规则的 key规则目标(上下文 it)版本规则描述
    folder.namemethod1.1.11+设置 api 所属文件夹
    class.prefix.pathclass1.1.11+设置 API 请求前缀
    ignoreclass/method1.1.11+忽略 API
    moduleclass1.1.11+为 api 分组

API 配置

     规则的 key规则目标(上下文 it)版本规则描述
    api.namemethod1.1.11+设置 api 的名称
    method.docmethod1.1.11+方法(api)的额外注释
    method.content.type-1.1.11+用以设置 API 请求的 content-type
    method.default.http.methodmethod1.1.11+设置默认的 api 的 HttpMethod
    method.additional.headermethod1.1.11+API 需要额外的 header,
{name: "header name",value: "",desc: "",required:false, example:""}
    method.additional.parammethod1.1.11+API 需要额外的参数
{name: "param name",value: "defaultValue",desc: "",required:false}
method.returnmethod1.1.11+设置返回值的类型
method.return.mainmethod1.1.11+设置返回值的核心主体
path.multi-1.1.11+设置返回值的核心主体

请求参数

     规则的 key规则目标(上下文 it)版本规则描述
    param.default.valuearg1.1.11+API 参数的默认值
    param.example-1.1.11+用以设置参数的示例值
    param.descriptionarg1.1.11+参数的额外注释
    param.typearg1.1.11+用于设置 API 参数在 HTTP 请求中的类型
    param.ignorearg1.1.11+忽略 API 参数
    param.requiredarg1.1.11+API 参数是否为必须(即不可为空)

数据模型字段

     规则的 key规则目标(上下文 it)版本规则描述
    field.default.value-1.1.11+用以设置字段的默认值
    field.example-1.1.11+用以设置字段的示例值
field.descriptionfield1.1.11+字段的额外注释
    field.ignorefield1.1.11+忽略字段(设置某些字段不出现在 json 中,或不需要请求时给出)
field.mockfield1.1.11+生成 mock 信息
    field.mock.resolveProperty-1.1.11+用以开关是否解析field.mock规则结果中的占位符
    field.namefield1.1.11+设置输出的字段名(用于 json 中字段名与类中字段名不一致)
    field.requiredfield1.1.11+字段是否为必须(即不可为空)
    constant.field.ignorefield1.1.11+忽略常量字段

枚举

     规则的 key规则目标(上下文 it)版本规则描述
    enum.use.customclass1.1.11+用于设置使用@see枚举类型时的默认取值字段, 优先级高于enum.use.by.type
    enum.use.by.typeclass1.1.11+用于设置使用@see枚举类型时的默认使用类型一致的字段, 优先级低于enum.use.custom
    enum.use.ordinalclass1.1.11+用于设置使用@see枚举类型时的默认使用ordinal作为取值
    enum.use.nameclass1.1.11+用于设置使用@see枚举类型时的默认使用name作为取值

JSON 配置

     规则的 key规则目标(上下文 it)版本规则描述
json.rule.convert-1.1.11+用于设置某些类型转换为其他类型处理, 通常用于使用了 Spring 的自定义类型转换器的情况
    json.rule.enum.convertclass1.1.11+用于枚举类型的特殊转换
    ~json.rule.field.ignore~field1.1.11+忽略字段(设置某些字段不出现在 json 中,或不需要请求时给出) 已废弃, 使用field.ignore代替
    ~json.rule.field.name~field1.1.11+设置输出的字段名(用于 json 中字段名与类中字段名不一致)

methodDoc

     规则的 key规则目标(上下文 it)版本规则描述
    mdoc.class.filterclass1.1.11+选择哪些类可以导出方法文档(rpc)
    mdoc.method.pathmethod1.1.11+设置方法文档(rpc)的路径
    mdoc.method.http.methodmethod1.1.11+设置方法文档(rpc)HTTP 请求方式

支持的简单配置

简单配置无上下文

     规则的 key版本配置类型规则描述示例
    dev1.1.11+bool启动开发模式,打印更详细的日志dev=true
    max.deep1.1.11+int解析json时最大深度,默认 6max.deep=8
    max.elements1.1.11+int解析json时最大字段数,默认 256max.elements=512
    json.cache.disable1.1.11+bool禁用json解析缓存json.cache.disable=true
    http.timeOut1.1.11+inthttp请求的超时时间(s),优先级高于settinghttp.timeOut=5
    auto.format.url1.1.11+bool导入时是否格式化url,确保url/开始,且将[a-zA-Z0-9-/_:.{}?=!]之外的字符替换为/auto.format.url=false
    field.mock.resolveProperty1.1.11+bool是否处理mock信息中的占位符${xxx}field.mock.resolveProperty=true
    api.tag.delimiter1.1.11+stringtag的分割符, 默认为,api.tag.delimiter=,#

支持的回调

部分回调方法中可能没有it, 但可能会有附加的上下文供使用

     规则的 key规则目标(上下文 it)附加上下文版本规则描述
    api.class.parse.beforeclass1.1.11+解析api前回调
    api.class.parse.afterclass1.1.11+解析api后回调
    api.method.parse.beforemethod1.1.11+解析api方法前回调
    api.method.parse.aftermethod1.1.11+解析api方法后回调
    api.param.parse.beforeparam1.1.11+解析api参数前回调
    api.param.parse.afterparam1.1.11+解析api参数后回调
    export.aftermethodapi1.1.11+每个 api 导出完成后回调
    http.call.beforerequest1.1.11+http 请求前回调
    http.call.afterrequest, response1.1.11+http 请求后回调
    json.class.parse.beforeclass1.1.11+解析类型前回调
    json.class.parse.afterclass1.1.11+解析类型后回调
    json.field.parse.beforefield1.1.11+解析类型字段前回调
    json.field.parse.afterfield1.1.11+解析类型字段后回调
    json.method.parse.beforemethod1.1.11+解析类型方法 (getter/setter) 前回调
    json.method.parse.aftermethod1.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{...}
  • 字面量

    • boolean 如: api.open=true
    • string 如: api.status=done

高级脚本规则

  • 由于JDK11js引擎可能缺失, 故推荐使用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 一级目录/二级目录后归属到一级目录/二级目录。 多级目录使用斜杠/分隔。其中\/为特殊字符,需要转义,\/表示字符/\\表示字符\

class.prefix.path

设置 API 请求前缀

默认推荐配置

#Resolve spring properties
###set ignoreUnresolved = true
class.prefix.path=${server.servlet.context-path}
###set ignoreUnresolved = false

使用推荐配置后,可识别如下 spring 配置

spring application.properties

server.servlet.context-path=/demo

spring application.yaml/application.yml

server:
servlet:
context-path: /demo

自定义 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");
}

}

method.doc

API 接口说明,方法(API)的额外注释

默认推荐配置

#deprecated info(java)
method.doc[#deprecated]=groovy:"\n「已废弃」" + it.doc("deprecated")
method.doc[@java.lang.Deprecated]=「已废弃」

method.doc[groovy:it.containingClass().hasDoc("deprecated")]=groovy:"\n「已废弃」" + it.containingClass().doc("deprecated")
method.doc[groovy:it.containingClass().hasAnn("java.lang.Deprecated")]=「已废弃」


#deprecated info(kotlin)
method.doc[@kotlin.Deprecated]=groovy:"\n「已废弃」" + it.ann("kotlin.Deprecated","message")
method.doc[groovy:it.containingClass().hasAnn("kotlin.Deprecated")]=groovy:"\n「已废弃」 " + it.containingClass().ann("kotlin.Deprecated","message")

添加对 swagger @ApiOperation 支持

method.doc=@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.content.type

用于设置 API 请求默认的content-type, 插件依然会在必要的时候强行覆盖掉

如当遇到@RequestBody时, 将被强行覆盖为application/json

默认情况下, 插件优先使用application/x-www-form-urlencoded, 如希望优先使用multipart/form-data

配置如下:

method.content.type=multipart/form-data

method.default.http.method

设置默认的 api 的 HttpMethod

默认情况下, 当 API 上未指定 HttpMethod, 且无特殊参数时默认使用GET

如希望默认使用POST

配置如下:

method.default.http.method=POST

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 的响应:
名称类型是否必须默认值备注其他信息
msgstring非必须响应消息mock:
codeinteger非必须响应码mock: 0
datainteger非必须响应数据
当前用户类型,[用户类型]
枚举: 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 的响应:
名称类型是否必须默认值备注其他信息
msgstring非必须响应消息mock:
codeinteger非必须响应码mock: 0
+datainteger[]非必须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...
}

path.multi

用于当 API 有多个可用路径时如何处理 目前可用策略(策略不区分大小写):

可用策略策略描述
FIRST选择第一个可用路径
LAST选择最后一个可用路径
LONGEST选择最长的可用路径
SHORTEST选择最短的可用路径
ALL为每一个可用路径生成一个 api

可能的配置如下:

  1. 选择第一个可用路径
path.multi=first
  1. 选择最后一个可用路径
path.multi=last
  1. 选择最长的可用路径
path.multi=longest
  1. 选择最短的可用路径
path.multi=shortest
  1. 为每一个可用路径生成一个 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.default.value

用于设置 API 参数的默认值

添加对 swagger @ApiParam 支持

param.default.value=@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.example

参数示例信息

示例

配置如下:

param.demo=groovy:it.method().doc("demo",it.name())

使用如下:

/**
* @demo newName apifox
*/
@RequestMapping(value = "/set", method = RequestMethod.PUT)
public Object set(@RequestParam String newName){
...
}

param.doc

参数的额外注释

在注释中给出参数类型

param.doc=js:"类型:"+it.type().name()

在注释中给出参数类型并去掉 java 包名

param.doc=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.http.type

用于设置 API 参数在 HTTP 请求中的类型(位置:body/form/query)

@RequestBody/@ModelAttribute/@RequestHeader/@PathVariable等忽略此规则

参数注解有@RequestParamHttpMehotdGET也忽略此规则

其他不满足规则的参数在规则缺省的情况下, 优先采取query模式

配置示例

全设置为 form, 优先使用表单进行提交:

param.http.type=form

RequestParam 作为 query, 其他做为 form:

param.http.type[@org.springframework.web.bind.annotation.RequestParam]=query
param.http.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.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");
}

}

导出结果如下:

请求参数:

参数名称是否必须示例备注
seed666666seed for mock

数据模型字段

field.default.value

用于设置字段的默认值

原生编码支持

默认的所有含有默认初始值的字段, 取其默认初始值. 如:

private Integer code = 200;//响应码

额外的配置

配置如下:

field.default.value=#default

DemoDto.java

public class DemoDto {

/**
* 价格
* @default 666
*/
@NotNull
private Float price;

...
}

导出结果如下:

名称类型是否必须默认值备注其他信息
pricenumber必须666价格

field.demo

字段示例信息

示例

配置如下:

field.demo=#demo

使用如下:

/**
* @demo 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 返回值导出:

名称类型是否必须默认值备注其他信息
astring非必须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 返回值导出:

名称类型是否必须默认值备注其他信息
shouldNotIgnoreForGsoninteger非必须mock: @natural(0,10000)
shouldNotIgnoreForJacksoninteger非必须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 返回值导出:

名称类型是否必须默认值备注其他信息
namestring非必须用户名mock: tangcent
ageinteger非必须年龄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 返回值导出:

名称类型是否必须默认值备注其他信息
birthDaystring非必须生日mock: @date
regtimestring非必须注册时间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 返回值导出:

名称类型是否必须默认值备注其他信息
rangeIntinteger非必须mock: @integer(666,999)
positiveOrZeroFloatnumber非必须mock: @float(0,88888888,6)
maxIntinteger非必须mock: @integer(0,999)
minIntinteger非必须mock: @integer(666)
assertFalseboolean非必须mock: false
maxDoublenumber非必须mock: @float(0,999)
minDoublenumber非必须mock: @float(666)
positiveinteger非必须mock: @integer(1,88888888)
positiveOrZerointeger非必须mock: @integer(0,88888888)
strstring必须
negativeinteger非必须mock: @integer(-888888888,-1)
rangeFloatnumber非必须mock: @float(66,9999,6)
assertTrueboolean非必须mock: true
negativeOrZerointeger非必须mock: @integer(-888888888,0)
positiveFloatnumber非必须mock: @float(0.01,88888888,6)
emailstring非必须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;

}

导出结果

名称类型是否必须默认值备注其他信息
pricenumber必须价格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 返回值导出:

名称类型是否必须默认值备注其他信息
ainteger非必须mock: @natural(0,10000)
binteger非必须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 返回值导出:

名称类型是否必须默认值备注其他信息
ainteger必须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 :游客

枚举

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 结果为:
名称类型是否必须默认值备注其他信息
typeinteger非必须用户类型枚举: 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 结果为:
名称类型是否必须默认值备注其他信息
typeinteger非必须用户类型枚举: 1,2,3
枚举说明: 1: 管理员 2: 成员 3: 游客

enum.use.ordinal

用于设置使用@see枚举类型时的默认使用ordinal作为取值

优先级低于enum.use.customenum.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 结果为:
名称类型是否必须默认值备注其他信息
typeinteger非必须用户类型枚举: 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.customenum.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 结果为:
名称类型是否必须默认值备注其他信息
typestring非必须用户类型枚举: 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 结果为:
名称类型是否必须默认值备注其他信息
typestring非必须用户类型枚举: 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 结果为:
名称类型是否必须默认值备注其他信息
typeinteger非必须用户类型枚举: 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, see field.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 返回值导出:

名称类型是否必须默认值备注其他信息
shouldNotIgnoreForGsoninteger非必须mock: @natural(0,10000)
shouldNotIgnoreForJacksoninteger非必须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 返回值导出:

名称类型是否必须默认值备注其他信息
ainteger非必须mock: @natural(0,10000)
binteger非必须mock: @natural(0,10000)

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)附加上下文
methodapi

示例

增加接口描述信息

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())

自动加入指定 toekn

http.call.before=groovy:```
request.header("token","xxxxxxxxxxxxx")
```

自动加入从 localStorage 获取的 toekn

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()+"解析完成")