Spring REST Docs生成接口文档

介绍

Spring REST Docs官网的介绍如下

restdocs_01

大概意思就是说通过Spring REST Docs是用Asciidoctor编写的手写文档和Spring MVC Test生成的自动生成的代码片段
结合帮助我们生成RESTful服务的接口文档。

与Swagger的对比

如果有使用自动生成接口文档工具的同学,应该对Swagger不陌生。那Spring REST docs跟Swagger有哪些差异?

对比如下:

Spring REST DocsSwagger
代码侵入性零侵入高,
需要往代码内增加@Api、@ApiOperation等注解
易用性较低,
需要先生成代码片段文件后,
再编辑adoc格式的文件进行生成html,
进行查看
高,
直接可生成,无需其他操作
扩展性高,
最终的生成的接口文档界面可自己定义。
界面样式可自定义
较低,
生成的接口界面为固定。无法修改

如何使用

本文以spingboot 2.3.10.RELEASE、Spring REST Docs 2.0.5.RELEASE为例。

新建工程

访问 https://start.spring.io/,新一个spring-rest-docs-demo的工程,并选择添加依赖。
如下图所示,点击GENERATE生成代码。将生成的代码导入IDE内。

restdocs_02

打开pom文件添加FastJson相关jar,后面使用。完整的pom.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.10.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-rest-docs-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-rest-docs-demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.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>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.restdocs</groupId>
			<artifactId>spring-restdocs-mockmvc</artifactId>
			<scope>test</scope>
		</dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.asciidoctor</groupId>
				<artifactId>asciidoctor-maven-plugin</artifactId>
				<version>1.5.8</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>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

编辑接口相关代码

在com.example.demo包下新建controller和vo两个包,然后编写后面用到的vo类。

在vo包下新建AddVo类,代码如下

package com.example.demo.vo;


import javax.validation.constraints.NotNull;

/**
 * @author lijun
 * @Description
 */
public class AddVo {

    @NotNull
    private String data;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }
}

然后controller包下编写接入层IndexController类,并增加GET和POST接口。完整代码如下:

package com.example.demo.controller;

import com.example.demo.vo.AddVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lijun
 * @Description
 * @Date 2021/4/28 16:59
 */
@RestController
public class IndexController {

    @GetMapping("/")
    public Map index(){
        Map m = new HashMap();
        m.put("test","2122");
        return m;
    }

    @PostMapping("/")
    public AddVo add(@RequestBody AddVo vo){
        return vo;
    }
}

编写生成片段测试类

在测试的包下新建一个IndexTest测试类。代码如下:

package com.example.demo;

/**
 * @author lijun
 * @Description
 */

import com.alibaba.fastjson.JSON;
import com.example.demo.vo.AddVo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.restdocs.constraints.ConstraintDescriptions;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.HashMap;
import java.util.Map;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@SpringBootTest(classes = SpringRestDocsDemoApplication.class)
@RunWith(SpringRunner.class)
public class IndexTest {

    @Rule
    public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext context;

    @Before
    public void setUp() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
                .apply(documentationConfiguration(this.restDocumentation))
                .build();
    }

    @Test
    public void index() throws Exception {

        this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andDo(document("{ClassName}/{methodName}"));

    }

    @Test
    public void add() throws Exception {
        ConstraintDescriptions userConstraints = new ConstraintDescriptions(AddVo.class);
        AddVo addVo = new AddVo();
        addVo.setData("测试");
        this.mockMvc.perform(post("/").accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON).content(JSON.toJSONString(addVo)))
                .andExpect(status().isOk())
                .andDo(document("{ClassName}/{methodName}",
                        requestFields(fieldWithPath("data").description(userConstraints.descriptionsForProperty("data")))));
    }
}

我们这边使用了Junit4.x。如果使用Junit5.x请把@Before注解改为@BeforeEach。

其中restDocumentation对象指定了生成的代码片段输出的目录。默认目录为target/generated-snippets,也可以自行更改。

运行IndexTest类后,可以在target/generated-snippets目录下出现相关文件。如下图所示:

restdocs_03

编写asciidoc文件

  • 首先在src/main文件夹下创建一个名称为asciidoc的文件夹,名称固定,不可变。

  • 在asciidoc文件夹下,创建一个名称为index.adoc的文件,该文件名可任意

编辑需要生成的html界面,index.adoc文档的最终内容如下:

= 用 Spring REST Docs 构建文档
:author: lijun
:email: 625995897@qq.com
:revnumber: v1.0
:toc: left
:toc-title: 目录



== 测试GET
.request
include::{snippets}/IndexTest/index/http-request.adoc[]
.request-body说明
include::{snippets}/IndexTest/index/request-body.adoc[]
.response
include::{snippets}/IndexTest/index/http-response.adoc[]

== 测试POST
.request
include::{snippets}/IndexTest/add/http-request.adoc[]
.request-body
include::{snippets}/IndexTest/add/request-body.adoc[]
.request-body说明
include::{snippets}/IndexTest/add/request-fields.adoc[]
.response
include::{snippets}/IndexTest/add/http-response.adoc[]

相关asciidoc语法参考地址
官网手册链接地址:https://asciidoctor.org/docs/user-manual
asciidoctor基础语法:https://blog.youkuaiyun.com/jioujiou520/article/details/90613175

生成接口html

打开控制台。切换到工程目录。执行如下命令

mvn package -Dmaven.test.skip=true

每一个xxx.adoc,最终都会生成xxx.html 存放在/target/generated-doc文件夹中,同时也会存放在/target/classes/static/docs文件中,以便访问

打开/target/generated-doc/index.html可查看生成的接口文档。如下图所示:

restdocs_04

完!!!

欢迎扫描下图关注公众号 IT李哥,公众号经常推送一些优质的技术文章

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值