# Torna插件

该插件通过扫描 Java 源代码和 Spring MVC 注解,自动生成标准化接口文档并推送到 Torna 平台。

插件项目地址 (opens new window)

# 功能特性

  • 支持springmvc接口推送
  • 支持dubbo接口推送
  • 支持接口分类管理
  • 支持配置文件继承
  • 支持第三方jar源码扫描
  • 支持重写第三方jar包类的字段描述和示列
  • 支持隐藏第三方jar包类的字段
  • 支持接口/字段隐藏
  • 全局定义默认示例值
  • 全局定义枚举字段code
  • 支持重写通用返回类(Result<T>)描述/示例值
  • 支持枚举描述国际化
  • 支持cli方式推送

# 1. 使用方式

# 1.1 引入依赖

在项目的启动模块 pom.xml 中引入依赖

<dependency>
    <groupId>cn.torna</groupId>
    <artifactId>torna-plugin</artifactId>
    <version>版本号</version>
    <scope>test</scope>
</dependency>

最新版本:maven

# 1.2 添加配置文件

在项目 src/main/resources 目录下创建 torna.yml 配置文件

# Torna 插件配置

# Torna 推送地址
url: http://localhost:7700/api
# Torna 推送 token
token: "xx"
# 推送人,如果为空,则获取当前电脑用户名
author: ""

# 扫描配置,可配置多个
## 前缀说明:
## package: 扫描包
## class: 扫描类,类全名
## method: 扫描方法,格式:类全名#方法名
## path: 扫描目录
scans: 
  # 扫描包下所有接口
  - "package:cn.torna.plugin.test.controller"
  # 扫描文件下所有接口
  # - "class:cn.torna.plugin.test.controller.UserController"
  # # 扫描单个接口
  # - "method:cn.torna.plugin.test.controller.UserController#postPage3"
# 调试模式,true:打印推送内容
debug: false

修改配置文件中的 urltoken 为自己的 Torna 地址和 token。

修改扫描配置

# 1.3 执行推送

在代码或单元测试中调用以下方法:

import cn.torna.plugin.core.TornaPlugin;

public class PushDoc {
    public static void main(String[] args) {
        // 自动查找 classpath 下的 torna.yml 并推送
        TornaPlugin.pushDoc();
        // 或指定文件
        // TornaPlugin.pushDoc("torna-1.yml");
    }
}

# 2. Tag 使用说明

# 2.1 类级别

  • @category: 指定文档目录,支持多级(使用/隔开,如 @category 模块/子模块)。若不指定,默认使用类注释。
  • @author: 模块作者。
  • @hidden 或 @ignore: 忽略该 Controller 下的所有接口。
  • @enum.code: 指定枚举值字段,如:@enum.code type
  • @dubbo: 指定当前接口dubbo服务

示列代码:

/**
 * User Management
 * 
 * @category 一级/二级
 * @author jim
 */
@RestController
@RequestMapping("/user")
public class UserController {}

// 指定枚举值字段
/**
 * 是/否枚举
 * 
 * @enum.code value
 */
@AllArgsConstructor
@Getter
public enum YesOrNoEnum {
    /**
     * 是-yes
     */
    YES(1, "是"),
    /**
     * 否-no
     */
    NO(0, "否");
    private Integer value;
    private String desc;
}

# 2.2 方法级别 (Method)

  • @author: 接口作者(优先于类级别)。
  • @apiNote: 接口详细描述。
  • @version 或 @since: 指定接口版本号。
  • @deprecated: 标记接口已废弃及废弃原因。
  • @hidden 或 @ignore: 忽略该接口。
  • @response.字段名: 重写返回对象的字段描述和示例值,格式:@response.字段名 描述信息|示例值
  • @codes: 指定错误码,格式:code:描述:解决方案|code:描述
  • @param: 参数描述,格式:@param 参数名 描述|示例值
  • @return: 定义单值返回的描述个示例值,格式:@return 描述|示例值

示列代码:

