SpringBoot項目生成RESTfull API的文檔

本人所在的項目團隊分為前端開發(fā)和后端開發(fā)兩個子小組,前后端通過RESTfull API通信弧岳,過去一般都要用word來寫API文檔,隨著需求的變化和開發(fā)的深入,往往還要多次更新API文檔簇捍,這會給開發(fā)人員增加不少工作量。最近俏拱,項目組引入了Springfox和Spring Rest Docs來自動生成文檔暑塑,本文做個記錄。

1.預(yù)備知識

建議了解swagger锅必、Asciidoc事格、asciidoctor-maven-pluginSpringBoot Testing。本人覺得Asciidoc官方介紹看起來比較晦澀搞隐,因此主要參考下面兩篇內(nèi)容:
使用Asciidoc代替Markdown和Word撰寫開發(fā)文檔
AsciidocFX Asciidoc的開源編輯器驹愚,連Markdown也支持。

2.關(guān)于Springfox和Spring Rest Docs

借用官網(wǎng)的一句話介紹Springfox:Automated JSON API documentation for API's built with Spring尔许。我理解就是為基于Spring構(gòu)建的API自動生成文檔么鹤。
最終目標是為我們的項目生成如下形式的文檔:

Springfox形式的文檔

Spring Rest DocsDocument RESTful services by combining hand-written documentation with auto-generated snippets produced with Spring MVC Test. 本文主要用Spring Rest Docs來生成API的例子。

3.在線文檔與離線文檔

必須要說明味廊,這里的目標是自動生成被官方稱為staticdocs的文檔(暫且理解為離線文檔)蒸甜,對應(yīng)Springfox官方文檔6. Configuring springfox-staticdocs棠耕。如果是在線文檔,可以參考這篇博文:Spring Boot中使用Swagger2構(gòu)建強大的RESTful API文檔

4.從Maven依賴開始

Spring Boot中使用Swagger2構(gòu)建強大的RESTful API文檔這篇博文中已經(jīng)知道了如何生成在線文檔柠新,其實我們的思路就是把在線文檔轉(zhuǎn)成staticdocs形式的文檔窍荧,因此該篇博文引用的依賴都要引入,Spring Rest Docs的依賴spring-restdocs-mockmvc恨憎,離線文檔的依賴springfox-staticdocs蕊退,因為要在單元測試的時候生成文檔,所以再加測試相關(guān)的spring-boot-starter-test憔恳。

<dependencies>
        <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>
    </dependencies>

5.Maven插件

