Springboot 集成Smart-Doc生成接口文档

通过Swagger系列可以快速生成API文档,但是这种API文档生成是需要在接口上添加注解等,这是一种侵入式方式;

本文主要介绍非侵入式的方式及集成Smart-doc案例

1. 前言

既然有了Swagger, 为何还会产生Smart-Doc这类工具?本质上是Swagger侵入性和依赖性

目前主流的技术文档工具存在什么问题:

  1. 侵入性强:需要编写大量的注解,代表工具有:swagger

  2. 强依赖性:如果项目不使用该工具,业务代码无法编译通过

  3. 代码解析能力弱,使用文档不齐全,主要代表为国内众多开源的相关工具

  4. 众多基于注释分析的哦你工具无法解析jar包里面的注释(sources jar),需要人工配置源码路径,无法满足DevOps构建场景

  5. 部分工具无法支持多模块复杂项目的代码分析

2. Smart-Doc介绍

smart-doc是一款同时支持JAVA REST API和Apache Dubbo RPC接口文档生成的工具,smart-doc在业内率先提出基于JAVA泛型定义推导的理念, 完全基于接口源码来分析生成接口文档,不采用任何注解侵入到业务代码中。你只需要按照java-doc标准编写注释, smart-doc就能帮你生成一个简易明了的Markdown、HTML5、Postman Collection2.0+、OpenAPI 3.0+的文档。

2.1 特性

  • 零注解、零学习成本、只需要写标准JAVA注释。
  • 基于源代码接口定义自动推导,强大的返回结构推导。
  • 支持Spring MVC、Spring Boot、Spring Boot Web Flux(controller书写方式)、Feign。
  • 支持Callable、Future、CompletableFuture等异步接口返回的推导。
  • 支持JavaBean上的JSR303参数校验规范,包括分组验证。
  • 对JSON请求参数的接口能够自动生成模拟JSON参数。
  • 对一些常用字段定义能够生成有效的模拟值。
  • 支持生成JSON返回值示例。
  • 支持从项目外部加载源代码来生成字段注释(包括标准规范发布的jar包)。
  • 支持生成多种格式文档:Markdown、HTML5、Asciidoctor、Postman Collection、OpenAPI 3.0。 Up- 开放文档数据,
  • 可自由实现接入文档管理系统。
  • 支持导出错误码和定义在代码中的各种字典码到接口文档。
  • 支持Maven、Gradle插件式轻松集成。
  • 支持Apache Dubbo RPC接口文档生成。
  • debug接口调试html5页面完全支持文件上传,下载(@download tag标记下载方法)测试。

3. 实现案例

从smart-doc 1.7.9开始官方提供了Maven插件,可以通过在项目中集成smart-doc的Maven插件,然后运行插件直接生成文档。 我们的案例基于smart-doc-maven-plugin,生成文档。示例参考官方配置文档而写。

3.1 添加maven插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>2.4.8</version>
<configuration>
<!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
<configFile>./src/main/resources/smart-doc.json</configFile>
<!--指定项目名称,推荐使用动态参数,例如${project.description}-->
<!--如果smart-doc.json中和此处都未设置projectName,2.3.4开始,插件自动采用pom中的projectName作为设置-->
<!--<projectName>${project.description}</projectName>-->
<!--smart-doc实现自动分析依赖树加载第三方依赖的源码,如果一些框架依赖库加载不到导致报错,这时请使用excludes排除掉-->
<excludes>
<!--格式为:groupId:artifactId;参考如下-->
<!--也可以支持正则式如:com.alibaba:.* -->
<exclude>com.alibaba:fastjson</exclude>
</excludes>
<!--includes配置用于配置加载外部依赖源码,配置后插件会按照配置项加载外部源代码而不是自动加载所有,因此使用时需要注意-->
<!--smart-doc能自动分析依赖树加载所有依赖源码,原则上会影响文档构建效率,因此你可以使用includes来让插件加载你配置的组件-->
<includes>
<!--格式为:groupId:artifactId;参考如下-->
<!--也可以支持正则式如:com.alibaba:.* -->
<include>com.alibaba:fastjson</include>
</includes>
</configuration>
<executions>
<execution>
<!--如果不需要在执行编译时启动smart-doc,则将phase注释掉-->
<phase>compile</phase>
<goals>
<!--smart-doc提供了html、openapi、markdown等goal,可按需配置-->
<goal>html</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