/**
 * Get user by ID
 * 
 * @param id    User ID|123
 * @param name  User name | jim
 * @param token Token|xxxxx
 * @return User info
 * @author tanghc
 * @apiNote This is a note for the API
 */
@GetMapping("/get/{name}")
public Result<UserDTO> getUser(@RequestParam @NotNull Long id, @PathVariable String name,
        @RequestHeader String token) {
    return Result.success(new UserDTO());
}

/**
 * 单值返回
 * 
 * @param id   User ID|123
 * @param name User name|jim
 * @return return user name...|xxxx
 * @author tanghc
 * @apiNote This is a note for the API
 * @deprecated This API is deprecated
 */
@GetMapping("/get1/{name}")
public String getUser1(@RequestParam @NotNull Long id) {
    return "success";
}

/**
 * 重写Result中的字段描述和示例值;指定错误码
 * 
 * @param userDTO User data
 * 
 * @response.data this is a response data|xxxxxxx
 * @response.code 200 is success|200
 * @response.message message|success
 * @codes 200:success|300:用户姓名格式错误:请输入正确的姓名
 * @apiNode: Batch create user.
 * @return Success status
 */
@PostMapping("/createBatch")
public Result<String> createBatch(@RequestBody List<UserDTO> userDTO) {
    return Result.success("success");
}

# 2.3 参数/字段级别 (Field/Param)

  • @required: 标记参数必填(支持 JSR-303 注解如 @NotNull)。
  • @mock 或 @example: 指定参数示例值。
  • @enum: 标记字段为枚举并指定枚举类,格式:@enum {EnumClass}
  • @hidden 或 @ignore: 忽略该字段。

示列代码:

public class UserDTO {
    /**
     * User ID
     * @mock 1
     */
    private Long id;
    /**
     * User name
     * @example jim
     */
    @NotBlank
    @Length(max = 20)
    private String username;
    /**
     * User age
     * @required
     */
    private Integer age;
    /**
     * User gender
     * @enum {GenderEnum}
     * @example 1
     */
    private Integer gender;

    // ↓ 指定枚举字段 {@link com.xx.StatusEnum}
    /**
     * 枚举字段 {@link com.xx.StatusEnum}
     */
    private Integer status;
}

# 3. 配置文件说明 (torna.yml)

  • 完整配置:
# Torna 插件默认配置

# 继承父文件,当前文件相对路径,如果父文件在上级目录,使用 ../torna.yml
# parent: ""

# Torna 推送地址
url: http://localhost:7700/api
# Torna 推送 token
token: "xx"
# 推送人,如果为空,则获取当前电脑用户名
author: ""

# 源码绝对路径,默认可不填
#srcDirs:
#  - "/Users/xx/Projects/torna-plugin/src"

# 本地maven仓库全路径,默认为空,为空则自动获取,如:C:/Users/xx/.m2/repository
#mavenRepositoryPath: ""

# 是否启用测试源码
# enableTestSrc: false

# 扫描配置,可配置多个
## 前缀说明:
## package: 扫描包
## class: 扫描类,类全名
## method: 扫描方法,格式:类全名#方法名
scans:
# 扫描包下所有接口
# - "package:cn.torna.plugin.test.controller"
# 扫描文件下所有接口
# - "class:cn.torna.plugin.test.controller.UserController"
# # 扫描单个接口
# - "method:cn.torna.plugin.test.controller.UserController.postPage3"
# 调试模式,true:打印推送内容
debug: false
# 全局定义枚举code, desc字段名
enumCodeName: ""
enumDescName: ""
# 全局定义枚举i18n字段名
enumI18nName: ""

# 是否显示数组元素类型
# 如果为true:则数组类型显示 array<string>、array<int32> 等, 如果为false:则数组类型显示 array
showArrayElementType: true

