通过将手写文档与使用 Spring MVC Test、WebTestClient 或 REST Assured 生成的自动生成的片段相结合,记录 RESTful 服务。

介绍

Spring REST Docs 的目的是帮助您为您的 RESTful 服务生成准确且可读的文档。

编写高质量的文档很困难。缓解这种困难的一种方法是使用非常适合这项工作的工具。为此,Spring REST Docs 默认使用Asciidoctor。Asciidoctor 处理纯文本并生成 HTML,其样式和布局可满足您的需求。如果您愿意,还可以将 Spring REST Docs 配置为使用 Markdown。

Spring REST Docs 使用由 Spring MVC 的测试框架、Spring WebFluxWebTestClientREST Assured 3编写的测试生成的片段。这种测试驱动的方法有助于保证服务文档的准确性。如果片段不正确,则生成它的测试会失败。

记录一个 RESTful 服务主要是描述它的资源。每个资源描述的两个关键部分是它使用的 HTTP 请求的详细信息和它产生的 HTTP 响应。Spring REST Docs 允许您使用这些资源以及 HTTP 请求和响应,从而使您的文档免受服务实现的内部细节的影响。这种分离有助于您记录服务的 API,而不是其实现。它还使您可以自由地改进实现,而无需重新编写文档。

入门

本节介绍如何开始使用 Spring REST 文档。

示例应用程序

如果您想直接进入,可以使用许多示例应用程序:

表 1. MockMvc
样本 构建系统 描述

Spring数据休息

Maven

演示为使用Spring Data REST实现的服务创建入门指南和 API 指南。

Spring仇恨

Gradle

演示为使用Spring HATEOAS实现的服务创建入门指南和 API 指南。

表 2. WebTestClient
样本 构建系统 描述

WebTestClient

Gradle

演示 Spring REST 文档与 Spring WebFlux 的 WebTestClient 的使用。

表 3. REST 保证
样本 构建系统 描述

REST Assured

Gradle

演示 Spring REST Docs 与REST Assured的使用。

表 4. 高级
样本 构建系统 描述

石板

Gradle

演示 Spring REST Docs 与 Markdown 和 Slate的使用。

测试NG

Gradle

演示 Spring REST Docs 与TestNG的使用。

JUnit 5

Gradle

演示 Spring REST Docs 与JUnit 5的使用。

要求

Spring REST Docs 具有以下最低要求:

  • java 8

  • Spring Framework 5(5.0.2 或更高版本)

此外,该spring-restdocs-restassured模块需要 REST Assured 3.0。

构建配置

使用 Spring REST Docs 的第一步是配置项目的构建。Spring HATEOAS和Spring Data REST示例分别包含一个build.gradlepom.xml,您可能希望将其用作参考。以下清单中描述了配置的关键部分:

plugins { (1)
	id "org.asciidoctor.jvm.convert" version "3.3.2"
}

configurations {
	asciidoctorExt (2)
}

dependencies {
	asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor:{project-version}' (3)
	testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc:{project-version}' (4)
}

ext { (5)
	snippetsDir = file('build/generated-snippets')
}

test { (6)
	outputs.dir snippetsDir
}

asciidoctor { (7)
	inputs.dir snippetsDir (8)
	configurations 'asciidoctorExt' (9)
	dependsOn test (10)
}
1 应用 Asciidoctor 插件。
2 声明asciidoctorExt扩展 Asciidoctor 的依赖项的配置。
3 spring-restdocs-asciidoctorasciidoctorExt配置中添加依赖项。这将自动配置snippets属性以在您的.adoc文件中使用以指向build/generated-snippets. 它还允许您使用operation块宏。
4 spring-restdocs-mockmvctestImplementation配置中添加依赖项。如果您想使用REST Assured 而不是 MockMvc,请分别添加对orWebTestClient的依赖项。spring-restdocs-webtestclientspring-restdocs-restassured
5 配置一个属性来定义生成的片段的输出位置。
6 配置test任务以添加片段目录作为输出。
7 配置asciidoctor任务。
8 将片段目录配置为输入。
9 配置asciidoctorExt扩展的配置使用。
10 使任务依赖于测试任务,以便在创建文档之前运行测试。

打包文档

您可能希望将生成的文档打包到项目的 jar 文件中——例如,让 Spring Boot 将其作为静态内容。为此,请配置项目的构建,以便:

  1. 在构建 jar 之前生成文档

  2. 生成的文档包含在 jar 中

以下清单显示了如何在 Maven 和 Gradle 中执行此操作:

bootJar {
	dependsOn asciidoctor (1)
	from ("${asciidoctor.outputDir}/html5") { (2)
		into 'static/docs'
	}
}
1 确保在构建 jar 之前已经生成了文档。
2 将生成的文档复制到 jar 的static/docs目录中。

生成文档片段

Spring REST Docs 使用 Spring MVC 的测试框架、Spring WebFluxWebTestClientREST Assured向您正在记录的服务发出请求。然后它为请求和结果响应生成文档片段。

设置你的测试

究竟如何设置测试取决于您使用的测试框架。Spring REST Docs 为 JUnit 4 和 JUnit 5 提供一流的支持。其他框架,例如 TestNG,也受支持,但需要进行更多设置。

设置您的 JUnit 4 测试

使用 JUnit 4 时,生成文档片段的第一步是声明一个public JUnitRestDocumentation被注释为 JUnit 的字段@Rule。以下示例显示了如何执行此操作:

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();

默认情况下,JUnitRestDocumentation规则会根据项目的构建工具自动配置输出目录:

构建工具 输出目录

Maven

target/generated-snippets

Gradle

build/generated-snippets

您可以通过在创建JUnitRestDocumentation实例时提供输出目录来覆盖默认值。以下示例显示了如何执行此操作:

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("custom");

接下来,您必须提供一种@Before方法来配置 MockMvc、WebTestClient 或 REST Assured。以下示例显示了如何执行此操作:

private RequestSpecification spec;

@Before
public void setUp() {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(this.restDocumentation)) (1)
			.build();
}
1 REST Assured 是通过将 a 添加RestAssuredRestDocumentationConfigurerFilter. 您可以从包中的静态documentationConfiguration()方法获取此类的实例。RestAssuredRestDocumentationorg.springframework.restdocs.restassured3

配置器应用合理的默认值,并提供用于自定义配置的 API。有关详细信息,请参阅配置部分

设置您的 JUnit 5 测试

使用 JUnit 5 时,生成文档片段的第一步是将其RestDocumentationExtension应用于您的测试类。以下示例显示了如何执行此操作:

@ExtendWith(RestDocumentationExtension.class)
public class JUnit5ExampleTests {

在测试典型的 Spring 应用程序时,您还应该应用SpringExtension

@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
public class JUnit5ExampleTests {

会根据RestDocumentationExtension项目的构建工具自动配置输出目录:

构建工具 输出目录

Maven

target/generated-snippets

Gradle

build/generated-snippets

如果您使用的是 JUnit 5.1,则可以通过将扩展注册为测试类中的字段并在创建时提供输出目录来覆盖默认值。以下示例显示了如何执行此操作:

public class JUnit5ExampleTests {

	@RegisterExtension
	final RestDocumentationExtension restDocumentation = new RestDocumentationExtension ("custom");

}

接下来,您必须提供一种@BeforeEach方法来配置 MockMvc、WebTestClient 或 REST Assured。以下清单显示了如何执行此操作:

private RequestSpecification spec;

@BeforeEach
public void setUp(RestDocumentationContextProvider restDocumentation) {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(restDocumentation)) (1)
			.build();
}
1 REST Assured 是通过将 a 添加RestAssuredRestDocumentationConfigurerFilter. 您可以从包中的静态documentationConfiguration()方法获取此类的实例。RestAssuredRestDocumentationorg.springframework.restdocs.restassured3

配置器应用合理的默认值,并提供用于自定义配置的 API。有关详细信息,请参阅配置部分

在没有 JUnit 的情况下设置测试

不使用 JUnit 时的配置与使用时的配置非常相似。本节介绍主要区别。TestNG 示例也说明了这种方法。

第一个区别是您应该使用ManualRestDocumentation. JUnitRestDocumentation此外,您不需要@Rule注释。下面的例子展示了如何使用ManualRestDocumentation

private ManualRestDocumentation restDocumentation = new ManualRestDocumentation();

其次,你必须ManualRestDocumentation.beforeTest(Class, String)在每次测试前打电话。作为配置 MockMvc、WebTestClient 或 REST Assured 的方法的一部分,您可以这样做。以下示例显示了如何执行此操作:

private RequestSpecification spec;

@BeforeMethod
public void setUp(Method method) {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(this.restDocumentation)).build();
	this.restDocumentation.beforeTest(getClass(), method.getName());
}

最后,您必须ManualRestDocumentation.afterTest在每次测试后致电。以下示例显示了如何使用 TestNG 执行此操作:

@AfterMethod
public void tearDown() {
	this.restDocumentation.afterTest();
}

调用 RESTful 服务

现在您已经配置了测试框架,您可以使用它来调用 RESTful 服务并记录请求和响应。以下示例显示了如何执行此操作:

RestAssured.given(this.spec) (1)
		.accept("application/json") (2)
		.filter(document("index")) (3)
		.when().get("/") (4)
		.then().assertThat().statusCode(is(200)); (5)
1 应用在@Before方法中初始化的规范。
2 表示需要application/json响应。
3 记录对服务的调用,将代码片段写入名为index(位于配置的输出目录下方)的目录中。片段由RestDocumentationFilter. 您可以从包中的静态document方法获取此类的实例。RestAssuredRestDocumentationorg.springframework.restdocs.restassured3
4 调用服务的根 ( /)。
5 断言服务产生预期的响应。

默认情况下,会写入六个片段:

  • <output-directory>/index/curl-request.adoc

  • <output-directory>/index/http-request.adoc

  • <output-directory>/index/http-response.adoc

  • <output-directory>/index/httpie-request.adoc

  • <output-directory>/index/request-body.adoc

  • <output-directory>/index/response-body.adoc

有关Spring REST Docs 生成的这些和其他片段的更多信息,请参阅记录您的 API 。

使用片段

在使用生成的代码片段之前,您必须创建一个.adoc源文件。只要文件有.adoc后缀,您就可以随意命名文件。生成的 HTML 文件具有相同的名称但带有.html后缀。源文件和生成的 HTML 文件的默认位置取决于您使用的是 Maven 还是 Gradle:

构建工具 源文件 生成的文件

Maven

src/main/asciidoc/*.adoc

target/generated-docs/*.html

Gradle

src/docs/asciidoc/*.adoc

build/asciidoc/html5/*.html

然后,您可以使用include 宏将生成的片段包含在手动创建的 Asciidoc 文件(本节前面描述)中。您可以使用构建配置中配置的snippets自动设置的属性来引用片段输出目录。以下示例显示了如何执行此操作:spring-restdocs-asciidoctor

include::{snippets}/index/curl-request.adoc[]

记录您的 API

本节提供有关使用 Spring REST Docs 记录您的 API 的更多详细信息。

超媒体

Spring REST Docs 支持在基于超媒体的API 中记录链接。以下示例显示了如何使用它:

RestAssured.given(this.spec).accept("application/json").filter(document("index", links((1)
		linkWithRel("alpha").description("Link to the alpha resource"), (2)
		linkWithRel("bravo").description("Link to the bravo resource")))) (3)
		.get("/").then().assertThat().statusCode(is(200));
1 配置 Spring REST 文档以生成描述响应链接的片段。对 使用静态links方法org.springframework.restdocs.hypermedia.HypermediaDocumentation
2 期待一个链接,其relalpha. 对 使用静态linkWithRel方法org.springframework.restdocs.hypermedia.HypermediaDocumentation
3 期待一个链接,其relbravo.

结果是一个名为的片段links.adoc,其中包含一个描述资源链接的表。

如果响应中的链接有title,则可以省略其描述符中的描述并title使用 。如果您省略描述并且链接没有title,则会发生故障。

记录链接时,如果在响应中找到未记录的链接,则测试失败。同样,如果在响应中未找到记录的链接并且该链接未标记为可选,则测试也会失败。

如果您不想记录链接,可以将其标记为已忽略。这样做可以防止它出现在生成的代码段中,同时避免上述失败。

您还可以在宽松模式下记录链接,其中任何未记录的链接都不会导致测试失败。为此,请使用 上的relaxedLinks方法org.springframework.restdocs.hypermedia.HypermediaDocumentation。在记录您只想关注链接子集的特定场景时,这可能很有用。

默认理解两种链接格式:

  • Atom:链接应该在一个名为links. 当响应的内容类型与 兼容时,默认使用此选项application/json

  • HAL:链接应位于名为_links. 当响应的内容类型与 兼容时,默认使用此选项application/hal+json

如果您使用 Atom 或 HAL 格式的链接,但具有不同的内容类型,您可以LinkExtractorlinks. 以下示例显示了如何执行此操作:

.filter(document("index", links(halLinks(), (1)
		linkWithRel("alpha").description("Link to the alpha resource"),
		linkWithRel("bravo").description("Link to the bravo resource"))))
1 指示链接为 HAL 格式。对 使用静态halLinks方法org.springframework.restdocs.hypermedia.HypermediaDocumentation

如果您的 API 以 Atom 或 HAL 以外的格式表示其链接,您可以提供自己的LinkExtractor接口实现以从响应中提取链接。

您可能希望在概述部分中记录一次,然后在 API 的其余文档中忽略它们,而不是记录每个响应共有的链接(例如使用 HALself时)。curies为此,您可以在对重用片段的支持的基础上,将链接描述符添加到预先配置为忽略某些链接的片段中。以下示例显示了如何执行此操作:

public static LinksSnippet links(LinkDescriptor... descriptors) {
	return HypermediaDocumentation.links(linkWithRel("self").ignored().optional(), linkWithRel("curies").ignored())
			.and(descriptors);
}

请求和响应负载

除了前面描述的特定于超媒体的支持之外,还提供了对请求和响应负载的一般文档的支持。

默认情况下,Spring REST Docs 会自动为请求正文和响应正文生成片段。这些片段分别被命名request-body.adoc和命名response-body.adoc

请求和响应字段

为了提供请求或响应负载的更详细文档,提供了对记录负载字段的支持。

考虑以下有效负载:

{
	"contact": {
		"name": "Jane Doe",
		"email": "jane.doe@example.com"
	}
}

您可以按如下方式记录上一个示例的字段:

RestAssured.given(this.spec).accept("application/json").filter(document("user", responseFields((1)
		fieldWithPath("contact.name").description("The user's name"), (2)
		fieldWithPath("contact.email").description("The user's email address")))) (3)
		.when().get("/user/5").then().assertThat().statusCode(is(200));
1 配置 Spring REST 文档以生成描述响应负载中的字段的片段。要记录请求,您可以使用requestFields. 两者都是org.springframework.restdocs.payload.PayloadDocumentation.
2 期望一个带有路径的字段contact.email。对 使用静态fieldWithPath方法org.springframework.restdocs.payload.PayloadDocumentation
3 期望一个带有路径的字段contact.name

结果是一个片段,其中包含一个描述字段的表。对于请求,此代码段名为request-fields.adoc. 对于响应,此代码段名为response-fields.adoc.

记录字段时,如果在有效负载中找到未记录的字段,则测试失败。同样,如果在有效负载中找不到记录的字段并且该字段未标记为可选,则测试也会失败。

如果您不想为所有字段提供详细文档,则可以记录有效负载的整个子部分。以下示例显示了如何执行此操作:

RestAssured.given(this.spec).accept("application/json")
		.filter(document("user",
				responseFields(subsectionWithPath("contact").description("The user's contact details")))) (1)
		.when().get("/user/5").then().assertThat().statusCode(is(200));
1 用路径记录小节contactcontact.email并且contact.name现在被视为也已记录在案。对 使用静态subsectionWithPath方法org.springframework.restdocs.payload.PayloadDocumentation

subsectionWithPath对于提供有效载荷的特定部分的高级概述非常有用。然后,您可以为小节生成单独的、更详细的文档。请参阅记录请求或响应负载的子部分

如果您根本不想记录某个字段或小节,可以将其标记为已忽略。这可以防止它出现在生成的代码段中,同时避免前面描述的失败。

您还可以在宽松模式下记录字段,其中任何未记录的字段都不会导致测试失败。为此,请使用relaxedRequestFieldsrelaxedResponseFields方法org.springframework.restdocs.payload.PayloadDocumentation。在记录您只想关注有效负载子集的特定场景时,这可能很有用。

默认情况下,Spring REST Docs 假定您记录的有效负载是 JSON。如果要记录 XML 有效负载,请求或响应的内容类型必须与application/xml.
JSON 负载中的字段

本节介绍如何使用 JSON 有效负载中的字段。

JSON 字段路径

JSON 字段路径使用点表示法或方括号表示法。点符号使用 '.' 分隔路径中的每个键(例如,a.b)。方括号表示法将每个键括在方括号和单引号中(例如,['a']['b'])。在任何一种情况下,[]都用于标识一个数组。点表示法更简洁,但使用括号表示法可以.在键名中使用 (例如,['a.b'])。这两种不同的符号可以用在同一个路径中(例如,a['b'])。

考虑以下 JSON 有效负载:

{
	"a":{
		"b":[
			{
				"c":"one"
			},
			{
				"c":"two"
			},
			{
				"d":"three"
			}
		],
		"e.dot" : "four"
	}
}

在前面的 JSON 负载中,都存在以下路径:

小路 价值

a

一个对象包含b

a.b

包含三个对象的数组

['a']['b']

包含三个对象的数组

a['b']

包含三个对象的数组

['a'].b

包含三个对象的数组

a.b[]

包含三个对象的数组

a.b[].c

包含字符串的数组onetwo

a.b[].d

字符串three

a['e.dot']

字符串four

['a']['e.dot']

字符串four

您还可以记录在其根目录中使用数组的有效负载。路径[]指的是整个数组。然后,您可以使用括号或点符号来标识数组条目中的字段。例如,[].id对应id于在以下数组中找到的每个对象的字段:

[
	{
		"id":1
	},
	{
		"id":2
	}
]

您可以*用作通配符来匹配具有不同名称的字段。例如,users.*.role可用于在以下 JSON 中记录每个用户的角色:

{
	"users":{
		"ab12cd34":{
			"role": "Administrator"
		},
		"12ab34cd":{
			"role": "Guest"
		}
	}
}
JSON 字段类型

当一个字段被记录时,Spring REST Docs 尝试通过检查有效负载来确定它的类型。支持七种不同的类型:

类型 描述

array

每次出现该字段的值都是一个数组。

boolean

每次出现该字段的值都是一个布尔值(truefalse)。

object

字段每次出现的值都是一个对象。

number

该字段每次出现的值都是一个数字。

null

该字段每次出现的值为null

string

该字段每次出现的值都是一个字符串。

varies

该字段在各种不同类型的有效负载中出现多次。

您还可以使用type(Object)on 方法显式设置类型FieldDescriptortoString提供的方法的结果Object在文档中使用。通常,使用 枚举的值之一JsonFieldType。以下示例显示了如何执行此操作:

.filter(document("user", responseFields(fieldWithPath("contact.email").type(JsonFieldType.STRING) (1)
		.description("The user's email address"))))
1 将字段的类型设置为String
XML 有效负载

本节介绍如何使用 XML 有效负载。

XML 字段路径

XML 字段路径是使用 XPath 描述的。 /用于下降到子节点。

XML 字段类型

type(Object)记录 XML 有效负载时,您必须使用on 方法为字段提供类型FieldDescriptortoString文档中使用了提供的类型方法的结果。

重用字段描述符

除了对重用片段的一般支持之外,请求和响应片段还允许使用路径前缀配置其他描述符。这使得请求或响应有效负载的重复部分的描述符被创建一次,然后被重用。

考虑一个返回一本书的端点:

{
	"title": "Pride and Prejudice",
	"author": "Jane Austen"
}

和的路径分别是title和。authortitleauthor

现在考虑一个返回书籍数组的端点:

[{
	"title": "Pride and Prejudice",
	"author": "Jane Austen"
},
{
	"title": "To Kill a Mockingbird",
	"author": "Harper Lee"
}]

和的路径分别是title和。单本书和书籍数组之间的唯一区别是字段的路径现在有一个前缀。author[].title[].author[].

您可以创建记录书籍的描述符,如下所示:

FieldDescriptor[] book = new FieldDescriptor[] { fieldWithPath("title").description("Title of the book"),
		fieldWithPath("author").description("Author of the book") };

然后,您可以使用它们来记录一本书,如下所示:

RestAssured.given(this.spec).accept("application/json").filter(document("book", responseFields(book))) (1)
		.when().get("/books/1").then().assertThat().statusCode(is(200));
1 记录titleauthor使用现有的描述符

您还可以使用描述符来记录一系列书籍,如下所示:

RestAssured.given(this.spec).accept("application/json")
		.filter(document("books", responseFields(fieldWithPath("[]").description("An array of books")) (1)
				.andWithPrefix("[].", book))) (2)
		.when().get("/books").then().assertThat().statusCode(is(200));
1 记录数组。
2 记录[].title[].author使用带有前缀的现有描述符[].

记录请求或响应负载的子部分

如果有效负载很大或结构复杂,则记录有效负载的各个部分会很有用。REST Docs 允许您通过提取有效负载的一小部分然后记录它来做到这一点。

记录请求或响应正文的子部分

考虑以下 JSON 响应正文:

{
	"weather": {
		"wind": {
			"speed": 15.3,
			"direction": 287.0
		},
		"temperature": {
			"high": 21.2,
			"low": 14.8
		}
	}
}

您可以生成一个记录该temperature对象的片段,如下所示:

RestAssured.given(this.spec).accept("application/json")
		.filter(document("location", responseBody(beneathPath("weather.temperature")))) (1)
		.when().get("/locations/1").then().assertThat().statusCode(is(200));
1 生成一个包含响应正文小节的片段。使用静态responseBodybeneathPath方法org.springframework.restdocs.payload.PayloadDocumentation。要为请求正文生成片段,您可以使用requestBody.responseBody

结果是一个包含以下内容的片段:

{
	"temperature": {
		"high": 21.2,
		"low": 14.8
	}
}

为了使片段的名称与众不同,包含了该小节的标识符。默认情况下,此标识符为beneath-${path}. 例如,前面的代码生成一个名为response-body-beneath-weather.temperature.adoc. 您可以使用该withSubsectionId(String)方法自定义标识符,如下所示:

responseBody(beneathPath("weather.temperature").withSubsectionId("temp"));

结果是一个名为request-body-temp.adoc.

记录请求或响应的子部分的字段

除了记录请求或响应正文的小节之外,您还可以记录特定小节中的字段。您可以生成一个记录temperature对象 (highlow) 字段的片段,如下所示:

RestAssured.given(this.spec).accept("application/json")
		.filter(document("location", responseFields(beneathPath("weather.temperature"), (1)
				fieldWithPath("high").description("The forecast high in degrees celcius"), (2)
				fieldWithPath("low").description("The forecast low in degrees celcius"))))
		.when().get("/locations/1").then().assertThat().statusCode(is(200));
1 生成一个片段,描述路径下响应负载的子部分中的字段weather.temperature。对 使用静态beneathPath方法org.springframework.restdocs.payload.PayloadDocumentation
2 记录highlow字段。

结果是一个片段,其中包含一个描述 的highlow字段的表weather.temperature。为了使片段的名称与众不同,包含了该小节的标识符。默认情况下,此标识符为beneath-${path}. 例如,前面的代码生成一个名为response-fields-beneath-weather.temperature.adoc.

请求参数

您可以使用 记录请求的参数requestParametersGET您可以在请求的查询字符串中包含请求参数。以下示例显示了如何执行此操作:

RestAssured.given(this.spec).filter(document("users", requestParameters((1)
		parameterWithName("page").description("The page to retrieve"), (2)
		parameterWithName("per_page").description("Entries per page")))) (3)
		.when().get("/users?page=2&per_page=100") (4)
		.then().assertThat().statusCode(is(200));
1 配置 Spring REST Docs 以生成描述请求参数的片段。对 使用静态requestParameters方法org.springframework.restdocs.request.RequestDocumentation
2 记录page参数。对 使用静态parameterWithName方法org.springframework.restdocs.request.RequestDocumentation
3 记录per_page参数。
4 使用查询字符串中的GET两个参数page和执行请求。per_page

您还可以将请求参数作为表单数据包含在 POST 请求的正文中。以下示例显示了如何执行此操作:

RestAssured.given(this.spec)
		.filter(document("create-user",
				requestParameters(parameterWithName("username").description("The user's username"))))
		.formParam("username", "Tester") (1)
		.when().post("/users") (2)
		.then().assertThat().statusCode(is(200));
1 配置username参数。
2 执行POST请求。

在所有情况下,结果都是一个名为的片段request-parameters.adoc,其中包含一个描述资源支持的参数的表。

记录请求参数时,如果在请求中使用了未记录的请求参数,则测试失败。同样,如果在请求中未找到记录的请求参数并且请求参数未标记为可选,则测试也会失败。

如果您不想记录请求参数,可以将其标记为已忽略。这可以防止它出现在生成的代码段中,同时避免上述失败。

您还可以在宽松模式下记录请求参数,其中任何未记录的参数都不会导致测试失败。为此,请使用 上的relaxedRequestParameters方法org.springframework.restdocs.request.RequestDocumentation。在记录您只想关注请求参数的子集的特定场景时,这可能很有用。

路径参数

您可以使用 记录请求的路径参数pathParameters。以下示例显示了如何执行此操作:

RestAssured.given(this.spec).filter(document("locations", pathParameters((1)
		parameterWithName("latitude").description("The location's latitude"), (2)
		parameterWithName("longitude").description("The location's longitude")))) (3)
		.when().get("/locations/{latitude}/{longitude}", 51.5072, 0.1275) (4)
		.then().assertThat().statusCode(is(200));
1 配置 Spring REST Docs 以生成描述请求路径参数的片段。对 使用静态pathParameters方法org.springframework.restdocs.request.RequestDocumentation
2 记录名为 的参数latitude。对 使用静态parameterWithName方法org.springframework.restdocs.request.RequestDocumentation
3 记录名为 的参数longitude
4 使用两个路径参数执行GET请求,latitude并且longitude.

结果是一个名为的片段path-parameters.adoc,其中包含一个描述资源支持的路径参数的表。

如果您使用 MockMvc,为了使路径参数可用于文档,您必须使用其中一种方法来构建请求,RestDocumentationRequestBuilders而不是MockMvcRequestBuilders.

记录路径参数时,如果在请求中使用了未记录的路径参数,则测试失败。同样,如果在请求中未找到记录的路径参数并且路径参数未标记为可选,则测试也会失败。

您还可以在宽松模式下记录路径参数,其中任何未记录的参数都不会导致测试失败。为此,请使用 上的relaxedPathParameters方法org.springframework.restdocs.request.RequestDocumentation。在记录您只想关注路径参数子集的特定场景时,这可能很有用。

如果您不想记录路径参数,可以将其标记为已忽略。这样做可以防止它出现在生成的代码段中,同时避免前面描述的失败。

索取零件

您可以requestParts用来记录多部分请求的各个部分。以下示例显示了如何执行此操作:

RestAssured.given(this.spec).filter(document("users", requestParts((1)
		partWithName("file").description("The file to upload")))) (2)
		.multiPart("file", "example") (3)
		.when().post("/upload") (4)
		.then().statusCode(is(200));
1 配置 Spring REST Docs 以生成描述请求部分的片段。对 使用静态requestParts方法org.springframework.restdocs.request.RequestDocumentation
2 记录名为file. 对 使用静态partWithName方法org.springframework.restdocs.request.RequestDocumentation
3 使用名为 的部分配置请求file
4 执行对 的POST请求/upload

结果是一个名为的片段request-parts.adoc,其中包含一个描述资源支持的请求部分的表。

在记录请求部分时,如果在请求中使用了未记录的部分,则测试失败。同样,如果在请求中未找到记录的部分并且该部分未标记为可选,则测试也会失败。

您还可以在轻松模式下记录请求部分,其中任何未记录的部分都不会导致测试失败。为此,请使用 上的relaxedRequestParts方法org.springframework.restdocs.request.RequestDocumentation。在记录您只想关注请求部分的子集的特定场景时,这可能很有用。

如果您不想记录请求部分,可以将其标记为已忽略。这可以防止它出现在生成的代码段中,同时避免前面描述的失败。

请求部分有效载荷

您可以以与请求的有效负载大致相同的方式记录请求部分的有效负载,并支持记录请求部分的正文及其字段。

记录请求部分的正文

您可以生成包含请求部分正文的片段,如下所示:

Map<String, String> metadata = new HashMap<>();
metadata.put("version", "1.0");
RestAssured.given(this.spec).accept("application/json")
		.filter(document("image-upload", requestPartBody("metadata"))) (1)
		.when().multiPart("image", new File("image.png"), "image/png").multiPart("metadata", metadata)
		.post("images").then().assertThat().statusCode(is(200));
1 配置 Spring REST 文档以生成一个片段,其中包含名为metadata. 对 使用静态requestPartBody方法PayloadDocumentation

结果是一个名为的片段request-part-${part-name}-body.adoc,其中包含部件的主体。例如,记录一个名为的部分metadata会生成一个名为request-part-metadata-body.adoc.

记录请求部分的字段

您可以使用与请求或响应的字段大致相同的方式记录请求部分的字段,如下所示:

Map<String, String> metadata = new HashMap<>();
metadata.put("version", "1.0");
RestAssured.given(this.spec).accept("application/json")
		.filter(document("image-upload", requestPartFields("metadata", (1)
				fieldWithPath("version").description("The version of the image")))) (2)
		.when().multiPart("image", new File("image.png"), "image/png").multiPart("metadata", metadata)
		.post("images").then().assertThat().statusCode(is(200));
1 配置 Spring REST 文档以生成一个片段,描述名为metadata. 对 使用静态requestPartFields方法PayloadDocumentation
2 期望一个带有路径的字段version。对 使用静态fieldWithPath方法org.springframework.restdocs.payload.PayloadDocumentation

结果是一个片段,其中包含一个描述部件字段的表。这个片段被命名为request-part-${part-name}-fields.adoc. 例如,记录一个名为的部分metadata会生成一个名为request-part-metadata-fields.adoc.

记录字段时,如果在部件的有效负载中发现未记录的字段,则测试失败。同样,如果在部件的有效负载中找不到记录的字段并且该字段未标记为可选,则测试也会失败。对于具有分层结构的有效负载,记录一个字段足以使其所有后代也被视为已记录。

如果您不想记录某个字段,可以将其标记为已忽略。这样做可以防止它出现在生成的代码段中,同时避免上述失败。

您还可以在宽松模式下记录字段,其中任何未记录的字段都不会导致测试失败。为此,请使用 上的relaxedRequestPartFields方法org.springframework.restdocs.payload.PayloadDocumentation。在记录您只想关注零件有效负载子集的特定场景时,这可能很有用。

有关描述字段、记录使用 XML 的有效负载等的更多信息,请参阅记录请求和响应有效负载部分

HTTP 标头

您可以分别使用requestHeaders和记录请求或响应中的标头。responseHeaders以下示例显示了如何执行此操作:

RestAssured.given(this.spec).filter(document("headers", requestHeaders((1)
		headerWithName("Authorization").description("Basic auth credentials")), (2)
		responseHeaders((3)
				headerWithName("X-RateLimit-Limit")
						.description("The total number of requests permitted per period"),
				headerWithName("X-RateLimit-Remaining")
						.description("Remaining requests permitted in current period"),
				headerWithName("X-RateLimit-Reset")
						.description("Time at which the rate limit period will reset"))))
		.header("Authorization", "Basic dXNlcjpzZWNyZXQ=") (4)
		.when().get("/people").then().assertThat().statusCode(is(200));
1 配置 Spring REST Docs 以生成描述请求标头的片段。对 使用静态requestHeaders方法org.springframework.restdocs.headers.HeaderDocumentation
2 记录Authorization标题。headerWithName在 org.springframework.restdocs.headers.HeaderDocumentation 上使用静态方法。
3 生成描述响应标头的片段。对 使用静态responseHeaders方法org.springframework.restdocs.headers.HeaderDocumentation
4 Authorization使用使用基本身份验证的标头配置请求。

结果是一个名为的片段request-headers.adoc和一个名为 的片段response-headers.adoc。每个都包含一个描述标题的表。

记录 HTTP 标头时,如果在请求或响应中未找到记录的标头,则测试失败。

重用代码段

正在记录的 API 具有一些在其多个资源中通用的特性是很常见的。为避免在记录此类资源时重复,您可以重用Snippet配置有公共元素的配置。

首先,创建Snippet描述通用元素的。以下示例显示了如何执行此操作:

protected final LinksSnippet pagingLinks = links(
		linkWithRel("first").optional().description("The first page of results"),
		linkWithRel("last").optional().description("The last page of results"),
		linkWithRel("next").optional().description("The next page of results"),
		linkWithRel("prev").optional().description("The previous page of results"));

其次,使用此代码段并添加更多特定于资源的描述符。以下示例显示了如何执行此操作:

RestAssured.given(this.spec).accept("application/json").filter(document("example", this.pagingLinks.and((1)
		linkWithRel("alpha").description("Link to the alpha resource"),
		linkWithRel("bravo").description("Link to the bravo resource")))).get("/").then().assertThat()
		.statusCode(is(200));
1 重复使用pagingLinks Snippet, 调用and来添加特定于正在记录的资源的描述符。

该示例的结果是具有、、、、和rel值的链接都已记录在案。firstlastnextpreviousalphabravo

记录约束

Spring REST Docs 提供了许多可以帮助您记录约束的类。您可以使用 的实例ConstraintDescriptions来访问类约束的描述。以下示例显示了如何执行此操作:

public void example() {
	ConstraintDescriptions userConstraints = new ConstraintDescriptions(UserInput.class); (1)
	List<String> descriptions = userConstraints.descriptionsForProperty("name"); (2)
}

static class UserInput {

	@NotNull
	@Size(min = 1)
	String name;

	@NotNull
	@Size(min = 8)
	String password;

}
1 ConstraintDescriptionsUserInput该类创建一个实例。
2 获取name属性约束的描述。此列表包含两种描述:一种用于NotNull约束,另一种用于Size约束。

Spring HATEOAS 示例中的ApiDocumentation类显示了此功能的实际应用。

寻找约束

默认情况下,通过使用 Bean Validation 找到约束Validator。目前,仅支持属性约束。您可以通过使用自定义实例Validator创建来自定义使用的。要完全控制约束解析,您可以使用自己的.ConstraintDescriptionsValidatorConstraintResolverConstraintResolver

描述约束

为所有 Bean Validation 2.0 的约束提供了默认描述:

  • AssertFalse

  • AssertTrue

  • DecimalMax

  • DecimalMin

  • Digits

  • Email

  • Future

  • FutureOrPresent

  • Max

  • Min

  • Negative

  • NegativeOrZero

  • NotBlank

  • NotEmpty

  • NotNull

  • Null

  • Past

  • PastOrPresent

  • Pattern

  • Positive

  • PositiveOrZero

  • Size

Hibernate Validator 还为以下约束提供了默认描述:

  • CodePointLength

  • CreditCardNumber

  • Currency

  • EAN

  • Email

  • Length

  • LuhnCheck

  • Mod10Check

  • Mod11Check

  • NotBlank

  • NotEmpty

  • Currency

  • Range

  • SafeHtml

  • URL

要覆盖默认描述或提供新描述,您可以创建一个基本名称为org.springframework.restdocs.constraints.ConstraintDescriptions. 基于 Spring HATEOAS 的示例包含此类资源包的示例

资源包中的每个键都是约束的完全限定名称加上.description. 例如,标准@NotNull约束的键是javax.validation.constraints.NotNull.description.

您可以使用属性占位符在其描述中引用约束的属性。例如,约束的默认描述@Min,Must be at least ${value}指的是约束的value属性。

要更好地控制约束描述解析,您可以ConstraintDescriptions使用自定义创建ResourceBundleConstraintDescriptionResolver. 要完全控制,您可以ConstraintDescriptions使用自定义ConstraintDescriptionResolver实现进行创建。

在生成的片段中使用约束描述

一旦有了约束的描述,您就可以在生成的代码段中随意使用它们。例如,您可能希望将约束描述作为字段描述的一部分。或者,您可以将约束作为额外信息包含在请求字段片段中。ApiDocumentationSpring HATEOAS-based sample 中的类说明了后一种方法。

默认片段

当您记录请求和响应时,会自动生成许多片段。

片段 描述

curl-request.adoc

包含与 正在记录curl的调用等效的命令。MockMvc

httpie-request.adoc

包含与 正在记录HTTPie的调用等效的命令。MockMvc

http-request.adoc

MockMvc包含与正在记录的调用等效的 HTTP 请求。

http-response.adoc

包含返回的 HTTP 响应。

request-body.adoc

包含已发送请求的正文。

response-body.adoc

包含返回的响应的正文。

您可以配置默认生成哪些片段。有关详细信息,请参阅配置部分

使用参数化输出目录

使用 MockMvc、REST Assured 时,或者WebTestClient您可以参数化document. 参数化输出WebTestClient需要 Spring Framework 5.3.5 或更高版本。

支持以下参数:

范围 描述

{方法名}

测试方法的未修改名称。

{方法名}

测试方法的名称,使用 kebab-case 格式化。

{方法名}

测试方法的名称,使用snake_case 格式化。

{班级名称}

测试类的未修改简单名称。

{班级名称}

测试类的简单名称,使用 kebab-case 格式化。

{班级名称}

测试类的简单名称,使用snake_case 格式化。

{步}

当前测试中对服务的调用计数。

例如,document("{class-name}/{method-name}")在名为creatingANote测试类的测试方法中,GettingStartedDocumentation将片段写入名为getting-started-documentation/creating-a-note.

@Before参数化输出目录与方法结合使用特别有用。它允许文档在设置方法中配置一次,然后在类中的每个测试中重用。以下示例显示了如何执行此操作:

@Before
public void setUp() {
	this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(this.restDocumentation))
			.addFilter(document("{method-name}/{step}")).build();
}

有了这个配置,对您正在测试的服务的每次调用都会生成默认片段,而无需任何进一步的配置。查看GettingStartedDocumentation每个示例应用程序中的类以了解此功能的实际作用。

自定义输出

本节介绍如何自定义 Spring REST Docs 的输出。

自定义生成的片段

Spring REST Docs 使用Mustache模板来生成生成的代码片段。 为 Spring REST Docs 可以生成的每个片段提供了默认模板。要自定义片段的内容,您可以提供自己的模板。

模板是从org.springframework.restdocs.templates子包的类路径加载的。子包的名称由正在使用的模板格式的 ID 确定。默认模板格式 Asciidoctor 的 ID 为asciidoctor,因此从org.springframework.restdocs.templates.asciidoctor. 每个模板都以其生成的片段命名。例如,要覆盖curl-request.adoc片段的模板,请创建一个名为curl-request.snippetin的模板src/test/resources/org/springframework/restdocs/templates/asciidoctor

包括额外信息

有两种方法可以提供额外信息以包含在生成的代码段中:

  • 使用attributes描述符上的方法为其添加一个或多个属性。

  • 调用curlRequest, httpRequest,httpResponse等时传入一些属性。这些属性与整个片段相关联。

在模板呈现过程中,任何附加属性都可用。结合自定义片段模板,这使得在生成的片段中包含额外信息成为可能。

一个具体的例子是在记录请求字段时添加一个约束列和一个标题。第一步是为constraints您记录的每个字段提供一个属性并提供一个title属性。以下示例显示了如何执行此操作:

.filter(document("create-user",
		requestFields(attributes(key("title").value("Fields for user creation")), (1)
				fieldWithPath("name").description("The user's name")
						.attributes(key("constraints").value("Must not be null. Must not be empty")), (2)
				fieldWithPath("email").description("The user's email address")
						.attributes(key("constraints").value("Must be a valid email address"))))) (3)
1 配置title请求字段片段的属性。
2 设置字段的constraints属性name
3 设置字段的constraints属性email

第二步是提供一个名为的自定义模板,该模板request-fields.snippet在生成的代码段表中包含有关字段约束的信息并添加标题。以下示例显示了如何执行此操作:

.{{title}} (1)
|===
|Path|Type|Description|Constraints (2)

{{#fields}}
|{{path}}
|{{type}}
|{{description}}
|{{constraints}} (3)

{{/fields}}
|===
1 为表格添加标题。
2 添加一个名为“约束”的新列。
3 constraints在表的每一行中包含描述符的属性。

自定义请求和响应

在某些情况下,您可能不希望完全按照发送的方式记录请求或按照收到的方式记录响应。Spring REST Docs 提供了许多预处理器,可用于在记录之前修改请求或响应。

预处理是通过调用documentanOperationRequestPreprocessor或 an来配置的OperationResponsePreprocessor。您可以通过使用静态preprocessRequestpreprocessResponse方法来获取实例Preprocessors。以下示例显示了如何执行此操作:

RestAssured.given(this.spec).filter(document("index", preprocessRequest(removeHeaders("Foo")), (1)
		preprocessResponse(prettyPrint()))) (2)
		.when().get("/").then().assertThat().statusCode(is(200));
1 应用一个请求预处理器来删除名为Foo.
2 应用一个漂亮地打印其内容的响应预处理器。

或者,您可能希望对每个测试应用相同的预处理器。您可以通过RestDocumentationConfigurer在方法中使用 API@Before来配置预处理器。例如,Foo要从所有请求中删除标头并漂亮地打印所有响应,您可以执行以下操作之一(取决于您的测试环境):

private RequestSpecification spec;

@Before
public void setup() {
	this.spec = new RequestSpecBuilder()
			.addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors()
					.withRequestDefaults(removeHeaders("Foo")) (1)
					.withResponseDefaults(prettyPrint())) (2)
			.build();
}
1 应用一个请求预处理器来删除名为Foo.
2 应用一个漂亮地打印其内容的响应预处理器。

然后,在每个测试中,您可以执行特定于该测试的任何配置。以下示例显示了如何执行此操作:

RestAssured.given(this.spec)
		.filter(document("index", links(linkWithRel("self").description("Canonical self link")))).when()
		.get("/").then().assertThat().statusCode(is(200));

各种内置预处理器,包括上面说明的那些,都可以通过Preprocessors. 有关详细信息,请参见下文

预处理器

漂亮的印刷

prettyPrintonPreprocessors格式化请求或响应的内容,使其更易于阅读。

如果您正在记录基于超媒体的 API,您可能希望鼓励客户端通过使用链接而不是通过使用硬编码的 URI 来导航 API。一种方法是限制文档中 URI 的使用。 maskLinkson将响应中任何链接的Preprocessors替换为。如果您愿意,还可以指定不同的替换。href…​

删除标题

removeHeadersonPreprocessors从请求或响应中删除名称等于任何给定标头名称的任何标头。

removeMatchingHeadersonPreprocessors从请求或响应中删除名称与任何给定正则表达式模式匹配的任何标头。

替换模式

replacePatternonPreprocessors提供了一种通用机制,用于替换请求或响应中的内容。任何匹配正则表达式的匹配项都会被替换。

修改请求参数

您可以使用modifyParametersonPreprocessors添加、设置和删除请求参数。

修改 URI

如果您使用未绑定到服务器的 MockMvc 或 WebTestClient,则应通过更改配置来自定义 URI 。

您可以使用modifyUrisonPreprocessors修改请求或响应中的任何 URI。当使用绑定到服务器的 REST Assured 或 WebTestClient 时,这允许您在测试服务的本地实例时自定义出现在文档中的 URI。

编写你自己的预处理器

如果内置预处理器之一不能满足您的需求,您可以通过实现OperationPreprocessor接口来编写自己的预处理器。然后,您可以以与任何内置预处理器完全相同的方式使用您的自定义预处理器。

如果您只想修改请求或响应的内容(正文),请考虑实现ContentModifier接口并将其与内置的ContentModifyingOperationPreprocessor.

配置

本节介绍如何配置 Spring REST 文档。

记录在案的 URI

本节介绍配置文档化的 URI。

MockMvc URI 自定义

使用 MockMvc 时,Spring REST Docs 记录的 URI 的默认配置如下:

环境 默认

方案

http

主持人

localhost

港口

8080

此配置由 应用MockMvcRestDocumentationConfigurer。您可以使用其 API 更改一个或多个默认值以满足您的需要。以下示例显示了如何执行此操作:

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
		.apply(documentationConfiguration(this.restDocumentation).uris().withScheme("https")
				.withHost("example.com").withPort(443))
		.build();
如果端口设置为配置方案的默认值(HTTP 端口 80 或 HTTPS 端口 443),则在生成的片段中的任何 URI 中都会省略它。
要配置请求的上下文路径,请使用contextPathon 方法MockHttpServletRequestBuilder

REST 有保证的 URI 自定义

REST Assured 通过发出实际的 HTTP 请求来测试服务。因此,一旦对服务执行了操作,但在记录之前,必须自定义 URI。为此目的提供了一个特定于 REST-Assured 的预处理器。

WebTestClient URI 自定义

使用 WebTestClient 时,Spring REST Docs 记录的 URI 的默认基础是http://localhost:8080. 您可以使用on 方法自定义此基础。以下示例显示了如何执行此操作: baseUrl(String)WebTestClient.Builder

@Before
public void setUp() {
	this.webTestClient = WebTestClient.bindToApplicationContext(this.context).configureClient()
			.baseUrl("https://api.example.com") (1)
			.filter(documentationConfiguration(this.restDocumentation)).build();
}
1 将记录的 URI 的基数配置为https://api.example.com.

片段编码

默认的代码片段编码是UTF-8. 您可以使用RestDocumentationConfigurerAPI 更改默认代码段编码。例如,以下示例使用ISO-8859-1

this.spec = new RequestSpecBuilder()
		.addFilter(documentationConfiguration(this.restDocumentation).snippets().withEncoding("ISO-8859-1"))
		.build();
当 Spring REST Docs 将请求或响应的内容转换为 aString时,如果可用,则使用标头中charset指定的内容。Content-Type如果没有,则使用 JVM 的默认值CharsetCharset您可以使用file.encoding系统属性 配置 JVM 的默认值。

片段模板格式

默认的代码片段模板格式是 Asciidoctor。Markdown 也支持开箱即用。您可以使用RestDocumentationConfigurerAPI 更改默认格式。以下示例显示了如何执行此操作:

this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(this.restDocumentation).snippets()
		.withTemplateFormat(TemplateFormats.markdown())).build();

默认片段

默认情况下会生成六个片段:

  • curl-request

  • http-request

  • http-response

  • httpie-request

  • request-body

  • response-body

您可以在设置期间使用RestDocumentationConfigurerAPI 更改默认代码段配置。以下示例curl-request默认仅生成代码段:

this.spec = new RequestSpecBuilder()
		.addFilter(documentationConfiguration(this.restDocumentation).snippets().withDefaults(curlRequest()))
		.build();

默认操作预处理器

您可以在设置期间使用RestDocumentationConfigurerAPI 配置默认请求和响应预处理器。以下示例Foo从所有请求中删除标头并漂亮地打印所有响应:

this.spec = new RequestSpecBuilder()
		.addFilter(documentationConfiguration(this.restDocumentation).operationPreprocessors()
				.withRequestDefaults(removeHeaders("Foo")) (1)
				.withResponseDefaults(prettyPrint())) (2)
		.build();
1 应用一个请求预处理器来删除名为Foo.
2 应用一个漂亮地打印其内容的响应预处理器。

与 Asciidoctor 合作

本节描述了与 Spring REST 文档特别相关的使用 Asciidoctor 的各个方面。

Asciidoc 是文档格式。Asciidoctor 是从 Asciidoc 文件(以 结尾.adoc)生成内容(通常为 HTML)的工具。

包括片段

本节介绍如何包含 Asciidoc 片段。

包括一个操作的多个片段

您可以使用名为的宏operation来导入为特定操作生成的所有或部分片段。通过包含spring-restdocs-asciidoctor在项目的构建配置中可以使用它。

宏的目标是操作的名称。在最简单的形式中,您可以使用宏来包含操作的所有片段,如以下示例所示:

operation::index[]

你可以使用操作宏也支持一个snippets属性。snippets用于选择应包含的片段的属性。该属性的值是一个逗号分隔的列表。列表中的每个条目都应该是要包含的片段文件的名称(减去.adoc后缀)。例如,只能包含 curl、HTTP 请求和 HTTP 响应片段,如下例所示:

operation::index[snippets='curl-request,http-request,http-response']

前面的示例等效于以下示例:

[[example_curl_request]]
== Curl request

include::{snippets}/index/curl-request.adoc[]

[[example_http_request]]
== HTTP request

include::{snippets}/index/http-request.adoc[]

[[example_http_response]]
== HTTP response

include::{snippets}/index/http-response.adoc[]
章节标题

对于使用宏包含的每个片段,operation都会创建一个带有标题的部分。为以下内置片段提供了默认标题:

片段 标题

curl-request

卷曲请求

http-request

HTTP 请求

http-response

HTTP 响应

httpie-request

HTTPie 请求

links

链接

request-body

请求正文

request-fields

请求字段

response-body

响应正文

response-fields

响应字段

-对于上表中未列出的片段,通过将字符替换为空格并将第一个字母大写来生成默认标题。例如,名为custom-snippet will be“自定义片段”的片段的标题。

您可以使用文档属性自定义默认标题。属性的名称应该是operation-{snippet}-title. 例如,要将curl-request片段的标题自定义为“示例请求”,您可以使用以下属性:

:operation-curl-request-title: Example request

包括单个片段

include 宏用于在文档中包含各个片段。您可以使用该snippets属性(通过spring-restdocs-asciidoctor构建配置中配置自动设置)来引用片段输出目录。以下示例显示了如何执行此操作:

include::{snippets}/index/curl-request.adoc[]

自定义表格

许多片段在其默认配置中包含一个表。可以通过在包含片段时提供一些额外的配置或使用自定义片段模板来自定义表格的外观。

格式化列

Asciidoctor 对格式化表格的列有丰富的支持。cols如以下示例所示,您可以使用属性指定表格列的宽度:

[cols="1,3"] (1)
include::{snippets}/index/links.adoc[]
1 表格的宽度被分成两列,第二列的宽度是第一列的三倍。

配置标题

您可以使用以 . 为前缀的行来指定表的标题.。以下示例显示了如何执行此操作:

.Links (1)
include::{snippets}/index/links.adoc[]
1 表的标题将是Links

避免表格格式问题

Asciidoctor 使用该|字符来分隔表格中的单元格。如果您希望 a|出现在单元格的内容中,这可能会导致问题。你可以通过用反斜杠转义来避免这个问题|——换句话说,通过使用\|而不是|.

所有默认的 Asciidoctor 片段模板都使用名为tableCellContent. 如果您编写自己的自定义模板,您可能想要使用这个 Lamba。以下示例显示如何转义|包含description属性值的单元格中的字符:

| {{#tableCellContent}}{{description}}{{/tableCellContent}}

延伸阅读

有关自定义表格的更多信息,请参阅Asciidoctor 用户手册的表格部分。

使用 Markdown

本节描述了与 Spring REST 文档特别相关的 Markdown 方面。

限制

Markdown 最初是为为网络写作的人设计的,因此不像 Asciidoctor 那样适合编写文档。通常,这些限制可以通过使用构建在 Markdown 之上的另一个工具来克服。

Markdown 没有对表格的官方支持。Spring REST Docs 的默认 Markdown 片段模板使用Markdown Extra 的表格格式

包括片段

Markdown 没有内置支持将一个 Markdown 文件包含在另一个文件中。要将生成的 Markdown 片段包含在您的文档中,您应该使用支持此功能的附加工具。Slate是一个特别适合记录 API 的示例。

贡献

Spring REST Docs is intended to make it easy for you to produce high-quality documentation for your RESTful services. However, we cannot achieve that goal without your contributions.

Questions

You can ask questions about Spring REST Docs on Stack Overflow by using the spring-restdocs tag. Similarly, we encourage you to help your fellow Spring REST Docs users by answering questions.

Bugs

If you believe you have found a bug, please take a moment to search the existing issues. If no one else has reported the problem, please open a new issue that describes the problem in detail and, ideally, includes a test that reproduces it.

Enhancements

如果您希望对 Spring REST Docs 进行增强,欢迎请求请求。源代码在GitHub 上。您可能希望搜索现有问题拉取请求,以查看是否已提出增强功能。您可能还想在开始工作之前打开一个新问题来讨论可能的增强功能。


1. see XML Configuration