3.2 添加smart-doc配置文件

在上面的configFile属性中的路径创建配置文件,输入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{
"serverUrl": "http://127.0.0.1", //服务器地址,非必须。导出postman建议设置成http://{{server}}方便直接在postman直接设置环境变量
"pathPrefix": "", //设置path前缀,非必须。如配置Servlet ContextPath 。@since 2.2.3
"isStrict": false, //是否开启严格模式
"allInOne": true, //是否将文档合并到一个文件中,一般推荐为true
"outPath": "/Users/xiaoyuge/Desktop/smartDoc", //指定文档的输出路径
"coverOld": true, //是否覆盖旧的文件,主要用于markdown文件覆盖
"createDebugPage": true,//@since 2.0.0 smart-doc支持创建可以测试的html页面,仅在AllInOne模式中起作用。
"packageFilters": "",//controller包过滤,多个包用英文逗号隔开,2.2.2开始需要采用正则:com.test.controller.*
"md5EncryptedHtmlName": false,//只有每个controller生成一个html文件时才使用
"style":"xt256", //基于highlight.js的代码高设置,可选值很多可查看码云wiki,喜欢配色统一简洁的同学可以不设置
"projectName": "chapter9",//配置自己的项目名称,不设置则插件自动获取pom中的projectName
"skipTransientField": true,//目前未实现
"sortByTitle":false,//接口标题排序,默认为false,@since 1.8.7版本开始
"showAuthor":true,//是否显示接口作者名称,默认是true,不想显示可关闭
"requestFieldToUnderline":true,//自动将驼峰入参字段在文档中转为下划线格式,//@since 1.8.7版本开始
"responseFieldToUnderline":true,//自动将驼峰入参字段在文档中转为下划线格式,//@since 1.8.7版本开始
"inlineEnum":true,//设置为true会将枚举详情展示到参数表中,默认关闭,//@since 1.8.8版本开始
"recursionLimit":7,//设置允许递归执行的次数用于避免一些对象解析卡主,默认是7,正常为3次以内,//@since 1.8.8版本开始
"allInOneDocFileName":"index.html",//自定义设置输出文档名称, @since 1.9.0
"requestExample":"true",//是否将请求示例展示在文档中,默认true,@since 1.9.0
"responseExample":"true",//是否将响应示例展示在文档中,默认为true,@since 1.9.0

"ignoreRequestParams":[ //忽略请求参数对象,把不想生成文档的参数对象屏蔽掉,@since 1.9.2
"org.springframework.ui.ModelMap"
],
"dataDictionaries": [{ //配置数据字典,没有需求可以不设置
"title": "http状态码字典", //数据字典的名称
"enumClassName": "org.chapter9.ResponseStatus", //数据字典枚举类名称
"codeField": "responseCode",//数据字典字典码对应的字段名称
"descField": "description"//数据字典对象的描述信息字典
}],
"errorCodeDictionaries": [{ //错误码列表,没有需求可以不设置
"title": "title",
"enumClassName": "org.chapter9.ResponseStatus", //错误码枚举类
"codeField": "responseCode",//错误码的code码字段名称
"descField": "description"//错误码的描述信息对应的字段名
}],
"revisionLogs": [{ //文档变更记录,非必须
"version": "1.0", //文档版本号
"revisionTime": "2026-05-11 22:12:01", //文档修订时间
"status": "update", //变更操作状态,一般为:创建、更新等
"author": "xiaoyuge", //文档变更作者
"remarks": "init user xiaoyuge" //变更描述
},{ //文档变更记录,非必须
"version": "1.1", //文档版本号
"revisionTime": "2023-05-15 12:12:02", //文档修订时间
"status": "update", //变更操作状态,一般为:创建、更新等
"author": "xiaoyuge", //文档变更作者
"remarks": "add address xiaoyuge" //变更描述
}
],
"customResponseFields": [{ //自定义添加字段和注释,一般用户处理第三方jar包库,非必须
"name": "code",//覆盖响应码字段
"desc": "响应代码",//覆盖响应码的字段注释
"ownerClassName": "org.springframework.data.domain.Pageable", //指定你要添加注释的类名
"ignore":true, //设置true会被自动忽略掉不会出现在文档中
"value": "00000"//设置响应码的值
}],
"requestHeaders": [{ //设置请求头,没有需求可以不设置
"name": "token",//请求头名称
"type": "string",//请求头类型
"desc": "desc",//请求头描述信息
"value":"token请求头的值",//不设置默认null
"required": false,//是否必须
"since": "-",//什么版本添加的改请求头
"pathPatterns": "/app/test/**",//请看https://gitee.com/smart-doc-team/smart-doc/wikis/请求头高级配置?sort_id=4178978
"excludePathPatterns":"/app/page/**"//请看https://gitee.com/smart-doc-team/smart-doc/wikis/请求头高级配置?sort_id=4178978
},{
"name": "appkey",//请求头
"type": "string",//请求头类型
"desc": "desc",//请求头描述信息
"value":"appkey请求头的值",//不设置默认null
"required": false,//是否必须
"pathPatterns": "/test/add,/testConstants/1.0",//正则表达式过滤请求头,url匹配上才会添加该请求头,多个正则用分号隔开
"since": "-"//什么版本添加的改请求头
}],
"requestParams": [ //设置公共参数,没有需求可以不设置
{
"name": "configPathParam",//请求名称
"type": "string",//请求类型
"desc": "desc",//请求描述信息
"paramIn": "path", // 参数所在位置 header-请求头, path-路径参数, query-参数
"value":"testPath",//不设置默认null
"required": false,//是否必须
"since": "2.2.3",//什么版本添加的该请求
"pathPatterns": "/app/test/**",//请看https://gitee.com/smart-doc-team/smart-doc/wikis/请求高级配置?sort_id=4178978
"excludePathPatterns":"/app/page/**"//请看https://gitee.com/smart-doc-team/smart-doc/wikis/请求高级配置?sort_id=4178978
}],
"responseBodyAdvice":{ //自smart-doc 1.9.8起,非必须项,ResponseBodyAdvice统一返回设置(不要随便配置根据项目的技术来配置),可用ignoreResponseBodyAdvice tag来忽略
"className":"org.chapter9.ResponseStatus" //通用响应体
}
}

