您的位置:首页 > Web前端 > HTML

将Swagger导出HTML、PDF和MARKDOWN的一些心得

2018-03-12 11:26 741 查看
首先,我的项目是SpringBoot1.3.2+Spring4.2.3+JaveSE1.7+JUNIT4
之前也不会,就在网上找了一些教程,但是到我的实际项目中,都会有问题,今天只是记录下都需要怎么样去实现与出现的一些问题
Swagger的配置import static com.google.common.base.Predicates.or;
import static springfox.documentation.builders.PathSelectors.regex;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);

@Bean
public Docket engineDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2)
.groupName("ENGINE_API").apiInfo(cmApiInfo()).select()
.paths(or(regex("/ops/v1/execEngine.*"), regex("/ops/v1/exec/executor.*"))) // and by paths
.build();

return swaggerSpringMvcPlugin;
}

@Bean
public Docket cmDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2).groupName("CM_API")
.apiInfo(cmApiInfo()).select().paths(or(regex("/conf/v1/.*"))) // and by paths
.build();

return swaggerSpringMvcPlugin;
}

@Bean
public Docket opDefinitionkDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2)
.groupName("OpDefinition_API").apiInfo(opDefApiInfo()).select()
.paths(or(regex("/ops/v1/opdefinition.*"))) // and by paths
.build();

return swaggerSpringMvcPlugin;
}

@Bean
public Docket opJobDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2)
.groupName("OpJob_API").apiInfo(opJobApiInfo()).select()
.paths(or(regex("/ops/v1/opjob.*"), regex("/ops/v1/plan.*"))) // and by paths
.build();

return swaggerSpringMvcPlugin;
}

@SuppressWarnings("unchecked")
@Bean
public Docket dashboardDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2)
.groupName("Dashboard_API").apiInfo(dashboradApiInfo()).select()
.paths(or(regex("/cm/v1/dashboard.*"))) // and by paths
.build();
return swaggerSpringMvcPlugin;
}

@SuppressWarnings("unchecked")
@Bean
public Docket inspectDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2)
.groupName("Inspect_API").apiInfo(inspectApiInfo()).select()
.paths(or(regex("/inspect/v1/.*"))) // and by paths
.build();

return swaggerSpringMvcPlugin;
}

@SuppressWarnings("unchecked")
@Bean
public Docket sysMgtDocket() {
Docket swaggerSpringMvcPlugin = new Docket(DocumentationType.SWAGGER_2)
.groupName("SysMgt_API").apiInfo(opLogApiInfo()).select()
.paths(or(regex("/ops/v1/oplog.*"), regex("/cms/v1/sys/dept.*"),
regex("/cms/v1/sys/account.*"), regex("/cms/v1/sys/role.*"), regex("/cms/v1/login"),
regex("/cms/v1/logout"), regex("/cms/v1/sys/permission.*"))) // and by paths
.build();

return swaggerSpringMvcPlugin;
}

private ApiInfo cmApiInfo() {
return new ApiInfoBuilder()
.title("此分组的具体信息")
.description("描述信息")
.version("1.0")
.contact(new Contact("公司名称", "公司主页地址", "联系人邮件"))
.build();
}

private ApiInfo opDefApiInfo() {
return new ApiInfoBuilder()
.title("此分组的具体信息")
.description("描述信息")
.version("1.0")
.contact(new Contact("公司名称", "公司主页地址", "联系人邮件"))
.build();
}

private ApiInfo opJobApiInfo() {
return new ApiInfoBuilder()
.title("此分组的具体信息")
.description("描述信息")
.version("1.0")
.contact(new Contact("公司名称", "公司主页地址", "联系人邮件"))
.build();
}

private ApiInfo dashboradApiInfo() {
return new ApiInfoBuilder()
.title("此分组的具体信息")
.description("描述信息")
.version("1.0")
.contact(new Contact("公司名称", "公司主页地址", "联系人邮件"))
.build();
}

private ApiInfo opLogApiInfo() {
return new ApiInfoBuilder()
.title("此分组的具体信息")
.description("描述信息")
.version("1.0")
.contact(new Contact("公司名称", "公司主页地址", "联系人邮件"))
.build();
}

private ApiInfo inspectApiInfo() {
return new ApiInfoBuilder()
.title("此分组的具体信息")
.description("描述信息")
.version("1.0")
.contact(new Contact("公司名称", "公司主页地址", "联系人邮件"))
.build();
}
}

