Spring Boot [如何優雅的編寫文檔]

導讀:

在團隊協做的時候許多時候須要用到接口文檔,咱們一般經過手工編寫大量重複格式的文檔,讓我想起了程序員最討厭的兩件事:沒有文檔,編寫文檔。哈哈,若是使用過swagger的朋友應該都很瞭解它帶給咱們的便利,若是你尚未使用swagger的話,正好打算編寫RESTful API文檔,這裏有一篇文章Spring Boot中使用Swagger2構建強大的RESTful API文檔能夠幫助你在較短的時間內構建出一個線上文檔,有些時候咱們須要生成離線文檔有該怎麼作呢?帶着這個問題咱們一塊兒去出發。html

關於swagger:

Swagger - 先後端分離後的契約html5

經過Swagger進行API設計,與Tony Tam的一次對話git

一個簡短的總結,更好的生成RESTful API文檔,提供相應的測試功能,效果圖以下:程序員

swagger

編寫離線文檔:

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

引入pom依賴:

其實咱們的思路就是把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>

使用Maven插件:

咱們使用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的插件,只須要執行測試就能夠生成相應的文檔, 效果圖以下:後端

Spring REST Docs

補充:

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

參考資料:

Spring REST Docs

SpringBoot項目生成RESTfull API的文檔

Introduction to Spring REST Docs

asciidoctor-maven-plugin

相關文章
相關標籤/搜索