3.3 运行测试

执行maven命令生成文档

1
mvn -Dfile.encoding=UTF-8 smart-doc:html

构建后的html如下:

也可以看到还自动提供了mock的数据,以及测试接口的按钮。还包含自定义的返回枚举类型等。

3.4 生成更多类型的文档

1
2
3
4
5
6
7
8
#生成markdown
mvn -Dfile.encoding=UTF-8 smart-doc:markdown
#生成adoc
mvn -Dfile.encoding=UTF-8 smart-doc:adoc
#生成postman json数据
mvn -Dfile.encoding=UTF-8 smart-doc:postman
#生成 Open Api 3.0+, Since smart-doc-maven-plugin 1.1.5
mvn -Dfile.encoding=UTF-8 smart-doc:openapi

4. 进一步理解

4.1 smart-doc 如何从注释拓展文档内容

smart-doc是通过使用javadoc文档注释来去除注解式的侵入,因此smart-doc每增加一个功能首先都是去考虑javadoc生的tag

下面对smart-doc使用的一些javadoc的注释tag做介绍:

tag名称 描述
@param 对于在Spring Boot接口层,对于简单类型的参数必须在使用@param时写上注释描述,对于Entity类型smart-doc则不会检查
@deprecated 可以在注释中用于标记接口已经废弃,作用同@Deprecated注解
@apiNote @apiNote是JAVA新增的文档tag,smart-doc使用@apiNote的注释作为方法的详细描述,因此可以使用@apiNote来写一段长注释。如果一个方法不写 @apiNote注释说明,smart-doc直接使用方法默认注释填充