注意:强调一下,这里面我们用了Swagger分组的方式,也就是上面的groupName内容,这个
pom.xml配置
<?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>

<groupId>com.chinamobile.iot</groupId>
<artifactId>restdocs</artifactId>
<version>1.0-SNAPSHOT</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>

<properties>
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>

<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
<generated.asciidoc.directory>src/asciidoc</generated.asciidoc.directory>
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>

</properties>

<dependencies>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.8</version>
</dependency>

<!--WEB层-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--Swagger2-->
<!--在线文档-->
<!--swagger本身不支持spring mvc的,springfox把swagger包装了一下,让他可以支持springmvc-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<!--离线文档-->
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<version>1.1.2.RELEASE</version>
<scope>test</scope>
</dependency>
<!--springfox-staticdocs 生成静态文档-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-staticdocs</artifactId>
<version>2.6.1</version>
</dependency>

<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>

<build>
<plugins>
<!--<plugin>
<groupId>org.springframework.boot</groupId>

ca88
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>-->
<!--Maven通过Maven Surefire Plugin插件执行单元测试-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<!-- Run the generated asciidoc through Asciidoctor to generate
other documentation types, such as PDFs or HTML5 -->
<!--通过Asciidoctor使得asciidoc生成其他的文档格式,例如:PDF 或者HTML5-->
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.3</version>
<!-- Include Asciidoctor PDF for pdf generation -->
<!--生成PDF-->
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.0-alpha.14</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>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>
<!--html5-->
<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>
<!--pdf-->
<execution>
<id>output-pdf</id>
<phase>test</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>

生成HTML和PDF的测试类import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import com.idcos.cms.server.CloudConfServer;

import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import springfox.documentation.staticdocs.SwaggerResultHandler;

@AutoConfigureMockMvc
@AutoConfigureRestDocs(outputDir = "target/generated-snippets")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)//工程的启动类
public class SwaggerToHTMLandPDFTest {

private String snippetDir = "target/generated-snippets";
private String swaggerOutput = "src/asciidoc";
private String adocDir = "docs/asciidoc/src/asciidoc";

@Autowired
private MockMvc mockMvc;

@Test
public void Test() throws Exception {
// 得到swagger.json,写入outputDir目录中
mockMvc.perform(get("/v2/api-docs?group=SysMgt_API").accept(MediaType.APPLICATION_JSON))
.andDo(SwaggerResultHandler.outputDirectory(swaggerOutput).build())
.andExpect(status().isOk())
.andReturn();

// 读取上一步生成的swagger.json转成asciiDoc,写入到outputDir
Swagger2MarkupConverter.from(swaggerOutput + "/swagger.json")
.withMarkupLanguage(MarkupLanguage.ASCIIDOC)// 格式
.withExamples(snippetDir)
.build()
.intoFolder(adocDir);// 输出
}

}生成MARKDOWN的测试类import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.nio.file.Paths;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import com.idcos.cms.server.CloudConfServer;

import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import springfox.documentation.staticdocs.SwaggerResultHandler;

@AutoConfigureMockMvc
@AutoConfigureRestDocs(outputDir = "src/asciidoc")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = CloudConfServer.class)
public class SwaggerToMarkdownTest {

private String outputDir = "src/asciidoc";

@Autowired
private MockMvc mockMvc;

//生成markdowd文档
@Test
public void Test1() throws Exception{
// 得到swagger.json,写入outputDir目录中
mockMvc.perform(get("/v2/api-docs?group=SysMgt_API").accept(MediaType.APPLICATION_JSON))
.andDo(SwaggerResultHandler.outputDirectory(outputDir).build())
.andExpect(status().isOk())
.andReturn();

//生成markdown的配置
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.withOutputLanguage(Language.ZH)
.withPathsGroupedBy(GroupBy.TAGS)
.build();

//获取swagger.json文件,输出到outputDir中
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(Paths.get("src/asciidoc/swagger.json")).withConfig(config).build();
converter.toFile(Paths.get(outputDir));
}
}注意:在上面的mockMvc获取swagger.json文件的地址中,加入了group的查询参数,我之前在网上搜索的教程中,只有一个说了这个问题,但是也不是很清楚,导致我获取json文件很长时间。如果在swagger的配置中(看上面的SwaggerConfigration),进行了分组,在获取swagger.json的时候,就需要加上group这个参数,如果没有分组,就不用加

