关于spring:SpringBoot接口-如何生成接口文档之非侵入方式通过注释生成SmartDoc

7次阅读

共计 12647 个字符,预计需要花费 32 分钟才能阅读完成。

通过 Swagger 系列能够疾速生成 API 文档,然而这种 API 文档生成是须要在接口上增加注解等,这表明这是一种侵入式形式;那么有没有非侵入式形式呢, 比方通过正文生成文档?本文次要介绍非侵入式的形式及集成 Smart-doc 案例。咱们构建常识体系时应用 Smart-doc 这类工具并不是指标,而是 要理解非侵入形式能做到什么水平和技术思路。@pdai

  • SpringBoot 接口 – 如何生成接口文档之非侵入形式(通过正文生成)Smart-Doc?

    • 筹备知识点

      • 为什么会产生 Smart-Doc 这类工具?
      • 什么是 Smart-Doc?有哪些个性?
    • 实现案例

      • 配置
      • 运行测试
      • 生成更多类型的文档
    • 进一步了解

      • 正文信息是无限的,smart-doc 如何从正文拓展文档内容呢?
      • Maven 多模块中应用插件有没有比拟好的实际?
      • 如果生成文档时遇到问题,该如何调试?
    • 示例源码
    • 更多内容

筹备知识点

须要理解 Swagger 侵入性和依赖性,以及 Smart-Doc 这类工具如何解决这些问题, 局部内容来自官方网站。@pdai

为什么会产生 Smart-Doc 这类工具?

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

咱们来看下目前支流的技术文档工具存在什么问题:

  1. 侵入性强,须要编写大量注解,代表工具如:swagger,还有一些公司自研的文档工具
  2. 强依赖性,如果我的项目不想应用该工具,业务代码无奈编译通过。
  3. 代码解析能力弱,应用文档不齐全,次要代表为国内泛滥开源的相干工具。
  4. 泛滥基于正文剖析的工具无奈解析 jar 包外面的正文(sources jar 包),须要人工配置源码门路,无奈满足 DevOps 构建场景。
  5. 局部工具无奈反对多模块简单我的项目代码剖析。

什么是 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+ 的文档。

  • 零注解、零学习老本、只须要写规范 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 1.7.9 开始官网提供了 Maven 插件,能够通过在我的项目中集成 smart-doc 的 Maven 插件,而后运行插件间接生成文档。咱们的案例基于 smart-doc-maven-plugin,生成文档。示例参考官网配置文档而写。

配置

增加 maven 的插件

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

其中./src/main/resources/smart-doc.json 是配置文件。

{"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,  // 是否笼罩旧的文件,次要用于 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": "pdai-springboot-demo-smart-doc",// 配置本人的项目名称,不设置则插件主动获取 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": "tech.pdai.springboot.smartdoc.constant.ResponseStatus", // 数据字典枚举类名称
    "codeField": "responseCode",// 数据字典字典码对应的字段名称
    "descField": "description"// 数据字典对象的形容信息字典
  }],
  "errorCodeDictionaries": [{ // 错误码列表,没有需要能够不设置
    "title": "title",
    "enumClassName": "tech.pdai.springboot.smartdoc.constant.ResponseStatus", // 错误码枚举类
    "codeField": "responseCode",// 错误码的 code 码字段名称
    "descField": "description"// 错误码的形容信息对应的字段名
  }],
  "revisionLogs": [{ // 文档变更记录,非必须
    "version": "1.1", // 文档版本号
    "revisionTime": "2022-07-01 22:12:01", // 文档订正工夫
    "status": "update", // 变更操作状态,个别为:创立、更新等
    "author": "pdai", // 文档变更作者
    "remarks": "init user api" // 变更形容
  },{ // 文档变更记录,非必须
    "version": "1.2", // 文档版本号
    "revisionTime": "2022-07-01 22:12:02", // 文档订正工夫
    "status": "update", // 变更操作状态,个别为:创立、更新等
    "author": "pdai", // 文档变更作者
    "remarks": "add address api" // 变更形容
  }
  ],
  "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":"tech.pdai.springboot.smartdoc.entity.ResponseResult" // 通用响应体
  }
}