另一方面,原生的tag是不够的,所以smart-doc又通过自定义tag来支持更多的功能拓展

tag名称 描述
@ignore @ignore tag用于过滤请求参数对象上的某个字段,设置后smart-doc不输出改字段到请求参数列表中。关于响应字段忽略的请看【忽略响应字段】,如果@ignore加到方法上,则接口方法不会输出到文档。从1.8.4开始@ignore支持添加到Controller上进行忽略不想生成文档的接口类。@ignore也可以用于方法上忽略某个请求参数。
@required 如果你没有使用JSR303参数验证规范实现的方式来标注字段,就可以使用@required去标注请求参数对象的字段,标注smart-doc在输出参数列表时会设置为true
@mock 从smart-doc 1.8.0开始,@mock tag用于在对象基本类型字段设置自定义文档展示值。设置值后smart-doc不再帮你生成随机值。方便可以通过smart-doc直接输出交付文档。
@dubbo 从smart-doc 1.8.7开始,@dubbo tag用于在Dubbo的API接口类上添加让smart-doc可以扫描到Dubbo RPC的接口生成文档。
@restApi 从smart-doc 1.8.8开始,@restApi tag用于支持smart-doc去扫描Spring Cloud Feign的定义接口生成文档。
@order 从smart-doc 1.9.4开始,@order tag用于设置Controller接口或者API入口的自定义排序序号,@order 1就表示设置序号为1。
@ignoreResponseBodyAdvice 从smart-doc 1.9.8开始,@ignoreResponseBodyAdvice tag用于忽略ResponseBodyAdvice设置的包装类。
@download 从smart-doc 2.0.1开始,@download tag用于标注在Controller的文件下载方法上,生成debug页面时可实现文件下载测试。并且支持下载文件带请求头参数测试
@page 从smart-doc 2.0.2开始,@page tag用于标注在Controller的方法上表示该方法用来渲染返回一个静态页面,生成debug页面时如果发起测试,测试页面会自动在浏览器开启新标签显示页面
@ignoreParams 从smart-doc 2.1.0开始,@ignoreParams tag用于标注在Controller方法上忽略掉不想显示在文档中的参数,例如:@ignoreParams id name,多个参数名用空格隔开
@tag @since 2.2.5, @tag用于将Controller方法分类, 可以将不同Contoller下的方法指定到多个分类下, 同时也可以直接指定Controller为一个分类或多个分类

4.2 smart-doc代码调试

在使用smart-doc-maven-plugin插件来构建生成API文档的过程中可能会出现一些错误问题,官方文档提供了调试方案

  1. 添加smart-doc 依赖

    因为smart-doc-maven-plugin最终时使用smart-doc来完成项目源码分析和文档生成的,通常情况下真正的调试代码是smart-doc

    1
    2
    3
    4
    5
    6
    <dependency>
    <groupId>com.github.shalousun</groupId>
    <artifactId>smart-doc</artifactId>
    <version>[最新版本]</version>
    <scope>test</scope>
    </dependency>

    注意:使用smart-doc的版本最好和插件依赖的smart-doc版本一致。

  1. 添加断点

  1. Debug模式运行构建目标

提示:上面是通过插件作为入口调试smart-doc的远啊,如果想调试插件本身的源码执行过程,则将插件的依赖添加到项目依赖中,如下:

1
2
3
4
5
<dependency>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>【maven仓库最新版本】</version>
</dependency>

然后通过上面的类似步骤调试smart-doc-maven-plugin的源码