顺便提一下,如果你学过swagger,swagger的访问地址http://localhost:8080/swagger-ui.html,就可以看到接口的所有信息,并且进行测试,还有一个地址http://localhost:8080/v2/api-docs,打开这个地址,页面就显示一堆数据,就是swagger.json文件的具体信息,如果分组,还是需要加上group这个参数。

还需要有一个文件index.adocinclude::{generated}/overview.adoc[]
include::{generated}/definitions.adoc[]
include::{generated}/paths.adoc[]当在运行一个测试类之后,会生成swagger.json,测试类的第二个方法,会生成三个文件



这三个文件就是把swagger.json文件进行了处理,为构建html和pdf生成adoc文件

步骤(生成html和pdf):
1.运行第一个测试类,生成swagger.json和三个adoc文件
2.命令行,运行mvn clean test
3.在target/asciidoc下面就会生成html和pdf

生成markdown文件,直接运行第二个测试类

注意:生成pdf的时候,对中文的支持很不好,会缺少文字,由于使用的分组,只能一个个的文档生成

我在构建文档过程中出现的问题
1.升级Springboot(1.3.2升级到1.5.2)
由于我的项目是使用mongo数据库的,配置文件<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd" default-autowire="byName">

<mongo:mongo id="mongo" replica-set="${mongo.replicaSet}" >
<mongo:options connections-per-host="${mongo.connectionsPerHost}"
threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
connect-timeout="${mongo.connectTimeout}" max-wait-time="${mongo.maxWaitTime}"
auto-connect-retry="${mongo.autoConnectRetry}" socket-keep-alive="${mongo.socketKeepAlive}"
socket-timeout="${mongo.socketTimeout}"
write-number="1" write-timeout="0" write-fsync="true" />
</mongo:mongo>

<!-- mongo:db-factory dbname="${mongo.dbname}" mongo-ref="mongo" username="${mongo.username}"
password="${mongo.password}"/>-->
<mongo:db-factory dbname="${mongo.dbname}" mongo-ref="mongo"/>
<!-- <mongo:db-factory dbname="${mongo.dbname}" mongo-ref="mongo"/> -->

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg ref="mappingMongoConverter" />
</bean>

<!-- <mongo:mapping-converter id="converter" db-factory-ref="mongoDbFactory"
/> -->
<!-- 默认Mongodb类型映射 -->
<bean id="defaultMongoTypeMapper"
class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
<constructor-arg name="typeKey">
<null /><!-- 这里设置为空,可以把 spring data mongodb 多余保存的_class字段去掉 -->
</constructor-arg>
</bean>

<bean id="mappingContext"
class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />

<!-- 转换器:1、去掉write的_class字段 2、TimestampConverter -->

<bean id="mappingMongoConverter"
class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mappingContext" ref="mappingContext" />
<property name="typeMapper" ref="defaultMongoTypeMapper" />
</bean>

<!-- mongo操作文件的模板 -->
<bean id="gridFsTemplate" class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
<constructor-arg ref="mongoDbFactory" />
<constructor-arg ref="mappingMongoConverter" />
</bean>

</beans>升级了之后,<mongo:mongo>这个element不能使用了,启动的时候导致mongo的bean都不可使用,程序无法启动,目前只能使用<mongo:mongo-client>,具体配置改为<mongo:mongo-client host="localhost" port="27017" id="mongo">
<mongo:client-options socket-keep-alive="${mongo.socketKeepAlive}"
socket-timeout="${mongo.socketTimeout}"
connect-timeout="${mongo.connectTimeout}"
max-wait-time="${mongo.maxWaitTime}"
threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}"
connections-per-host="${mongo.connectionsPerHost}"
/>
</mongo:mongo-client>其他的不用动

2.swagger-models的jar包出问题
之前这个jar包是不需要在pom.xml文件中引用的,是springfox.swagger2的包引用的,但是在运行第二个测试类的时候,有一个枚举类总是缺少元素,只能把这个包升级,在pom.xml中添加<dependency>    <groupId>io.swagger</groupId>    <artifactId>swagger-models</artifactId>    <version>1.5.18</version> </dependency>
解决此问题

最后在强调一下,在测试的过程中,会有一些文件路径的问题,这个只能具体测试的时候,去解决了
特此感谢 http://blog.csdn.net/fly910905/article/details/79131755#comments
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息