asciidoctor-maven-plugin插件是用來把Asciidoc格式轉(zhuǎn)成HTML5格式瓤荔。

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <includes>
                        <include>**/*Documentation.java</include>
                    </includes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.asciidoctor</groupId>
                <artifactId>asciidoctor-maven-plugin</artifactId>
                <version>1.5.3</version>

                <!-- Configure generic document generation settings -->
                <configuration>
                    <sourceDirectory>${project.basedir}/docs/asciidoc</sourceDirectory>
                    <sourceDocumentName>index.adoc</sourceDocumentName>
                    <attributes>
                        <doctype>book</doctype>
                        <toc>left</toc>
                        <toclevels>3</toclevels>
                        <numbered></numbered>
                        <hardbreaks></hardbreaks>
                        <sectlinks></sectlinks>
                        <sectanchors></sectanchors>
                        <generated>${project.build.directory}/asciidoc</generated>
                    </attributes>
                </configuration>
                <!-- Since each execution can only handle one backend, run
                     separate executions for each desired output type -->
                <executions>
                    <execution>
                        <id>output-html</id>
                        <phase>test</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>html5</backend>
                            <!--<outputDirectory>${project.basedir}/docs/asciidoc/html</outputDirectory>-->
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

6.文檔生成類的編寫

先貼代碼:

@AutoConfigureMockMvc
@AutoConfigureRestDocs(outputDir = "target/generated-snippets")
@RunWith(SpringRunner.class)
@SpringBootTest
public class Documentation {

    private String snippetDir = "target/generated-snippets";
    private String outputDir = "target/asciidoc";
    //private String indexDoc = "docs/asciidoc/index.adoc";

    @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轉(zhuǎn)成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("/student").param("name", "xxx")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andDo(document("getStudent", preprocessResponse(prettyPrint())));

        Student student = new Student();
        student.setName("xxx");
        student.setAge(23);
        student.setAddress("湖北麻城");
        student.setCls("二年級");
        student.setSex("男");

        mockMvc.perform(post("/student").contentType(MediaType.APPLICATION_JSON)
                .content(JSON.toJSONString(student))
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().is2xxSuccessful())
                .andDo(document("addStudent", preprocessResponse(prettyPrint())));
    }
}

這個類包含兩個方法,TestApi()是用來生成例子钥组,Test()用來生成Asciidoc的文檔输硝。生成例子用到了spring-restdocs-mockmvc,每一個API都要進行單元測試才能生成相應(yīng)的文檔片段(snippets)程梦,生成的結(jié)果如圖:


API使用例子片段

生成完整的Asciidoc文檔用到了Swagger2MarkupConverter点把,第一步先獲取在線版本的文檔并保存到文件swagger.json中,第二步把swagger.json和之前的例子snippets整合并保存為Asciidoc格式的完整文檔屿附。生成結(jié)果如圖:

Asciidoc格式的文檔

7.Swagger的配置

這部分可以定義一些文檔相關(guān)的信息郎逃。

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo())
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.chinamobile.iot.controller"))
            .paths(PathSelectors.any())
            .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
            .title("Student info query api")
            .description("Some API to operator student information")
            .termsOfServiceUrl("http://iot.10086.com/")
            .version("1.0")
            .build();
    }
}

8.生成HTML5的文檔

由于前面已經(jīng)配置了maven的插件,只需要執(zhí)行打包就可以生成相應(yīng)的文檔挺份,如圖:


最終文檔

源碼已放到GitHub:https://github.com/quiterr/restdocs
相關(guān)博文:http://blog.csdn.net/daisy_xiu/article/details/52368920

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末褒翰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子压恒,更是在濱河造成了極大的恐慌影暴,老刑警劉巖错邦,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件探赫,死亡現(xiàn)場離奇詭異,居然都是意外死亡撬呢,警方通過查閱死者的電腦和手機伦吠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魂拦,“玉大人毛仪,你說我怎么就攤上這事⌒究保” “怎么了箱靴?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荷愕。 經(jīng)常有香客問我衡怀,道長棍矛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任抛杨,我火速辦了婚禮够委,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怖现。我一直安慰自己茁帽,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布屈嗤。 她就那樣靜靜地躺著潘拨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饶号。 梳的紋絲不亂的頭發(fā)上战秋,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音讨韭,去河邊找鬼脂信。 笑死,一個胖子當著我的面吹牛透硝,可吹牛的內(nèi)容都是我干的狰闪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼濒生,長吁一口氣:“原來是場噩夢啊……” “哼埋泵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起罪治,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤丽声,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后觉义,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雁社,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年晒骇,在試婚紗的時候發(fā)現(xiàn)自己被綠了霉撵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡洪囤,死狀恐怖徒坡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘤缩,我是刑警寧澤喇完,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站剥啤,受9級特大地震影響锦溪,放射性物質(zhì)發(fā)生泄漏奄喂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一海洼、第九天 我趴在偏房一處隱蔽的房頂上張望跨新。 院中可真熱鬧,春花似錦坏逢、人聲如沸域帐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肖揣。三九已至,卻和暖如春浮入,著一層夾襖步出監(jiān)牢的瞬間龙优,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工事秀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留彤断,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓易迹,卻偏偏與公主長得像宰衙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睹欲,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容