看了不少Swagger 转PDF的文章,很多不能很好的跑起来,或多或少有点问题,并对PDF中文问题进行了处理,所以自己总结,写个总结,做个示例
本文参考了:
http://swagger2markup.github.io/swagger2markup/1.3.1/
https://github.com/Swagger2Markup/spring-swagger2markup-demo
Swagger 转PDF 的背景:
Swagger 是一个强大的API文档工具,但是在实际使用中会碰到一个比较现实的问题,
- 你开发好了一个接口,但是项目环境隔离,导致接口调用方访问不到Swagger,但是人家却等着开发
- 上个版本的迭代,依然在接续,但是,新的版本已经开始,人家看不到新版的Swagger
但是,重新编写 接口文档,又费时费力,所以就需要Swagger 生成静态文档
技术重点:
- swagger2markup JSON转成对应格式的文本文件,支持有asciidoc,markdown,confluence
- asciidoctorj ,将对应的文本文件转为 HTML
- 项目架构为 JDK1.8 maven springboot
示例代码:
1·pom 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cloud</groupId>
<artifactId>swagger-converter</artifactId>
<version>1.0.0</version>
<name>swagger-converter</name>
<description>swagger-converter</description>
<properties>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<!-- java version -->
<java.version>1.8</java.version>
<!-- swagger2markup config -->
<swagger2markup.version>1.3.3</swagger2markup.version>
<!-- 输出语言类型ASCIIDOC(".adoc,.asciidoc"),MARKDOWN(".md,.markdown"),CONFLUENCE_MARKUP(".txt") -->
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
<swagger2markup.outputLanguage>ZH</swagger2markup.outputLanguage>
<!-- AS_IS,TAGS,REGEX -->
<swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>
<!-- asciidoctor config -->
<asciidoctor.input.directory>${project.basedir}/src/docs/generated</asciidoctor.input.directory>
<asciidoctor.font>${project.basedir}/src/main/resources/fonts</asciidoctor.font>
<asciidoctor.themes>${project.basedir}/src/main/resources/themes</asciidoctor.themes>
<!-- swagger config -->
<!-- swagger JSON 数据地址 -->
<swagger.input>http://127.0.0.1:8080/v2/api-docs?group=%E7%94%A8%E6%88%B7%E7%9B%B8%E5%85%B3%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3</swagger.input>
<swagger.output.dir>${project.basedir}/src/docs/swagger</swagger.output.dir>
<swagger.snippetOutput.dir>${project.basedir}/src/docs/snippets</swagger.snippetOutput.dir>
<generated.asciidoc.directory>${project.basedir}/src/docs/generated</generated.asciidoc.directory>
<asciidoctor.html.output.directory>${project.basedir}/src/docs/html</asciidoctor.html.output.directory>
<asciidoctor.pdf.output.directory>${project.basedir}/src/docs/pdf</asciidoctor.pdf.output.directory>
<jackson.version>2.9.6</jackson.version>
<springfox.version>2.9.2</springfox.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.20</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-smile</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-afterburner</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-staticdocs</artifactId>
<version>2.6.1</version>
<exclusions>
<exclusion>
<groupId>io.github.robwin</groupId>
<artifactId>swagger2markup</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jsonSchema</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>io.github.robwin</groupId>
<artifactId>assertj-swagger</artifactId>
<version>0.8.1</version>
</dependency>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-spring-restdocs-ext</artifactId>
<version>${swagger2markup.version}</version>
</dependency>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>${swagger2markup.version}</version>
</dependency>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<compilerVersion>${java.version}</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
<!-- prevents endPosTable exception for maven compile -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<io.springfox.staticdocs.outputDir>${swagger.output.dir}</io.springfox.staticdocs.outputDir>
<io.springfox.staticdocs.snippetsOutputDir>${swagger.snippetOutput.dir}</io.springfox.staticdocs.snippetsOutputDir>
</systemPropertyVariables>
</configuration>
</plugin>
<!-- First, use the swagger2markup plugin to generate asciidoc -->
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>${swagger2markup.version}</version>
<dependencies>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-import-files-ext</artifactId>
<version>${swagger2markup.version}</version>
</dependency>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-spring-restdocs-ext</artifactId>
<version>${swagger2markup.version}</version>
</dependency>
</dependencies>
<configuration>
<swaggerInput>${swagger.input}</swaggerInput>
<outputDir>${generated.asciidoc.directory}</outputDir>
<config>
<swagger2markup.markupLanguage>${swagger2markup.markupLanguage}</swagger2markup.markupLanguage>
<swagger2markup.pathsGroupedBy>${swagger2markup.pathsGroupedBy}</swagger2markup.pathsGroupedBy>
<swagger2markup.outputLanguage>${swagger2markup.outputLanguage}</swagger2markup.outputLanguage>
<swagger2markup.extensions.dynamicOverview.contentPath>${generated.asciidoc.directory}</swagger2markup.extensions.dynamicOverview.contentPath>
<swagger2markup.extensions.dynamicDefinitions.contentPath>${generated.asciidoc.directory}</swagger2markup.extensions.dynamicDefinitions.contentPath>
<swagger2markup.extensions.dynamicPaths.contentPath>${generated.asciidoc.directory}</swagger2markup.extensions.dynamicPaths.contentPath>
<swagger2markup.extensions.dynamicSecurity.contentPath>${generated.asciidoc.directory}</swagger2markup.extensions.dynamicSecurity.contentPath>
<swagger2markup.extensions.springRestDocs.snippetBaseUri>${generated.asciidoc.directory}</swagger2markup.extensions.springRestDocs.snippetBaseUri>
<swagger2markup.extensions.springRestDocs.defaultSnippets>true</swagger2markup.extensions.springRestDocs.defaultSnippets>
</config>
</configuration>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>convertSwagger2markup</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Run the generated asciidoc through Asciidoctor to generate
other documentation types, such as PDFs or HTML5 -->
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.6</version>
<!-- Include Asciidoctor PDF for pdf generation -->
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.0-alpha.16</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
<!-- Configure generic document generation settings -->
<configuration>
<sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>
<sourceDocumentName>index.adoc</sourceDocumentName>
<attributes>
<doctype>book</doctype>
<toc>left</toc>
<toclevels>3</toclevels>
<numbered></numbered>
<hardbreaks></hardbreaks>
<sectlinks></sectlinks>
<sectanchors></sectanchors>
<generated>${generated.asciidoc.directory}</generated>
</attributes>
</configuration>
<!-- Since each execution can only handle one backend, run
separate executions for each desired output type -->
<executions>
<execution>
<id>output-html</id>
<phase>test</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html5</backend>
<outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
</configuration>
</execution>
<execution>
<id>output-pdf</id>
<phase>test</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory>
<attributes>
<pdf-fontsdir>${asciidoctor.font}</pdf-fontsdir>
<pdf-stylesdir>${asciidoctor.themes}</pdf-stylesdir>
<pdf-style>cn</pdf-style>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
<!-- specify the main class for the manifest -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>io.github.robwin.swagger2markup.petstore.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- copy dependencies to the lib directory -->
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- copy the generated documents -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static/docs</outputDirectory>
<resources>
<resource>
<directory>${asciidoctor.html.output.directory}</directory>
</resource>
<resource>
<directory>${asciidoctor.pdf.output.directory}</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
其中:
swagger.input:为在线swagger JSON字符串,可为文件也可以是在线接口请求
asciidoctor.pdf.output.directory:pdf 输出地址
asciidoctor.html.output.directory:html 输出地址
generated.asciidoc.directory:swagger 中间文件保存地址
asciidoctor.font :字体地址
asciidoctor.themes :主题地址
-
获取 swagger 数据地址,最直接的方式:
复制出完整路径, 替换 swagger.input 即可 -
执行 mvn clean test 即可生成对应的PDF接口文档
-
生成的样式为:
pdf:
html:
-
很多时候,公司会搭建 markdown,confluence 文档服务器,所以我们怎么可以生成对应的文档呢
-
生成 AsciiDocs
//输出Ascii格式
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.ASCIIDOC)
.withOutputLanguage(Language.ZH)
.withPathsGroupedBy(GroupBy.TAGS)
.withGeneratedExamples()
.withoutInlineSchema()
.withBasePathPrefix()
.withListDelimiter()
.build();
Swagger2MarkupConverter.from(new URL(API_URL))
.withConfig(config)
.build()
.toFile(Paths.get(PATH));
- 生成Confluence
//生成Markdown格式文档
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.CONFLUENCE_MARKUP)
.withOutputLanguage(Language.ZH)
.withPathsGroupedBy(GroupBy.TAGS)
.withGeneratedExamples()
.withoutInlineSchema()
.withBasePathPrefix()
.withListDelimiter()
.build();
Swagger2MarkupConverter.from(new URL(API_URL))
.withConfig(config)
.build()
.toFile(Paths.get(PATH));
- 生成 MarkdownDocs
//生成Markdown格式文档
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.withOutputLanguage(Language.ZH)
.withPathsGroupedBy(GroupBy.TAGS)
.withGeneratedExamples()
.withoutInlineSchema()
.withBasePathPrefix()
.withListDelimiter()
.build();
Swagger2MarkupConverter.from(new URL(API_URL))
.withConfig(config)
.build()
.toFolder(Paths.get(PATH));
示例DEMO,稍后放出