运行测试

能够通过 Maven 命令生成文档

// 生成 html
mvn -Dfile.encoding=UTF-8 smart-doc:html

在 IDEA 中,也能够通过 maven 插件构建

maven 构建日志如下

[INFO] Scanning for projects...
[INFO] 
[INFO] --------------< tech.pdai:115-springboot-demo-smart-doc >---------------
[INFO] Building 115-springboot-demo-smart-doc 1.0-SNAPSHOT
[INFO] --------------------------------[jar]---------------------------------
[INFO] 
[INFO] >>> smart-doc-maven-plugin:2.4.8:html (default-cli) > compile @ 115-springboot-demo-smart-doc >>>
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ 115-springboot-demo-smart-doc ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 0 resource
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ 115-springboot-demo-smart-doc ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] <<< smart-doc-maven-plugin:2.4.8:html (default-cli) < compile @ 115-springboot-demo-smart-doc <<<
[INFO] 
[INFO] 
[INFO] --- smart-doc-maven-plugin:2.4.8:html (default-cli) @ 115-springboot-demo-smart-doc ---
[INFO] ------------------------------------------------------------------------
[INFO] Smart-doc Start preparing sources at: 2022-07-01 22:43:54
[INFO] Artifacts that the current project depends on: ["org.springframework.boot:spring-boot-starter-web","org.springframework.boot:spring-boot-configuration-processor","org.projectlombok:lombok"]
[INFO] Smart-doc has loaded the source code path: [{"path":"D:/git/tech-pdai-spring-demos/115-springboot-demo-smart-doc/src/main/java"}]
[INFO] Smart-doc Starting Create API Documentation at: 2022-07-01 22:43:54
[INFO] API documentation is output to => D://md2
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.196 s
[INFO] Finished at: 2022-07-01T22:43:55+08:00
[INFO] ------------------------------------------------------------------------

构建后的 html 如下:

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

展现成果,能够参看 https://api.doubans.com/

生成更多类型的文档

smart-doc 还反对生成如下类型的文档:

// 生成 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

进一步了解

联合 smart-doc 官网文档,咱们通过几个问题进一步了解 smart-doc。次要内容来源于官网文档。

正文信息是无限的,smart-doc 如何从正文拓展文档内容呢?

咱们晓得正文的信息是无限的,swagger 技术栈的形式通过定义注解来束缚并拓展文档中的内容,那么 smart-doc 如何从正文拓展文档内容呢?

一方面 smart-doc 的实现初衷是通过应用 javadoc 文档正文来去除注解式的侵入,因而 smart-doc 每减少一个性能首先都是去思考 javadoc 原生的tag,

上面对 smart-doc 应用的一些 javadoc 的正文 tag 做介绍。

tag 名称 应用形容
@param 对于在 Spring Boot 接口层,对于简略类型的参数必须在应用 @param 时写上正文形容,对于 Entity 类型 smart-doc 则不会查看
@deprecated 能够在正文中用于标记接口曾经废除,作用同 @Deprecated 注解
@apiNote @apiNoteJAVA 新增的文档 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用于在 DubboAPI接口类上增加让 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,多个参数名用空格隔开
@response smart-doc 2.2.0 开始,@response tag标注在 Controller 办法上能够容许用这本人定义返回的 json example。倡议只在返回根底类型时应用,如:Result<String> 类型这种泛型是简略原生类型的响应。
@tag @since 2.2.5, @tag用于将 Controller 办法分类, 能够将不同 Contoller 下的办法指定到多个分类下, 同时也能够间接指定 Controller 为一个分类或多个分类

Maven 多模块中应用插件有没有比拟好的实际?

