本人所在的項目團隊分為前端開發(fā)和后端開發(fā)兩個子小組,前后端通過RESTfull API通信弧岳,過去一般都要用word來寫API文檔,隨著需求的變化和開發(fā)的深入,往往還要多次更新API文檔簇捍,這會給開發(fā)人員增加不少工作量。最近俏拱,項目組引入了Springfox和Spring Rest Docs來自動生成文檔暑塑,本文做個記錄。
1.預(yù)備知識
建議了解swagger锅必、Asciidoc事格、asciidoctor-maven-plugin和SpringBoot 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自動生成文檔么鹤。
最終目標是為我們的項目生成如下形式的文檔:
Spring Rest Docs:Document 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é)果如圖:
生成完整的Asciidoc文檔用到了Swagger2MarkupConverter点把,第一步先獲取在線版本的文檔并保存到文件swagger.json中,第二步把swagger.json和之前的例子snippets整合并保存為Asciidoc格式的完整文檔屿附。生成結(jié)果如圖:
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