一、简介(摘要)
smart-doc是一款同时支持JAVA REST API和Apache Dubbo RPC接口文档生成的工具,smart-doc在业内率先提出基于JAVA泛型定义推导的理念, 完全基于接口源码来分析生成接口文档,不采用任何注解侵入到业务代码中。你只需要按照java-doc标准编写注释, smart-doc就能帮你生成一个简易明了的Markdown、HTML5、Postman Collection2.0+、OpenAPI 3.0+的文档。
二、特点(摘要)
- 零注解、零学习成本、只需要写标准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标记下载方法)测试。
三、smart-doc+Torna文档自动化
官方链接 Wiki - Gitee.com
需要从smart-doc 2.0.9才支持推送文档到torna,当然推荐使用smart-doc同学关注的新版本的发布。推荐smart-doc和torna都使用最新的版本。
如何把自动追踪到torna
首先是在javaspring的项目中集成smart-doc。smart-doc是看smart-doc官方的其他。其实是smart-doc让思路变得简单易懂。因此是一直使用文档的smart-doc的集成到smart-doc的使用。 doc也很简单,只需要在smart-json文件中添加几行写入到doc.torna的
{
"serverUrl": "http://127.0.0.1", //服务器地址,非必须。导出postman建议设置成http://{{server}}方便直接在postman直接设置环境变量
"isStrict": false, //是否开启严格模式
"outPath": "", //指定文档的输出路径,maven插件不需要,gradle插件必须
"packageFilters": "",//controller包过滤,多个包用英文逗号隔开
"projectName": "smart-doc",//配置自己的项目名称
"appToken": "c16931fa6590483fb7a4e85340fcbfef", //torna平台appToken,@since 2.0.9
"appKey": "20201216788835306945118208",//torna平台对接appKey,torna 1.11.0版本后不再需要, @since 2.0.9,
"secret": "W.ZyGMOB9Q0UqujVxnfi@.I#V&tUUYZR",//torna平台secret,torna 1.11.0版本后不再需要,@since 2.0.9
"openUrl": "http://localhost:7700/api",//torna平台地址,填写自己的私有化部署地址@since 2.0.9
"debugEnvName":"测试环境", //torna测试环境
"replace": true,//推送torna时替换旧的文档
"debugEnvUrl":"http://127.0.0.1",//torna
}
注意: appKey
, appToken
,secret
如果你不是管理员需要去问管理员了解你周围项目的具体相关信息。
Torna从11.11.0版本开始,开始使用smart-doc版本因此升级文档的密钥数据已经不再需要配置app和secret,只需要配置appToken即可,建议升级Torna。
如果你是管理员可以在torna的空间管理中查看。
查看空间里相关项目的token
遥控器操作
集成smart-doc并直接编写并编写脚本的maven或者可以使用smart-doc直接到文档插件的maven,或者直接将文档写入到gradle中了。
如果你想用智能文档备忘录或者gradle,请查看智能文档正式声明和gradle。
四、Spring Boot 集成 smart-doc
1.添加插件,配置pom.xml文件
<!--api文档 begin-->
<plugin>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>2.3.5</version>
<configuration>
<!--指定生成文档的使用的配置文件-->
<configFile>${basedir}/src/main/resources/smart-doc.json</configFile>
<!--smart-doc实现自动分析依赖树加载第三方依赖的源码,如果一些框架依赖库加载不到导致报错,这时请使用excludes排除掉-->
<excludes>
<!--也可以支持正则式如:com.alibaba:.* -->
<exclude>commons-jxpath:.*</exclude>
<exclude>io.zipkin.brave:.*</exclude>
<exclude>org.apache.kafka:.*</exclude>
<exclude>org.springframework.kafka:.*</exclude>
<exclude>com.netflix.servo:.*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<!--如果不需要在执行编译时启动smart-doc,则将phase注释掉-->
<!-- <phase>compile</phase>-->
<goals>
<goal>html</goal>
</goals>
</execution>
</executions>
</plugin>
<!--api文档 end-->
描述:
<plugin>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc-maven-plugin</artifactId>
<version>[最新版本]</version>
<configuration>
<!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
<configFile>./src/main/resources/smart-doc.json</configFile>
<!--指定项目名称-->
<projectName>测试</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>
2.在.../resources/路径上,添加 smart-doc.json 文件
{
"serverUrl": "http://127.0.0.1",//指定后端服务访问地址
"outPath": "src/main/resources/static/doc/api",//指定文档的输出路径,生成到项目静态文件目录下,随项目启动可以查看
"isStrict": false,//是否开启严格模式
"allInOne": true,//是否将文档合并到一个文件中
"createDebugPage": false,//是否创建可以测试的html页面
"packageFilters": "com.xxxx.aio.controller.WorkbenchController", //controller包过滤
"style": "xt256",//基于highlight.js的代码高设置
"projectName": "aio",//配置自己的项目名称
"showAuthor": false,//是否显示接口作者名称
"allInOneDocFileName": "index.html"//自定义设置输出文档名称
}
3.官方配置说明如下:
{
"serverUrl": "http://127.0.0.1", //服务器地址,非必须。导出postman建议设置成http://{{server}}方便直接在postman直接设置环境变量
"pathPrefix": "", //设置path前缀,非必须。如配置Servlet ContextPath 。@since 2.2.3
"isStrict": false, //是否开启严格模式
"allInOne": true, //是否将文档合并到一个文件中,一般推荐为true
"outPath": "D://md2", //指定文档的输出路径
"coverOld": true, //是否覆盖旧的文件,主要用于mardown文件覆盖
"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": "smart-doc",//配置自己的项目名称,不设置则插件自动获取pom中的projectName
"framework": "spring",//smart-doc默认支持spring和dubbo框架的文档,使用默认框架不用配置,当前支持spring、dubbo、JAX-RS(待完善)
"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
"urlSuffix":".do",//支持SpringMVC旧项目的url后缀,@since 2.1.0
"displayActualType":false,//配置true会在注释栏自动显示泛型的真实类型短类名,@since 1.9.6
"appKey": "20201216788835306945118208",// torna平台对接appKey,, @since 2.0.9
"appToken": "c16931fa6590483fb7a4e85340fcbfef", //torna平台appToken,@since 2.0.9
"secret": "W.ZyGMOB9Q0UqujVxnfi@.I#V&tUUYZR",//torna平台secret,@since 2.0.9
"openUrl": "http://localhost:7700/api",//torna平台地址,填写自己的私有化部署地址@since 2.0.9
"debugEnvName":"测试环境", //torna环境名称
"debugEnvUrl":"http://127.0.0.1",//推送torna配置接口服务地址
"tornaDebug":false,//启用会推送日志
"ignoreRequestParams":[ //忽略请求参数对象,把不想生成文档的参数对象屏蔽掉,@since 1.9.2
"org.springframework.ui.ModelMap"
],
"dataDictionaries": [{ //配置数据字典,没有需求可以不设置
"title": "http状态码字典", //数据字典的名称
"enumClassName": "com.power.common.enums.HttpCodeEnum", //数据字典枚举类名称
"codeField": "code",//数据字典字典码对应的字段名称
"descField": "message"//数据字典对象的描述信息字典
}],
"errorCodeDictionaries": [{ //错误码列表,没有需求可以不设置
"title": "title",
"enumClassName": "com.power.common.enums.HttpCodeEnum", //错误码枚举类
"codeField": "code",//错误码的code码字段名称
"descField": "message"//错误码的描述信息对应的字段名
}],
"revisionLogs": [{ //文档变更记录,非必须
"version": "1.0", //文档版本号
"revisionTime": "2020-12-31 10:30", //文档修订时间
"status": "update", //变更操作状态,一般为:创建、更新等
"author": "author", //文档变更作者
"remarks": "desc" //变更描述
}
],
"customResponseFields": [{ //自定义添加字段和注释,一般用户处理第三方jar包库,非必须
"name": "code",//覆盖响应码字段
"desc": "响应代码",//覆盖响应码的字段注释
"ownerClassName": "org.springframework.data.domain.Pageable", //指定你要添加注释的类名
"ignore":true, //设置true会被自动忽略掉不会出现在文档中
"value": "00000"//设置响应码的值
}],
"customRequestFields": [{ //自定义请求体的注释,@since 2.1.3,非必须
"name":"code", //属性名
"desc":"状态码", //描述
"ownerClassName":"com.xxx.constant.entity.Result", //属性对应的类全路径
"value":"200", //默认值或者mock值
"required":true, //是否必填
"ignore":false //是否忽略
}],
"requestHeaders": [{ //设置请求头,没有需求可以不设置
"name": "token",//请求头名称
"type": "string",//请求头类型
"desc": "desc",//请求头描述信息
"value":"token请求头的值",//不设置默认null
"required": false,//是否必须
"since": "-",//什么版本添加的改请求头
"pathPatterns": "/app/test/**",//请看https://smart-doc-group.github.io/#/zh-cn/diy/advancedFeatures?id=公共请求头
"excludePathPatterns":"/app/page/**"//请看https://smart-doc-group.github.io/#/zh-cn/diy/advancedFeatures?id=公共请求头
},{
"name": "appkey",//请求头
"type": "string",//请求头类型
"desc": "desc",//请求头描述信息
"value":"appkey请求头的值",//不设置默认null
"required": false,//是否必须
"pathPatterns": "/test/add,/testConstants/1.0",//正则表达式过滤请求头,url匹配上才会添加该请求头,多个正则用分号隔开
"since": "-"//什么版本添加的改请求头
}],
"requestParams": [ //公共请求参数(通过拦截器处理的场景),@since 2.2.3,没有需求请不要设置
{
"name": "configPathParam",//请求参数名称
"type": "string",//请求参数类型
"desc": "desc",//请求参数描述信息
"paramIn": "path",
"value":"testPath",//不设置默认null
"required": false,//是否必须
"since": "-",//什么版本添加的改请求参数
"pathPatterns": "*",//正则表达式过滤请求参数
"excludePathPatterns":"/app/page/**" //参考请求头中的用法
},
{
"name": "configQueryParam",//请求参数名称
"type": "string",//请求参数类型
"desc": "desc",//请求参数描述信息
"paramIn": "query",
"value":"testQuery",//不设置默认null
"required": false,//是否必须
"since": "-",//什么版本添加的改请求参数
"pathPatterns": "*",//正则表达式过滤请求参数
"excludePathPatterns":"/app/page/**"
}
],
"rpcApiDependencies":[{ // 项目开放的dubbo api接口模块依赖,配置后输出到文档方便使用者集成
"artifactId":"SpringBoot2-Dubbo-Api",
"groupId":"com.demo",
"version":"1.0.0"
}],
"rpcConsumerConfig": "src/main/resources/consumer-example.conf",//文档中添加dubbo consumer集成配置,用于方便集成方可以快速集成
"apiObjectReplacements": [{ // 自smart-doc 1.8.5开始你可以使用自定义类覆盖其他类做文档渲染,非必须
"className": "org.springframework.data.domain.Pageable",
"replacementClassName": "com.power.doc.model.PageRequestDto" //自定义的PageRequestDto替换Pageable做文档渲染
}],
"apiConstants": [{//从1.8.9开始配置自己的常量类,smart-doc在解析到常量时自动替换为具体的值,非必须
"constantsClassName": "com.power.doc.constants.RequestParamConstant"
}],
"responseBodyAdvice":{ //自smart-doc 1.9.8起,非必须项,ResponseBodyAdvice统一返回设置(不要随便配置根据项目的技术来配置),可用ignoreResponseBodyAdvice tag来忽略
"className":"com.power.common.model.CommonResult" //通用响应体
},
"requestBodyAdvice":{ 自smart-doc 2.1.4 起,支持设置RequestBodyAdvice统一请求包装类,非必须
"className":"com.power.common.model.CommonResult"
},
"groups": [ // @since 2.2.5, 对不同的controller进行分组
{
"name": "测试分组",
"apis": "com.power.doc.controller.app.*"
}
],
"requestParamsTable": true, // 是否将请求参数表展示在文档中,默认true,@since 2.2.5
"responseParamsTable": true //是否将响应参数表展示在文档中, 默认true,@since 2.2.5
}
4.根据需求生成文档(一般都是生成html)
五、实践
smart-doc是一款根据接口的泛型定义来在编译器期加载分析项源代码的返回类型和请求参数类型来实现的工具。如果你在代码的接口定义中返回如下几种类型我们都将无法做处理。
不规范的返回定义
1.1 接口中使用Map
因为无法分析代码中map的key值,所以smart-doc无法生成好的文档。
@GetMapping(value = "/object")
public Map<String, User> testMapUser() {
return null;
}
这种生成文档中key没法明确。
1.2 返回JSONObject
/**
* 返回用户信息
* @return
*/
@GetMapping(value = "/user")
public JSONObject object() {
return null;
}
团队中有这样定义返回数据一定要批评,鬼知道返回的是啥。程序员都看不懂,更别说smart-doc了。
1.3 返回ModelMap
/**
* 返回用户信息
* @return
*/
@GetMapping(value = "/user")
public ModelMap object() {
return null;
}
这个和map是一个道理,并且smart-doc直接天生屏蔽ModelMap
。
1.4 不规范说明
上面只列举了一些常见的,可能还有很多,如果项目中使用了类似例子,也不愿意调整代码那就回归swagger老老实实写注解。
正确的示范
2.1 设计通用返回
大多数成熟团队的统一返回类似如下(因文档篇幅,省略很多注释,使用smart-doc在真实代码中请规范些注释),当然可以根据自己项目来定制。
public abstract class BaseResult<T> implements Serializable {
private boolean success = false;
private String message;
private T data;
private String code;
private String timestamp;
}
编写一个静态的返回工具类
public class CommonResult<T> extends BaseResult implements Serializable {
private static final long serialVersionUID = -7268040542410707954L;
public CommonResult() {
}
public CommonResult(boolean success, String message) {
this.setSuccess(success);
this.setMessage(message);
}
public CommonResult(boolean success) {
this.setSuccess(success);
}
public CommonResult(String code, String message) {
this.setCode(code);
this.setMessage(message);
}
public CommonResult(boolean success, String message, T data) {
this.setSuccess(success);
this.setMessage(message);
this.setData(data);
}
public static CommonResult ok() {
return ok(BaseErrorCode.Common.SUCCESS);
}
public static <T> CommonResult<T> ok(IMessage msg) {
return baseCreate(msg.getCode(), msg.getMessage(), true);
}
public static CommonResult fail() {
return fail(BaseErrorCode.Common.UNKNOWN_ERROR);
}
public static CommonResult fail(IMessage message) {
return fail(message.getCode(), message.getMessage());
}
public static CommonResult fail(String code, String msg) {
return baseCreate(code, msg, false);
}
private static <T> CommonResult<T> baseCreate(String code, String msg, boolean success) {
CommonResult result = new CommonResult();
result.setCode(code);
result.setSuccess(success);
result.setMessage(msg);
result.setTimestamp(DateTimeUtil.nowStrTime());
return result;
}
public CommonResult<T> setResult(T data) {
this.setData(data);
return this;
}
public T getData() {
return (T) super.getData();
}
}
2.2 接口例子
正确示范:
/**
* 工作台
* @className WorkbenchController
* @author zhangs
* @email 853632587@qq.com
* @date 2022/1/13 10:27
* @version 1.0
*/
@Controller
@RequestMapping(value = "/workbench")
public class WorkbenchController {
/**
* 添加用户信息
*
* @param user
* @param type 类型
* @return
*/
@PostMapping("/add")
public CommonResult<User> addUser(@RequestBody User user,String type) {
return CommonResult.ok().setResult(user);
}
}
这种定义统一返回结构和明确的返回对象定义,smart-doc能够推导根据接口定义帮你推导出类的字段定义,包括嵌套的对象定义。
错误示范:
@PostMapping("/add")
public CommonResult addUser(@RequestBody User user){
return CommonResult.ok().setResult(user);
}
上面这种情况smart-doc无法知道你定义的返回类型
泛型命名规范
smart-doc的一些用户在使用过程中,在定义一些实体中涉及到泛型命名是使用多字母组合要做为泛型名,smart-doc是不支持这样的命名解析的。 包括在jdk的源代码中也没有这样定义过,这一是smart-doc不想支持奇奇怪怪的泛型命名方式的原因,约定规范一直是smart-doc的理念。
虽然没有强制的命名规范,但是为了便于代码阅读,也形成了一些约定俗成的命名规范,如下:
- T: Type(Java 类)通用泛型类型,通常作为第一个泛型类型
- S: 通用泛型类型,如果需要使用多个泛型类型,可以将S作为第二个泛型类型
- U: 通用泛型类型,如果需要使用多个泛型类型,可以将U作为第三个泛型类型
- V: 通用泛型类型,如果需要使用多个泛型类型,可以将V作为第四个泛型类型
- E: 集合元素泛型类型,主要用于定义集合泛型类型
- K: 映射-键泛型类型,主要用于定义映射泛型类型
- V: 映射-值泛型类型,主要用于定义映射泛型类型
- N: Number数值泛型类型,主要用于定义数值类型的泛型类型
- ?: 表示不确定的java类型
六、访问地址
http://localhost:8080/doc/api/index.html
七、类注释
/**
* @className $className$
* @author zhangs
* @email 853632587@qq.com
* @date $date$ $time$
* @version 1.0
*/
八、注意事项
1.不要用关键字命名接口,例如:order、permits等
2.接口参数变成时,及时同步注解 ,例如新增了 appSource
/**
* 用户权限
* @param userInfoParams
* @param appSource 端来源
* @return
*/
@WebAuth
@GetMapping("/permits")
public Response<PermitsDto> userPermits(@WebUserInfo WebUserInfoParams userInfoParams,Byte appSource)
{
...
}
3.设置maven环境变量
变量名:MAVEN_OPTS
变量值:-Dmaven.multiModuleProjectDirectory -Xms256m -Xmx1024m -Dfile.encoding=UTF-8
内存溢出配置:
VM Options: -Dmaven.multiModuleProjectDirectory -Xms256m -Xmx1024m -Dfile.encoding=UTF-8
ideal 配置如下: