日常开发中可能很少会用到
spring rest docs
来创建API文档,因为spring boot容易集成的原因,大家可能还是比较倾向于使用swaggerUI文档框架了,spring rest docs有一个好处是需要写单元测试(这个是很多开发人员不愿意的,包括我 -_-),还有个人觉得从界面和展示效果,我还是比较喜欢spring rest docs。在开发中接口文档是必不可少的,至于选择哪一种,就自由选择了。
下面只要是以一个简单的例子来介绍怎么样去使用spring rest docs来生成文档的。
第一步先保证这些依赖引入,至于可以结合spring boot里面是starter来引入,如1.5.12.RELEASE
<properties>
<!--spring restdocs-->
<spring-restdocs.version>1.2.4.RELEASE</spring-restdocs.version>
<!--asciidoctor-->
<asciidoctor-maven-plugin.version>1.5.6</asciidoctor-maven-plugin.version>
</properties>
<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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<version>1.2.4.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>${asciidoctor-maven-plugin.version}</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-asciidoctor</artifactId>
<version>${spring-restdocs.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static/docs</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/generated-docs</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</build>
建一个单元测试类:
import com.google.common.collect.ImmutableMap;
import com.xxx.service.customerservice.CustomerServiceTaskService;
import com.xxx..test.common.BaseTest;
import com.xxx.test.common.Constants;
import org.junit.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.restdocs.payload.JsonFieldType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
/**
* @Date 2019-07-08
*/
public class ControllerTest extends BaseTest {
@MockBean
private CustomerServiceTaskService customerServiceTaskService;
@Test
public void listAvailableLists() throws Exception {
List<Map<String, Object>> campaigns = new ArrayList<>();
Map<String, Object> campaign = new HashMap<>();
campaign.put("campaignId", 1);
campaign.put("campaignName", "活动名称");
campaign.put("remark", "备注信息");
campaigns.add(campaign);
when(this.customerServiceTaskService.listCampaigns(Constants.DEFAULT_V))
.thenReturn(campaigns);
assertGet("/xxxx/xx/listAvailableLists",
ImmutableMap.of("vin", Constants.DEFAULT_V),
document("v2-listAvailableLists",
preprocessResponse(prettyPrint()),
responseFields(
fieldWithPath("code").description("业务码"),
fieldWithPath("msg").optional().type(JsonFieldType.STRING).description("业务描述"),
subsectionWithPath("data").description("数据")
),
responseFields(beneathPath("data").withSubsectionId("data"),
fieldWithPath("[].campaignId").description("ID"),
fieldWithPath("[].campaignName").description("名称"),
fieldWithPath("[].remark").description("备注")
),
requestParameters(
parameterWithName("key").description("参数")
)
)
);
}
}
BaseTest.java
import com.xxx.server.boot.Application;
import com.xxx.test.AbstractMockTest;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
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.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
/**
* @author huangdi1309
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Application.class})
@AutoConfigureMockMvc
@AutoConfigureRestDocs("target/generated-snippets")
@Ignore
public class BaseTest extends AbstractMockTest {
@Autowired
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Override
protected MockMvc getMockMvc() {
return this.mockMvc;
}
}
AbstractMockTest.java
public void assertGet(String api, Map<String, Object> params, RestDocumentationResultHandler document) throws Exception {
this.assertGet(api, params, (HttpHeaders)null, HttpStatus.OK.value(), document);
}
public void assertGet(String api, Map<String, Object> params, int status, RestDocumentationResultHandler document) throws Exception {
this.assertGet(api, params, (HttpHeaders)null, status, document);
}
public void assertGet(String api, Map<String, Object> params, HttpHeaders headers, int status, RestDocumentationResultHandler document) throws Exception {
MockHttpServletRequestBuilder builder = RestDocumentationRequestBuilders.get(api, new Object[0]);
if (params != null) {
builder.params(this.toMulti(params));
}
if (headers != null) {
builder.headers(headers);
}
builder.contentType(MediaType.APPLICATION_JSON_UTF8).accept(new MediaType[]{MediaType.APPLICATION_JSON_UTF8});
ResultActions actions = this.perform(builder);
if (document != null) {
actions.andDo(document);
}
actions.andExpect(MockMvcResultMatchers.status().is(status));
}
在src/main/asciidoc目录下创建index.adoc 内容:
= Management API 文档
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toclevels: 4
:sectlinks:
:numbered:
== API(v2版)
[[v2-listAvailableLists]]
=== 获取xxxxxx接口(/xxx/v2/xxx/listAvailableLists)
operation::v2-listAvailableLists[snippets='request-parameters,http-request,http-response,response-fields,response-fields-data']
[[v2-xxx-listFeedbacks]]
=== 获取事件接口(/xxx/v2/xxx/listFeedbacks)
operation::v2-xxx-listFeedbacks[snippets='request-parameters,http-request,http-response,response-fields,response-fields-data']
[[v2-xxx-listHis]]
=== 获取历史接口(/xxx/v2/xxx/listUpgradeHis)
operation::v2-xxx-listHis[snippets='request-parameters,http-request,http-response,response-fields,response-fields-data']
通过mvnw package命令(也可以通过idea的maven界面操作,我就是这样的)就可以生成文档了。
在/target/generated-docs下有个index.html,打开这个html,显示如下:
版权声明:本文为huangdi1309原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。