Guidance:
Interface documentation is often used when working together as a team. Often we write a lot of documents in repetitive formats by hand, which reminds me of two things programmers hate most: writing documents without them.Ha-ha, if you've used swagger, your friends should know all about its convenience. If you haven't used swagger yet, you're just about to write a RESTful API document. Here's an article Build a powerful RESTful API document using Swagger2 in Spring Boot It can help you build an online document in a short time. Sometimes we need to generate an offline document. What can we do?Let's go with this question.
About swagger:
Swagger - Front End Separated Contract
API design via Swagger, a conversation with Tony Tam
A short summary to better generate the RESTful API documentation and provide the appropriate testing capabilities as follows:
Write offline documentation:
Swagger provides us with the ability to generate online documents, but sometimes customers need an api for offline documents. Is there a better way to help us generate offline documents through swagger?
That's what we're doing today: Springfox and Spring Rest Docs
1. Preparatory knowledge:
It is recommended that you know swagger, Asciidoc, asciidoctor-maven-plugin, and SpringBoot Testing.The corresponding information can be Google by itself.
2. About Springfox and Spring Rest Docs:
The official website is Springfox: Automated JSON API documentation for API's built with Spring.We can understand that documents are automatically generated for SPI built on Spring.
Introducing pom dependency:
In fact, our idea is to convert swagger online documents into staticdocs, introduce some related Spring Rest Docs dependent spring-restdocs-mockmvc, offline documents dependent springfox-staticdocs, because to generate documents when unit testing, then test the related spring-boot-starter-test.
<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>
Using the Maven plug-in:
We use the asciidoctor-maven-plugin plugin to convert the Asciidoc format to HTML5 format
Learn more about: Introduction to Use
<plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <configuration> <!--To configure index.adoc Get Path for--> <!--<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>
Write test classes to generate offline documentation:
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 { // Get swagger.json and write to the output Dir directory mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON)) .andDo(SwaggerResultHandler.outputDirectory(outputDir).build()) .andExpect(status().isOk()) .andReturn(); // Read the swagger.json generated in the previous step, convert it to asciiDoc, and write it to outputDir // This outputDir must match the <generated></generated>tag configuration within the plug-in Swagger2MarkupConverter.from(outputDir + "/swagger.json") .withPathsGroupedBy(GroupBy.TAGS)// Sort by tag .withMarkupLanguage(MarkupLanguage.ASCIIDOC)// format .withExamples(snippetDir) .build() .intoFolder(outputDir);// output } @Test public void TestApi() throws Exception { mockMvc.perform(get("/api/user/1") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(MockMvcRestDocumentation.document("Query Users", preprocessResponse(prettyPrint()))); UserInfo userInfo = new UserInfo(); userInfo.setName("lisi"); userInfo.setAge(23); userInfo.setAddress("Jinan"); userInfo.setSex("male"); mockMvc.perform(post("/api/user").contentType(MediaType.APPLICATION_JSON) .content(JSON.toJSONString(userInfo)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()) .andDo(MockMvcRestDocumentation.document("New Users", preprocessResponse(prettyPrint()))); } }
Since maven's plug-in has been configured previously, you only need to execute tests to generate the appropriate documentation, as shown below:
Supplement:
Swagger configuration:
@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(); } }
Related source is managed github
Reference material:
SpringBoot project generates documentation for RESTfull API