在團隊協做的時候許多時候須要用到接口文檔,咱們一般經過手工編寫大量重複格式的文檔,讓我想起了程序員最討厭的兩件事:沒有文檔,編寫文檔。哈哈,若是使用過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
參考資料: