一个 java restful api 文档生成工具,不用像Swagger一样写大量注解,完全基于接口源码分析来生成接口文档,但是需要按照 java的标准注释写。
完全基于接口源码来分析生成接口文档,不采用任何注解侵入到业务代码中。
你只需要按照java-doc
标准编写注释, smart-doc
就能帮你生成一个简易明了的Markdown
、HTML5
、Postman ollection2.0+
、OpenAPI 3.0+
的文档。
注意:需要完全按照java的标准注释,如果方法注释包含特殊符号或者换行的话,生成的json是会出现格式错误,但是不影响相关的html使用。
JAVA
注释。Spring MVC
、Spring Boot
、Spring Boot Web Flux
(Controller
书写方式)Feign
。Callable
、Future
、CompletableFuture
等异步接口返回的推导。JavaBean
上的JSR303
参数校验规范,包括分组验证。JSON
请求参数的接口能够自动生成模拟JSON
参数。JSON
返回值示例。Markdown
、HTML5
、Asciidoctor
、Postman Collection
、OpenAPI 3.0
。 开放文档数据,可自由实现接入文档管理系统。Maven
、Gradle
插件式轻松集成。Apache Dubbo RPC
接口文档生成。debug
接口调试html5
页面完全支持文件上传,下载(@download tag
标记下载方法)测试。smart-doc + Torna 组成的文档生成和管理解决方案,使用smart-doc
无侵入完成JAVA
源代码分析和提取注释生成API
文档,自动将文档推送到Torna
企业级接口文档管理平台。
简单总结了几个特别明显以及我认为最关键的几个优点如下:
缺点
我总结了一下我使用过程中的缺点,在此我仅代表我自己提出的缺点如下
ResultVO>
,解析成ResultVODefinePage(新版本已解决)功能特性 | smart-doc | swagger |
---|---|---|
代码侵入 | 无 | 注解侵入性严重 |
集成复杂度 | 简单,只需插件 | 偏复杂 |
插件支持 | 有 gradle 和 maven 插件 | 无插件 |
openapi 规范支持 | 支持 openapi 3.0 | 完全支持 openapi 的版本 |
CI 构建集成 | 可在 ci 构建阶段使用maven 或者 gradle 命令启动插件生成文档 | 不支持 |
集中化文档中心集成 | 已经和 torna 企业级接口文档管理平台对接 | 不支持 |
维护持续性 | 值得信赖,开源后用户基础多,一直持续维护 | 全球用户多,开源维护值得信赖 |
接口 debug | 2.0.0 版本开始已经支持 debug,页面比 swagger 漂亮太多了。 | 支持 |
Smart-doc 从 2.0.0 后几乎实现了 swagger ui 的功能,并且比 swagger ui 更简洁大方,也更符合国内开发者的诉求。当然 smart-doc 的功能也已经超过了 swagger 为 java 开发者提供的功能。当然 smart-doc 本身是只支持扫描代码生成 openapi 3.0 的文档的,也可以将生成的 openapi 3.0 文档导入到其他 ui 中渲染展示。
swagger 生成 离线的文档 需要借助第三方jar包实现,而 smart-doc 直接 运行 test 方法就可以直接导出 md,html,asciidoc 等格式文档。
设计思路不同,smart-doc 是基于 源码分析的,它生成api文档是通过分析JAVA源码主要是通过 注释 和 系统自带注解,来实现文档的 生成,而 swagger 是运行时 自动生成在线文档,并且 生成 测试 接口的 案例。由于他们设计思路 理念 不一样,swagger2 使用过程需要使用它定义的@API 相关注解,这样就污染了源码,代码入侵有点高,而smart -doc 就不一样了,主要是通过 注释 、解析/** */ 来生成API文档的 。这样基本上没有入侵性,很自由!
swagger
使用maven或者gradle插件进行一键生成对应的文档格式或者命令进行生成,在这里我只展示了maven插件的使用姿势。
<plugin>
<groupId>com.github.shalousungroupId>
<artifactId>smart-doc-maven-pluginartifactId>
<version>2.4.9version>
<configuration>
<configFile>./src/main/resources/smart-doc.jsonconfigFile>
<projectName>测试projectName>
<excludes>
<exclude>com.alibaba:fastjsonexclude>
excludes>
<includes>
<include>com.alibaba:fastjsoninclude>
<include>com.baomidou:mybatis-plus-extensioninclude>
<include>org.springframework.data:spring-data-commonsinclude>
includes>
configuration>
<executions>
<execution>
<phase>compilephase>
<goals>
<goal>htmlgoal>
goals>
execution>
executions>
plugin>
如果配置
这些,可以在以上指令被触发时执行smart-doc文档生成
使用maven插件命令如下:
//生成html
mvn -Dfile.encoding=UTF-8 smart-doc:html
//生成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
// 生成文档推送到Torna平台
mvn -Dfile.encoding=UTF-8 smart-doc:torna-rest
// Apache Dubbo RPC文档
// Generate html
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-html
// Generate markdown
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-markdown
// Generate adoc
mvn -Dfile.encoding=UTF-8 smart-doc:rpc-adoc
// 生成dubbo接口文档推送到torna
mvn -Dfile.encoding=UTF-8 smart-doc:torna-rpc
使用IDE一键生成如下:
优点:便捷,快速上手
缺点:每个服务各自指定smart-doc的配置文件smart-doc.json
导入相关smart-doc依赖
<dependency>
<groupId>com.github.shalousungroupId>
<artifactId>smart-docartifactId>
<version>2.5.1version>
dependency>
手动为每个项目引入以上jar包,可以使用smart-doc.json配置文件也可以使用smart-doc自带的ApiConfig
配置类进行手动配置。
使用单元测试测试API文档生成如下:
@Test
public void testBuilderControllersApi() {
ApiConfig config = new ApiConfig();
config.setServerUrl("http://localhost:8080");
//当把AllInOne设置为true时,Smart-doc将会把所有接口生成到一个Markdown、HHTML或者AsciiDoc中
config.setAllInOne(true);
//HTML5文档,建议直接放到src/main/resources/static/doc下,Smart-doc提供一个配置常量HTML_DOC_OUT_PATH
//源码---String HTML_DOC_OUT_PATH = "src/main/resources/static/doc";
config.setOutPath("src/main/resources/static/doc");
// 设置接口包扫描路径过滤,如果不配置则Smart-doc默认扫描所有的接口类
// 配置多个报名有英文逗号隔开
config.setPackageFilters("com.***.Controller.*");
//设置错误错列表,遍历自己的错误码设置给Smart-doc即可
List<ApiErrorCode> errorCodeList = new ArrayList<>();
for (HttpCodeEnum codeEnum : HttpCodeEnum.values()) {
ApiErrorCode errorCode = new ApiErrorCode();
errorCode.setValue(codeEnum.getCode()).setDesc(codeEnum.getMessage());
errorCodeList.add(errorCode);
}
//不需要显示错误码,则可以不用设置错误码。
config.setErrorCodes(errorCodeList);
//生成Markdown文件
HtmlApiDocBuilder.buildApiDoc(config);
}
Q:为什么说公司内部建议使用呢?
答:每个公司都会有自己的maven仓库(几乎),可以搞一些定制化的工具包,比如:日志、认证、链路、授权等。可以在工具包中加入smart-doc包进行简单开发。
可以这么做:
将smart-doc集成到工具包中,在工具包进行打包,提供给使用方,然后定制开发进行配置化管理
每个Java业务服务引入公共jar包,然后进行配置,自定义配置如下:
# 是否开启html生成,默认为false
smart-doc.html-enable=true
# html生成路径,默认为当前服务子目录doc下
smart-doc.out-path=/doc/
# 接口返回对象配置
smart-doc.response-class-name=com.sparkxmedia.xplatform.sd.api.common.result.ResultVO
# 自定义请求头
smart-doc.request-header.username=zane
smart-doc.request-header.user_id=1
smart-doc.request-header.authorization=test
# controller层包
smart-doc.package-filters=com.sparkxmedia.xplatform.sd.api.ai.controller.*,com.sparkxmedia.xplatform.sd.api.controller.*
# 如果使用swagger-ui替代smart-doc的html,则需配置获取openapi.json路径
springdoc.swagger-ui.url=/sd-api/doc/openapi.json
其核心代码如下:
package com.cuizb.tools.starter.config.doc;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author: Java技术债务
* @Date: 2021/6/6 20:03
* Describe: 跨域解决,映射生成的静态资源
*/
@Slf4j
@Configuration
@EnableConfigurationProperties({ApiDocProperties.class})
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private ApiDocProperties apiDocProperties;
/**
* 解决跨域问题
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOriginPatterns("/**")
.maxAge(3600);
}
@SneakyThrows
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 当前项目根路径
String rootPath = ResourceUtils.getURL("").getPath();
// 文档保存绝对路径
rootPath = rootPath.substring(0, rootPath.length() - 1) + apiDocProperties.getOutPath();
// 映射到当前项目根路径+用户自定义路径(当前仅支持当前项目下路径)
String resourcesPath;
if ("dev".equals(apiDocProperties.getProfileActive()) || "local".equals(apiDocProperties.getProfileActive())) {
resourcesPath = "file:///" + rootPath;
} else {
resourcesPath = "file:///" + apiDocProperties.getOutPath();
}
log.info(">>>>>>>>>>>>>" + resourcesPath);
//配置静态资源映射
registry
.addResourceHandler("/doc/static/**")
.addResourceLocations(resourcesPath);
}
}
package com.cuizb.tools.starter.config.doc;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author Java技术债务
* @date 2022-08-17 15:08
* Be in awe of every code modification
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Configuration
@ConfigurationProperties(prefix = "smart-doc")
public class ApiDocProperties {
@Value("${server.port}")
private int port;
@Value("${app.id}")
private String appId;
@Value("${server.servlet.context-path:}")
private String pathFilter;
@Value("${spring.profiles.active:dev}")
private String profileActive;
private boolean htmlEnable;
private String outPath;
private String responseClassName;
private Map<String, String> requestHeader = new HashMap<>();
private String packageFilters;
}
/**
* @author Java技术债务
* @date 2022-08-16 18:17
* Be in awe of every code modification
*/
@Slf4j
@EnableConfigurationProperties({ApiDocProperties.class})
@Controller
//@RequestMapping("${spring.application.name}/doc")
@Profile({"dev", "local", "qa", "test", "sit", "uat"})
@RequestMapping("/doc")
public class DocController {
@Autowired
private ApiDocProperties apiDocProperties;
private ApiDocConfig apiDocConfig;
public DocController() {
}
@GetMapping("/openapi.json")
@ResponseBody
public String openapi() {
initApiDocConfig();
ApiConfig config = apiDocConfig.getApiConfig();
return OpenApiBuilder.buildOpenApi(config).trim().replace(" ", "");
}
@GetMapping("/build")
public String buildHtml() {
initApiDocConfig();
... ...
}
}
代码解释:
WebMvcConfig
解决跨域以及文件映射,由开发人员决定是否使用smart-doc生成的API接口文档页面,因为有的已经使用了其他产品,可以将smart-doc生成的json同步到现有的产品,当然如果你只使用smart-doc的话,不需要配置文件映射。ApiDocProperties
自定义配置,开发人员只关心自己当前服务的smart-doc相关配置即可DocController
工具包中的uri进行资源访问,可以自定义html,openapi.json等路径。也可以自定义开发,生成json文件或者json字符串等。当前为了适用本公司,简单的自定义了一些开发,以下是简单的配置了一些路径资源:
如果你想使用这种的话,你可以继续研究与开发。。。
可以入手使用,关键是零侵入,还支持dubbo方式(虽然我未体验使用此方式)
谢谢阅读,如果有不一样的见解,请评论说出你的观点以及见解。。。觉得不错的话,介意点个赞吗?我知道你不介意,谢谢哈。。。
一些工具特性介绍等引用smart-doc官方文档:https://smart-doc-group.github.io/#/zh-cn/start/quickstart