Spring REST Docs 帮助你管理 RESTful 服务文档,使用 Asciidoctor 来编写文档,使用 Spring MVC Test 自动生成片段。
编程界的大家应该都有听说过restful风格能够提高项目的性能,而且现在到处都在说我们的项目是rest风格的,那么什么是rest风格呢?简单来举个例子 大家就能懂啦: 比如说现在有这样一个url: https://www.oschina.net/news/66853/spring-rest-docs-1-0-0 这里的66853可能是一个专用的id或者其他相关的映射,我们从这里是不能知道它到底指的是什么。 而如果是非restful风格的url则会是这样: https://www.oschina.net/news/uid?userUid=66853/spring-rest-docs-1-0-0 XXX?XXX= XXX这样大家都能猜出来的url,后来加密之后发送到后台,然后就出现了所谓的rest比较流行。
例子:SpringBoot工程,将http接口通过API文档暴露出来,只需要通过JUnit单元测试和spring的MockMVC就可以生成文档。 SpringRestDoc框架通过测试来生成REST接口的说明文档:可以对参数和返回值进行简单的说明,还能产生url和返回用例,通过单元测试,和目前的moxkMVC框架相结合,可以产生Asciidoctor文档片段。 缺点:目前只能生成片段,继承一整个API文档的话还需要手动去写。当然测试的越多,文档的内容就越详细。 解决方案:这里的只能产生片段文章,不能自动整合成一整个文档的缺点,可以使用我上一篇介绍的swagger去解决。swagger具有较强的能力和自信能做好这件事情 ,你就放心交给它好了。
软件:idea jdk:1.8 maven:3.0+
restdoc是通过单元测试生成snippets文件,然后snippets根据插件生成html文档 在测试类中的设置: (1)
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");(2) Then 在@before方法中配置MockMVC或者REST assured:
Setting up your JUnit tests
private MockMvc mockMvc; @Autowired private WebApplicationContext context; @Before public void setUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) .apply(documentationConfiguration(this.restDocumentation)) .build(); }MockMvc实例是使用一个配置MockMvcRestDocumentationConfigurer来配置的。这个类的一个实例可以是从org.springframework.restdocs.mockmvc.MockMvcRestDocumentation中的静态documentationConfiguration()方法获得。
Setting up your tests without JUnit 与上面不同的是不需要@Rule,并且换成了JUnitRestDocumentation
private ManualRestDocumentation restDocumentation = new ManualRestDocumentation("target/generated-snippets");同样的,setup()方法中MockMVC的设置将变成这样:
private MockMvc mockMvc; @Autowired private WebApplicationContext context; @BeforeMethod public void setUp(Method method) { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) .apply(documentationConfiguration(this.restDocumentation)) .build(); this.restDocumentation.beforeTest(getClass(), method.getName()); }但是在每个测试之后ManualRestDocumentation.afterTest()方法都将被调用一次:
@AfterMethod public void tearDown() { this.restDocumentation.afterTest(); }the testing framework被配置好之后,它就可以尝试去集成RESTful服务了,针对其中的请求和回复进行相应详细的说明。 举个栗子:(kotlin
@Resource private lateinit var context: WebApplicationContext private lateinit var mockMvc: MockMvc //设置测试片段生成文件夹的位置 @Rule @JvmField var restDocumentation = JUnitRestDocumentation("target/asciidoc/snippets") @Before fun setUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(context) .apply<DefaultMockMvcBuilder>(documentationConfiguration(this.restDocumentation)) .build() } @Test fun create() { val parentId = "sssssssssss" val request = post("/groups/$parent") this.mockMvc.perform(request) .andException(status.isCreated) .andDo(print()) .andDo(document("{methodName}", preprocessRequest(prettyPrint()))) }举个Spring REST Docs的官方文档中的例子:(java) 我们可以在andDo()中添加一些对参数的具体描述:
this.mockMvc.perform(get("/locations/{latitude}/{longitude}", 51.5072,0.1275)) .andExpect(status().isOk()) .andDo(document("locations", pathParameters(parameterWithName("latitude").description("The location's latitude"),parameterWithName("longitude").description("The location's longitude") )));关于这些Spring REST Docs的官方文档中对参数的具体描述的一些用法我就不详细赘述了,因为这个很显然,代码上看起来不整齐,此时也已经有更好的东西代替它了,所以我们直接学习更好的解决“为属性和回复消息进行详细说明”的问题的解决方案就好啦~
以上是在SpringRESTDocs的官方文档中学习到的知识,做以简单的总结。
【那么有什么好的解决方案呢?】 就是我上一篇文章提到的springfox-swagger,它是一个能力的强者,为什么呢?话不多说,举个简单的栗子: 使用springfox-swagger这个框架的时候,我们是把api的详细注释都添加在Controller层的各个类中: (kotlin)当然啦,想使用下面这段代码的模式,就需要配置集成springfox-swagger在你的项目中。(SpringBoot+SpringDataJPA+SpringFramework+Springfox-swagger)
@RestController @Api(value = "User", description = "the chapter of user") @RequestMapping("/users", produces = arrayOf(MediaType.APPLICATION_JSON_UTF8_VALUE)) class ItemController { @ApiOperation(value = "createUser", notes = "创建一个user") @ApiImplicitParams( ApiImplicitParam(name = "Name", value = "用户名", paramType = "path", required = true, dataType = "String"), ApiImplicitParam(name = "age", value = "用户的年龄", paramType = "path", required = true, dataType = "Int") ) @ApiResponses( ApiResponse(code = 200, message = "创建成功", response = User::class), ApiResponse(code = 404, message = "没有找到", response = Void::class) ) @PostMapping("{name}/age/{age}", consumes = arrayOf(MediaType.APPLICATION_JSON_UTF8_VALUE)) fun create(@PathVariable("name") userName: String, @PathVariable("age") userAge: Int): ResponseEntity<Any> { //此处实现的代码省略 //...... return user } }关于Api的一些简单的注解,都在上一篇中有描述。
总结: (1)springRESTDocs主要是用来在测试的时候生成测试代码片段,并且在测试片段中添加一些简单的说明; (2)swagger主要是用来提供测试界面,并整合生成API接口文档; (3)MockMVC是一个属于spring MVC的测试框架,基于Restful风格的SpringMVC的测试,可以测试完成的流程。关于MockMVC的相关信息可以查看网址:http://www.cnblogs.com/lyy-2016/p/6122144.html他写的很棒,也可以看我之前写的博客。
下面 举一个完整的例子,结合springBoot+SpringDataJPA+SpringMVC+MockMVC+SpringRESTDocs+Springfox-swagger,完成生成一个具体的详细的API接口文档。
mavne会自动下载你所需要的jar包
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <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>这里的@Configuration注解,让spring加载配置,@EnableSwagger2启用Swagger2 再通过createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)。
在单元测试的时候,SpringRestDocs会生成一些代码片段,这里就是将片段整合先生成一个json文件,再转换格式的过程。
其中.apply(documentationConfiguration(this.restDocumentation))就是将MockMVC和SpringRestDocs结合在一起。 @Rule 表示当前是在Junit测试环境下的测试
@Test fun create() { val json = """ { "userName" : "userName", "age" : "24" } """ val request = post("/users") .contentType("{生产类型}") .content(json) .accept("{消费类型}") this.mockMvc.perform(request) .andExpect(status().isCreated) .andDo(print()) .andDo(document("createUser", preprocessResponse(prettyPrint()))) }这里的andDo()之类的用法 ,我在之前的文章中都有讲过。这些都是用来模拟一个Mockmvc的请求。 这里的.andDo(document(“createUser”, preprocessResponse(prettyPrint())))是属于SpringRestDocs在生成的测试代码片段中加的一些简单的注释
这里所有的api注解,在单元测试完成之后,运行Swagger2的test,都能被整合到api接口文档中。其他的就不再赘述了。
over啦~ 待完善revision