在团队协做的时候许多时候须要用到接口文档,咱们一般经过手工编写大量重复格式的文档,让我想起了程序员最讨厌的两件事:没有文档,编写文档。哈哈,若是使用过swagger的朋友应该都很了解它带给咱们的便利,若是你尚未使用swagger的话,正好打算编写RESTful API文档,这里有一篇文章Spring Boot中使用Swagger2构建强大的RESTful API文档能够帮助你在较短的时间内构建出一个线上文档,有些时候咱们须要生成离线文档有该怎么作呢?带着这个问题咱们一块儿去出发。html
Swagger - 先后端分离后的契约html5
经过Swagger进行API设计,与Tony Tam的一次对话git
一个简短的总结,更好的生成RESTful API文档,提供相应的测试功能,效果图以下:程序员
swagger为咱们提供了生成在线文档的功能,然而有些时候客户须要的是离线文档的api,有没有什么较好的办法能够经过swagger帮助咱们生成离线文档呢?github
这就是今天的主角: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自动生成文档。web
其实咱们的思路就是把swagger在线文档转成staticdocs形式的文档,引入相关的一些依赖 Spring Rest Docs的依赖spring-restdocs-mockmvc,离线文档的依赖springfox-staticdocs,由于要在单元测试的时候生成文档,因此再加测试相关的spring-boot-starter-test。spring
<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>
咱们使用asciidoctor-maven-plugin插件将Asciidoc格式转成HTML5格式
了解更多: 使用介绍json
<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配置:api
@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
参考资料: