SpringBoot非官方教程 | 第十篇: 用Spring Restdocs创建API文档

news/2025/3/22 1:19:18

准备工作

你需要15min
Jdk 1.8
maven 3.0+
idea

创建工程

引入依赖,其pom文件:

<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><scope>test</scope></dependency>
</dependencies>

通过@SpringBootApplication,开启springboot

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

在springboot通常创建一个controller:

@RestController
public class HomeController {@GetMapping("/")public Map<String, Object> greeting() {return Collections.singletonMap("message", "Hello World");}}

启动工程,访问localhost:8080,浏览器显示:

{“message”:”Hello World”}

证明接口已经写好了,但是如何通过restdoc生存api文档呢

Restdoc,通过单元测试生成api文档

restdocs是通过单元测试生存snippets文件,然后snippets根据插件生成htm文档的。

建一个单元测试类:

@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")
public class WebLayerTest {@Autowiredprivate MockMvc mockMvc;@Testpublic void shouldReturnDefaultMessage() throws Exception {this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk()).andExpect(content().string(containsString("Hello World"))).andDo(document("home"));}
}

其中,@ AutoConfigureRestDocs注解开启了生成snippets文件,并指定了存放位置。

启动单元测试,测试通过,你会发现在target文件下生成了一个snippets文件夹,其目录结构如下:

└── target└── snippets└── home└── httpie-request.adoc└── curl-request.adoc└── http-request.adoc└── http-response.adoc

默认情况下,snippets是Asciidoctor格式的文件,包括request和reponse,另外其他两种httpie和curl两种流行的命令行的http请求模式。

到目前为止,只生成了Snippets文件,需要用Snippets文件生成文档。

怎么用Snippets

创建一个新文件src/main/asciidoc/index.adoc :

用 Spring REST Docs 构建文档

This is an example output for a service running at http://localhost:8080:.request
include::{snippets}/home/http-request.adoc[].response
include::{snippets}/home/http-response.adoc[]

这个例子非常简单,通过单元测试和一些简单的配置就能够得到api文档了。

adoc的书写格式,参考:http://docs.spring.io/spring-...,这里不多讲解。

需要使用asciidoctor-maven-plugin插件,在其pom文件加上:

<plugin><groupId>org.asciidoctor</groupId><artifactId>asciidoctor-maven-plugin</artifactId><executions><execution><id>generate-docs</id><phase>prepare-package</phase><goals><goal>process-asciidoc</goal></goals><configuration><sourceDocumentName>index.adoc</sourceDocumentName><backend>html</backend><attributes><snippets>${project.build.directory}/snippets</snippets></attributes></configuration></execution></executions>
</plugin>

这时只需要通过mvnw package命令就可以生成文档了。
在/target/generated-docs下有个index.html,打开这个html,显示如下,界面还算简洁:

clipboard.png

结语

通过单元测试,生存adoc文件,再用adoc文件生存html,只需要简单的几步就可以生成一个api文档的html文件,这个html文件你可以通网站发布出去。整个过程很简单,对代码无任何影响。

源码下载:https://github.com/forezp/Spr...

参考资料

restdocs

http://docs.spring.io/spring-...


https://dhexx.cn/news/show-442720.html

相关文章

javascript的数组之splice()

splice()方法通过删除现有元素和/或添加新元素来更改一个数组的内容。修改数组自身 1 var months [Jan, March, April, June];2 months.splice(1, 0, Feb);3 // inserts at 1st index position4 console.log(months);5 // expected output: Array [Jan, Feb, March, April, Ju…

剑指offer第二版面试题11:旋转数组的最小数字(java)

题目描述&#xff1a; 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个递增排序的数组的一个旋转&#xff0c;输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转&#xff0c;该数组的最小值为1。 解题思路&#x…

iOS自动布局的学习

Autolayout&#xff1a; 最重要的两个概念&#xff1a; 约束&#xff1a;对控件位置和大小的限定条件参照&#xff1a;对控件设置的约束是相对于哪一个视图而言的自动布局的核心计算公式&#xff1a; obj1.property1 &#xff08;obj2.property2 * multiplier&#xff09; cons…

Python 学习笔记: 迭代器和生成器

迭代器 迭代器遵循迭代器协议&#xff1a;必须拥有__iter__方法和__next__方法。 list1 [1,2,3,4,5] it list1.__iter__() it 就是个迭代器。 it.__next()__ 输出 1 it.__next()__ 输出 2 .。。。。。等等&#xff0c; 每次输出1个值。 生成器 生成器函数&#xff1a; 一个包…

javascript判断一个对象是否为数组

在JavaScript中&#xff0c;可以通过typeof操作符来判断基本数据类型(Undefined、Null、Boolean、Number和String)&#xff0c;同时相信大家也熟知typeof对于对象的判断是不准确的&#xff0c;因为特殊值Null被认为是一个空的对象的引用。 对于数组的创建&#xff0c;可以使用构…

BZOJ1509: [NOI2003]逃学的小孩 (树形DP)

题意:给一棵树 选三个点A,B,C 求A到B的再从B到C的距离最大值 需要满足AB的距离小于AC的距离 题解:首先树上的最大距离就想到了直径 但是被样例误导了TAT BC两点构成了直径 我一开始以为A在直径上答案最大 然后再加上最接近路径长度一半的路径 其实 A不在直径上的话显然更优啊..…

剑指offer第二版面试题12:矩阵中的路径(java)

问题描述&#xff1a; 请设计一个函数&#xff0c;用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始&#xff0c;每一步可以在矩阵中向左&#xff0c;向右&#xff0c;向上&#xff0c;向下移动一个格子。如果一条路径经过了…

对接门禁分享门禁二维码图片报错

咳咳&#xff0c;好久没更新博客了&#xff0c;身为一个ios程序员&#xff0c;懒成这样&#xff0c;真的是无药可救。这一年遇的坑解决了也没发上博客&#xff0c;真是耻辱啊。但是&#xff0c;今天这个通过友盟分享图片分享不出去的这个坑埋完后一定要发出来&#xff0c;免得后…

第五章 【BX】和loop指令

完整描述一个内存单元的条件&#xff1a;①内存单元的地址。②内存单元的长度。 用符号“&#xff08;&#xff09;”来表示一个寄存器或一个内存单元中的内容。eg:(ax)、(al)。“&#xff08;&#xff09;”中表示的数据有两种&#xff1a;①字节&#xff1b;②字。是哪种类型…

Java网络编程之TCP粘包拆包

TCP是个“流”协议&#xff0c;所谓流&#xff0c;就是没有界限的一串数据。大家可以想象河里的流水&#xff0c;他们是连成一片的&#xff0c;其间并没有分界线。TCP底层并不了解上层业务数据的具体含义&#xff0c;他会根据TCP缓冲区的实际情况进行包的划分&#xff0c;所以在…