导读:
在团队协作的时候许多时候需要用到接口文档,我们通常通过手工编写大量重复格式的文档,让我想起了程序员最讨厌的两件事:没有文档,编写文档。哈哈,如果使用过swagger的朋友应该都很了解它带给我们的便利,如果你还没有使用swagger的话,正好打算编写RESTful API文档,这里有一篇文章Spring Boot中使用Swagger2构建强大的RESTful API文档可以帮助你在较短的时间内构建出一个线上文档,有些时候我们需要生成离线文档有该怎么做呢?带着这个问题我们一起去出发。
关于swagger:
通过Swagger进行API设计,与Tony Tam的一次对话
一个简短的总结,更好的生成RESTful API文档,提供相应的测试功能,效果图如下:
编写离线文档:
swagger为我们提供了生成在线文档的功能,然而有些时候客户需要的是离线文档的api,有没有什么较好的办法可以通过swagger帮助我们生成离线文档呢?
这就是今天的主角:Springfox和Spring Rest Docs帮我们做的事情
1.预备知识:
建议了解swagger、Asciidoc、asciidoctor-maven-plugin和SpringBoot Testing。对应的资料可自行谷歌。
2.关于Springfox和Spring Rest Docs:
官网是这样描述的Springfox:Automated JSON API documentation for API's built with Spring。我们可以理解为为 基于Spring构建的API自动生成文档。
引入pom依赖:
其实我们的思路就是把swagger在线文档转成staticdocs形式的文档,引入相关的一些依赖 Spring Rest Docs的依赖spring-restdocs-mockmvc,离线文档的依赖springfox-staticdocs,因为要在单元测试的时候生成文档,所以再加测试相关的spring-boot-starter-test。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<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>
<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>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-staticdocs</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.8</version>
</dependency>
使用Maven插件:
我们使用asciidoctor-maven-plugin插件将Asciidoc格式转成HTML5格式
了解更多: 使用介绍
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<configuration>
<!--配置index.adoc的获取路径-->
<!--<sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>-->
<outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
<sourceDocumentName>index.adoc</sourceDocumentName>
<attributes>
<doctype>book</doctype>
<toc>left</toc>
<toclevels>3</toclevels>
<generated>${generated.asciidoc.directory}</generated>
</attributes>
</configuration>
<executions>
<execution>
<id>output-html</id>
<phase>test</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<attributes>
<snippets>${project.build.directory}/generated-snippets</snippets>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
编写测试类生成离线文档:
import cn.sunxyz.domain.UserInfo;
import com.alibaba.fastjson.JSON;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.GroupBy;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import org.junit.After;
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.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import springfox.documentation.staticdocs.SwaggerResultHandler;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@AutoConfigureMockMvc
@AutoConfigureRestDocs(outputDir = "target/generated-snippets")
@RunWith(SpringRunner.class)
@SpringBootTest
public class DocumentationBuild {
private String snippetDir = "target/asciidoc/generated-snippets";
private String outputDir = "target/asciidoc";
@Autowired
private MockMvc mockMvc;
@After
public void Test() throws Exception {
// 得到swagger.json,写入outputDir目录中
mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON))
.andDo(SwaggerResultHandler.outputDirectory(outputDir).build())
.andExpect(status().isOk())
.andReturn();
// 读取上一步生成的swagger.json转成asciiDoc,写入到outputDir
// 这个outputDir必须和插件里面<generated></generated>标签配置一致
Swagger2MarkupConverter.from(outputDir + "/swagger.json")
.withPathsGroupedBy(GroupBy.TAGS)// 按tag排序
.withMarkupLanguage(MarkupLanguage.ASCIIDOC)// 格式
.withExamples(snippetDir)
.build()
.intoFolder(outputDir);// 输出
}
@Test
public void TestApi() throws Exception {
mockMvc.perform(get("/api/user/1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("查询用户", preprocessResponse(prettyPrint())));
UserInfo userInfo = new UserInfo();
userInfo.setName("lisi");
userInfo.setAge(23);
userInfo.setAddress("山东济南");
userInfo.setSex("男");
mockMvc.perform(post("/api/user").contentType(MediaType.APPLICATION_JSON)
.content(JSON.toJSONString(userInfo))
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().is2xxSuccessful())
.andDo(MockMvcRestDocumentation.document("新增用户", preprocessResponse(prettyPrint())));
}
}
由于前面已经配置了maven的插件,只需要执行测试就可以生成相应的文档, 效果图如下:
补充:
Swagger配置:
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket configSpringfoxDocket_all(ApiInfo apiInfo) {
return new Docket(DocumentationType.SWAGGER_2)
.produces(Sets.newHashSet("application/json"))
.consumes(Sets.newHashSet("application/json"))
.protocols(Sets.newHashSet("http", "https"))
.apiInfo(apiInfo)
.forCodeGeneration(true)
.select().paths(regex("/api.*"))
.build();
}
@Bean
public Docket createUserInfoRestApi(ApiInfo apiInfo) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("user")
.produces(Sets.newHashSet("application/json"))
.consumes(Sets.newHashSet("application/json"))
.protocols(Sets.newHashSet("http", "https"))
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("cn.sunxyz.controller"))
.paths(regex("/api/user.*"))
.build();
}
@Bean
public ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Springfox REST API")
.description("Descriptions.")
.termsOfServiceUrl("http://springfox.io")
.license("Apache License Version 2.0")
.licenseUrl("https://github.com/springfox/springfox/blob/master/LICENSE")
.version("2.0")
.build();
}
}
相关源码已托管github
参考资料:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。