在独立的 Maven 我的项目中应用 smart-doc,以后能够说是如丝般爽滑。然而在 Maven 的多模块我的项目中应用 smart-doc-maven-plugin 时,很多同学就有疑难了,smart-doc 插件我到底是放在什么中央适合?是放在 Maven 的根 pom.xml 中?还是说各个须要生成 API 接口文档的模块中呢?上面就来说说依据不同的我的项目构造应该怎么放插件。

齐全的父子级关系的 maven 我的项目:

├─parent
├──common
│   pom.xml
├──web1
│   pom.xml
├──web2
│   pom.xml
└─pom.xml

下面的 maven 构造假如是严格依照父子级来配置的,而后 web1 和 web2 都依赖于 common,这种状况下如果跑到 web1 下或者 web2 目录下间接执行 mvn 命令来编译 都是无奈实现的。须要在根目录下来执行命令编译命令能力通过,而 smart-doc 插件会通过类加载器去加载用户配置的一些类,因而是须要调用编译的和执行命令 是一样的。这种状况下倡议你建 smart-doc-maven-plugin 放到根 pom.xml 中,在 web1 和 web2 中搁置各自的 smart-doc.json 配置。而后通过 -pl 去指定让 smart-doc 生成指定 模块的文档。操作命令如下:

# 生成 web1 模块的 api 文档
mvn smart-doc:markdown -Dfile.encoding=UTF-8  -pl :web1 -am
# 生成 web2 模块的 api 文档
mvn smart-doc:markdown -Dfile.encoding=UTF-8  -pl :web2 -am

如果不是依照严格父子级构建的我的项目,还是以下面的构造例子来说。common 模块放在类 parent 中,然而 common 的 pom.xml 并没有定义 parent。common 模块也很少变更,很多公司外部可能就间接把 common 独自 depoly 上传到了公司的 Nexus 仓库中,这种状况下 web1 和 web2 尽管依赖于 common,然而 web1 和 web2 都能够在 web1 和 web2 目录下用命令编译,这种状况下间接将 smart-doc-maven-plugin 独自放到 web1 和 web2 中是能够做构建生成文档的。

【多模块测试用例参考】

留神:怎么去应用插件并没有固定的模式,最重要的是纯熟 Maven 的一些列操作,而后依据本人的我的项目状况来调整。技巧娴熟就能应答自若。对于插件的应用,从 smart-doc-maven-plugin 1.2.0 开始,插件是可能主动剖析生成模块的依赖来加载必要的源码,并不会将所有模块的接口文档合并到一个文档中。

如果生成文档时遇到问题,该如何调试?

在应用 smart-doc-maven-plugin 插件来构建生成 API 文档的过程中可能会呈现一些谬误问题。官网文档中提供了调试的计划:

  1. 增加 smart-doc 依赖

因为 smart-doc-maven-plugin 最终是应用 smart-doc 来实现我的项目的源码剖析和文档生成的,
通常状况下真正的调试的代码是 smart-doc。但这个过程次要通过smart-doc-maven-plugin 来排查。

<dependency>
     <groupId>com.github.shalousun</groupId>
     <artifactId>smart-doc</artifactId>
     <version>[最新版本]</version>
     <scope>test</scope>
</dependency>

留神: 应用 smart-doc 的版本最好和插件依赖的 smart-doc 版本统一。

  1. 增加断点

增加断点如图所示

  1. Debug 模式运行构建指标

maven插件在 idea 中运行 debug 非常简单,操作如下图。

这样就能够间接进入断点了。

提醒: 下面是通过插件去作为入口调试 smart-doc 的源码,如果你想调试插件自身的源码执行过程,则将插件的依赖增加到我的项目依赖中, 如下:

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

而后通过下面的相似步骤调试 smart-doc-maven-plugin 的源码

示例源码

https://github.com/realpdai/t…

https://smart-doc-group.githu…

更多内容

辞别碎片化学习,无套路一站式体系化学习后端开发: Java 全栈常识体系(https://pdai.tech)

正文完
 0