Swagger离线接口文档生成总结
前言
需求:项目使用spring boot,maven工程,需要使用swagger生成接口文档,格式为html。
在网上查了一些资料,大部分是使用swagger-ui,在线文档,不符合要求;小部分提到了离线文档生成,但是总觉得有点绕,结合实际的使用经验,输出总结一篇,供参考。
本文使用常见的生成流程,swagger json -> asciidoc -> html,下面说明使用过程的几个关键点。
关键点1: 生成swagger json
生成swagger json,需要曲线救国一下,要在单元测试中调用生成函数生成。
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
//Application.class需要替换为你的工程中的applicaton类
//SwaggerConfig为swagger配置信息,详情如下
@SpringApplicationConfiguration(classes = {Application.class, SwaggerConfig.class})
public class Swagger2MarkupTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void convertSwaggerToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler
.outputDirectory("src/docs/asciidoc/generated").build())
.andExpect(status().isOk());
}
}
SwaggerConfig类主要配置需要扫描的接口信息,也放在单元测试的目录下。
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现
*
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//package包名替换为你的工程中需要扫描的接口的包名
.apis(RequestHandlerSelectors.basePackage("*.*.*.controller"))
.paths(PathSelectors.any())
.build();
}
/**
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("XX在线接口文档")
.version("1.0")
.build();
}
}
这一步依赖的jar包如下:
<!--主要用于函数和类的解释说明,swagger会扫描注解,生成对应信息-->
<!--如果不需要更多说明,该jar包可以移除-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.19</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<version>1.1.2.RELEASE</version>
<scope>test</scope>
</dependency>
完成上述这几步,运行测试,就会生成对应的swagger json文件。
关键点2:生成ascii doc
该步骤主要使用swagger2markup-maven-plugin来生成(gradle工程有对应的gradle plugin),pom配置如下:
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>${swagger2markup.plugin.version}</version>
<dependencies>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-import-files-ext</artifactId>
<version>${swagger2markup.extension.version}</version>
</dependency>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>${swagger2markup.version}</version>
</dependency>
</dependencies>
<configuration>
<!--swagger json路径-->
<swaggerInput>${swagger.input}</swaggerInput>
<!--ascii doc输出目录-->
<outputDir>${generated.asciidoc.directory}</outputDir>
<config>
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
<swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>
<swagger2markup.extensions.dynamicOverview.contentPath>${project.basedir}/src/docs/asciidoc/extensions/overview</swagger2markup.extensions.dynamicOverview.contentPath>
<swagger2markup.extensions.dynamicDefinitions.contentPath>${project.basedir}/src/docs/asciidoc/extensions/definitions</swagger2markup.extensions.dynamicDefinitions.contentPath>
<swagger2markup.extensions.dynamicPaths.contentPath>${project.basedir}/src/docs/asciidoc/extensions/paths</swagger2markup.extensions.dynamicPaths.contentPath>
<swagger2markup.extensions.dynamicSecurity.contentPath>${project.basedir}src/docs/asciidoc/extensions/security</swagger2markup.extensions.dynamicSecurity.contentPath>
</config>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>convertSwagger2markup</goal>
</goals>
</execution>
</executions>
</plugin>
相关配置信息:
<properties>
<swagger2markup.version>1.3.1</swagger2markup.version>
<swagger2markup.plugin.version>1.3.3</swagger2markup.plugin.version>
<swagger2markup.extension.version>1.3.1</swagger2markup.extension.version>
<asciidoctorj.version>1.5.5</asciidoctorj.version>
<asciidoctorj.pdf.version>1.5.0-alpha.15</asciidoctorj.pdf.version>
<jruby.version>9.1.8.0</jruby.version>
<!--swagger json路径,在convertSwaggerToAsciiDoc中指定,替换成自己工程中的路径-->
<swagger.input>${project.basedir}/src/docs/asciidoc/generated/XXXX.json</swagger.input>
<!--assiidoc使用的输入目录,adoc文件所在路径-->
<asciidoctor.input.directory>${project.basedir}/src/docs/asciidoc</asciidoctor.input.directory>
<!--assiidoc输出目录-->
<generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory>
<!--html文件输出目录-->
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
<!--pdf文件输出目录-->
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
</properties>
关键点3:生成html或其它类型文件
该步骤使用assiidoc来将ascii doc文件转换为html或其它类型文件。
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.5</version>
<dependencies>
<!-- 生成pdf文件的jar包依赖。(如果不需要可以移除) -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>${asciidoctorj.pdf.version}</version>
</dependency>
<!-- Comment this section to use the default jruby artifact provided by the plugin -->
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>${jruby.version}</version>
</dependency>
<!-- Comment this section to use the default AsciidoctorJ artifact provided by the plugin -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>${asciidoctorj.version}</version>
</dependency>
</dependencies>
<configuration>
<!-- asciidoc输入目录,该目录用于存放adoc文件,我的理解是生成文档的框架文件,用于描述文档结构的-->
<sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>
<!--指定adoc文件名-->
<sourceDocumentName>index.adoc</sourceDocumentName>
<attributes>
<doctype>book</doctype>
<toc>left</toc>
<toclevels>3</toclevels>
<numbered></numbered>
<hardbreaks></hardbreaks>
<sectlinks></sectlinks>
<sectanchors></sectanchors>
<!--ascii doc文件所在路径,步骤2中的输出目录-->
<generated>${generated.asciidoc.directory}</generated>
</attributes>
</configuration>
<executions>
<!-- 生成html文件 -->
<execution>
<id>output-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html5</backend>
<!--html输出目录-->
<outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
</configuration>
</execution>
<!-- 生成pdf文件.(如果不需要可以移除) -->
<execution>
<id>output-pdf</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<!-- pdf文件输出目录-->
<outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
index.adoc的内容:
include::{generated}/overview.adoc[]
include::{generated}/security.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/definitions.adoc[]
ok,完成这三个步骤,运行mnv install命令,就可以生成出像样的接口文档了。
总结
在实际使用中,可以将文件转换的工作当做一个单独的工程,swager json文件生成只作为单元测试代码存在,这样整个工程真正需要打进jar包的只有swagger-annotations,对现有代码影响较小,功能也很独立。
参考文档:
[1] 从代码中生成接口文档的完整过程–Gradle工程实例
[2] 将Swagger文件转换为html文件的maven工程示例
[3] Swagger2Markup官方文档
[4] Swagger2离线文档:PDF和Html5格式
[6] Swagger+spring boot 转换为html,PDF文件等