# 示例数据
example:
  # 默认示例值,如果没有填写示列值(@mock),将会用以下默认值代替
  defaultExample:
    Integer|Long|Short|Byte: 1
    String: "str"
    Boolean: true
    Double|Float|BigDecimal: 1.1
    char: "a"
    LocalDate: "2020-01-01"
    LocalTime: "12:12:12"
    LocalDatetime|Date: "2020-01-01 12:12:12"
    "List<String>": "[\"aa\",\"bb\"]"
    "List<Integer>|List<Long>|List<Byte>|List<Short>": "[1,2]"
    "List<Boolean>": "[true,false]"
    "List<Double>|List<Float>|List<BigDecimal>": "[1.1,2.2]"
    "List<Character>": "[\"a\",\"b\"]"

# 分类排序
## 格式:按 分类名称 排好即可,不需要填值
## 分类名称需要和接口上的 @category 注解值一致
#category:
#  订单中心:
#    订单查询:
#    结算管理:
#  商品中心:
#    商品查询:
#    价格管理:
#  Dubbo接口:
#    商品接口:
#    订单接口:

# 第三方jar管理
thirdJar:
  # 下载第三方jar源码,格式:<groupId>:<artifactId>[:version],版本号可选,不填则使用最新版本
  dependencies:
  # - "com.example:demo"
  # 重写jar包类的字段描述和示列
  jarClass:
    # 类全名,多个用 | 分隔
    com.xxx.Page|com.xxx.IPage:
      # 指定字段描述和示例
      total:
        example: "100"
      size:
        description: 每页记录数
        example: "10"
      current:
        description: 当前页
        example: "1"
      # 隐藏字段
      optimizeJoinOfCountSql:
        hidden: true
      optimizeCountSql:
        hidden: true
      countId:
        hidden: true
      orders:
        hidden: true


# 推送dubbo
dubbo:
  # 是否启用
  enable: false
  # 定义依赖,格式:groupId:artifactId:version
  dependency: "com.example:demo:1.0.0"


# 国际化
i18n:
  ## resources下的国际化配置目录,下面放属性文件,多个目录用,隔开
  dir: "i18n"
  # 指定本地Locale( Locale.toString() ),不指定使用系统默认Locale
  # locale: "zh_CN"
  ## [选填]扩展翻译
  translate:
    # 对应本地Locale( Locale.toString() )
    zh_CN:
      hello: "你好"
      world: "世界"
    en_US:
      hello: "Hello"
      world: "World"

# 文档分类

在类注释中添加@category <分类名称>[/<子目录>],多级目录用/隔开,如:@category 订单中心/订单管理

不同Controller可以填相同配置,文档推送是会进行整合

# 定义分类排序

设置category属性,格式:按 分类名称 排好即可,不需要填值。分类名称需要和接口上的 @category 注解值一致

# 分类排序
category:
  订单中心:
    订单查询:
    结算管理:
  商品中心:
    商品查询:
    价格管理:
  Dubbo接口:
    商品接口:
    订单接口:

# 最佳实践

在团队开发过程中,大部分配置都是一样的,只有个别配置不同,比如扫描接口,因为每个人负责的模块不一样,扫描的接口也就不一样。

在这种情况下,可以定义一个公共的配置,然后每个人定义自己的配置,继承公共的配置即可。

假设公共配置文件是torna.yml,内容如下:

# Torna 推送地址
url: http://localhost:7700/api
# Torna 推送 token
token: "xxxxx"
# 扫描方式交给子配置
# scans: 

# 调试模式,true:打印推送内容
debug: false
# 全局定义枚举code, desc字段名
enumCodeName: "code"
enumDescName: "desc"

# 第三方jar管理
thirdJar:
  # 定义依赖,格式:<groupId>:<artifactId>[:version],版本号可选,不填则使用最新版本
  dependencies:
    - "com.baomidou:mybatis-plus-core"
    - "com.baomidou:mybatis-plus-extension"

然后建立子配置文件,可以用名字做后缀,如:torna-xx.yml

# 继承父级配置,当前配置文件相对路径
parent: "torna.yml"

# 推送人
author: "jim"

scans: 
  - "package:cn.torna.plugin.test.controller"
debug: true

执行推送

public class PushDoc {
    public static void main(String[] args) {
         TornaPlugin.pushDoc("torna-xx.yml");
    }
}