提交 6c28d10a 编写于 作者: 茶陵後's avatar 茶陵後 👍

#25 spring hateoas

上级 9d5e3a20
# Spring Hateoas-参考文献
## [](#preface)1。前言
## 1.前言
### [](#migrate-to-1.0)1.1。迁移到 Spring Hateoas1.0
### 1.1.迁移到 Spring Hateoas1.0
对于 1.0,我们利用这个机会重新评估了我们为 0.x 分支所做的一些设计和包结构选择。对此有大量的反馈,主要版本的提升似乎是重构这些内容的最自然的地方。
#### [](#migrate-to-1.0.changes)1.1.1。变化
#### 1.1.1.变化
包结构中最大的变化是引入了超媒体类型注册 API,以支持 Spring Hateoas 中的其他媒体类型。这导致客户机和服务器 API(分别命名的包)以及包`mediatype`中的媒体类型实现的明确分离。
使你的代码库升级到新 API 的最简单的方法是使用[迁移脚本](#migrate-to-1.0.script)。在我们开始讨论这一问题之前,我们先来简单了解一下这些变化。
##### [](#migrate-to-1.0.changes.representation-models)表示模型
##### 表示模型
`ResourceSupport`/`Resource`/`Resources`/`PagedResources`这组类从来没有真正感觉到合适的名称。毕竟,这些类型实际上并不表示资源,而是表示模型,这些模型可以用超媒体信息和启示来丰富。以下是新名字与旧名字的对应方式:
......@@ -38,11 +38,11 @@
* `VndError`已被移动到`mediatype.vnderror`包中。
#### [](#migrate-to-1.0.script)1.1.2。迁移脚本
#### 1.1.2.迁移脚本
你可以在应用程序根目录中找到[a script](https://github.com/spring-projects/spring-hateoas/tree/master/etc)以运行,该根目录将更新所有导入语句和静态方法引用,使其指向在我们的源代码存储库中移动的 Spring Hateoas 类型。只需下载它,从你的项目根目录运行它。默认情况下,它将检查所有 Java 源文件,并用新的 Hateoas 类型引用替换旧的 Spring Hateoas 类型引用。
例 1迁移脚本的示例应用程序
例 1.迁移脚本的示例应用程序
```
$ ./migrate-to-1.0.sh
......@@ -59,7 +59,7 @@ Done!
现在验证对你最喜欢的 Git 客户机中的文件所做的更改,并根据需要提交。如果你发现方法或类型引用未被删除,请打开票据在出问题追踪器。
#### [](#migration.1-0-M3-to-1-0-RC1)1.1.3。从 1.0m3 迁移到 1.0rc1
#### 1.1.3.从 1.0m3 迁移到 1.0rc1
* `Link.andAffordance(…)`可提供的细节已移至`Affordances`。要手动构建`Affordance`实例,现在使用`Affordances.of(link).afford(…)`。还请注意从`Affordances`公开的新`AffordanceBuilder`类型,以便流畅地使用。详见[启示](#server.affordances)
......@@ -67,15 +67,15 @@ Done!
* HAL 窗体现在不呈现属性属性,如果它们的值符合规范中定义的默认值。也就是说,如果以前`required`显式地设置为`false`,那么我们现在省略`required`的条目。我们现在也只强制那些使用`PATCH`作为 HTTP 方法的模板不需要它们。
## [](#fundamentals)2。基本原理
## 2.基本原理
本节介绍了 Spring Hateoas 的基础知识及其基本的领域抽象。
### [](#fundamentals.links)2.1。链接
### 2.1.链接
超媒体的基本思想是用超媒体元素来丰富资源的表示。最简单的形式是链接。它们指示客户机可以导航到特定的资源。相关资源的语义是在所谓的链接关系中定义的。你可能已经在 HTML 文件的头中看到了这一点:
例 2HTML 文档中的链接
例 2.HTML 文档中的链接
```
<link href="theme.css" rel="stylesheet" type="text/css" />
......@@ -85,7 +85,7 @@ Done!
Spring Hateoas 允许你通过其不可变的`Link`值类型处理链接。它的构造函数接受超文本引用和链接关系,后者默认为 IANA 链接关系`self`。在[链接关系](#fundamentals.link-relations)中阅读有关后者的更多信息。
例 3使用链接
例 3.使用链接
```
Link link = Link.of("/something");
......@@ -101,11 +101,11 @@ assertThat(link.getRel()).isEqualTo(LinkRelation.of("my-rel"));
[ Building links in Spring MVC](#server.link-builder.webmvc)[Building links in Spring WebFlux](#server.link-builder.webflux)中找到有关如何创建指向 Spring MVC 和 Spring WebFlux 控制器的链接的更多信息。
### [](#fundamentals.uri-templates)2.2。URI 模板
### 2.2.URI 模板
对于 Spring Hateoas`Link`,超文本引用不仅可以是一个 URI,而且根据[RFC-6570](https://tools.ietf.org/html/rfc6570)也可以是一个 URI 模板。URI 模板包含所谓的模板变量,并允许扩展这些参数。这允许客户机将参数化模板转换为 URI,而无需了解最终 URI 的结构,只需了解变量的名称即可。
例 4使用带有模板化 URI 的链接
例 4.使用带有模板化 URI 的链接
```
Link link = Link.of("/{segment}/something{?parameter}");
......@@ -127,7 +127,7 @@ assertThat(link.expand(values).getHref()) (3)
URI 模板可以手动构建,然后添加模板变量。
例 5使用 URI 模板
例 5.使用 URI 模板
```
UriTemplate template = UriTemplate.of("/{segment}/something")
......@@ -136,15 +136,15 @@ UriTemplate template = UriTemplate.of("/{segment}/something")
assertThat(template.toString()).isEqualTo("/{segment}/something{?parameter}");
```
### [](#fundamentals.link-relations)2.3。链接关系
### 2.3.链接关系
要表示目标资源与当前资源的关系,可以使用所谓的链接关系。 Spring Hateoas 提供了一个`LinkRelation`类型来轻松地创建基于`String`的实例。
#### [](#fundamentals.link-relations.iana)2.3.1。IANA 链接关系
#### 2.3.1.IANA 链接关系
因特网分配号码管理局包含一组[预定义的链接关系](https://www.iana.org/assignments/link-relations/link-relations.xhtml)。它们可以通过`IanaLinkRelations`引用。
例 6使用 IANA 链接关系
例 6.使用 IANA 链接关系
```
Link link = Link.of("/some-resource"), IanaLinkRelations.NEXT);
......@@ -153,17 +153,17 @@ assertThat(link.getRel()).isEqualTo(LinkRelation.of("next"));
assertThat(IanaLinkRelation.isIanaRel(link.getRel())).isTrue();
```
### [](#fundamentals.representation-models)2.4。[]()表示模型
### 表示模型
Spring 为了方便地创建富含超媒体的表示,Hateoas 提供了一组在其根上带有`RepresentationModel`的类。它基本上是一个`Link`s 集合的容器,并且有方便的方法将它们添加到模型中。模型稍后可以呈现为各种媒体类型格式,这些格式将定义超媒体元素在表示中的外观。有关此的更多信息,请查看[媒体类型](#mediatypes)
例 7`RepresentationModel`类层次结构
例 7.`RepresentationModel`类层次结构
<img alt="diagram classes" src="images/diagram-classes.svg" height="120" width="632" />
使用`RepresentationModel`的默认方法是创建它的一个子类,以包含表示应该包含的所有属性,创建该类的实例,填充属性并用链接丰富它。
例 8样本表示模型类型
例 8.样本表示模型类型
```
class PersonModel extends RepresentationModel<PersonModel> {
......@@ -174,7 +174,7 @@ class PersonModel extends RepresentationModel<PersonModel> {
要让`RepresentationModel.add(…)`返回自身的实例,需要使用泛型自类型。模型类型现在可以这样使用:
例 9使用 Person 表示模型
例 9.使用 Person 表示模型
```
PersonModel model = new PersonModel();
......@@ -185,7 +185,7 @@ model.add(Link.of("https://myhost/people/42"));
如果你从 Spring MVC 或 WebFlux 控制器返回了这样的实例,并且客户机发送了一个`Accept`头,将其设置为`application/hal+json`,则响应将如下所示:
例 10为人员表示模型生成的 HAL 表示
例 10.为人员表示模型生成的 HAL 表示
```
{
......@@ -199,11 +199,11 @@ model.add(Link.of("https://myhost/people/42"));
}
```
#### [](#fundamentals.entity-model)2.4.1。项目资源表示模型
#### 2.4.1.项目资源表示模型
对于由单一对象或概念支持的资源,存在`EntityModel`类型的便利。与为每个概念创建自定义模型类型不同,你可以重用一个已经存在的类型,并将它的实例封装到`EntityModel`中。
例 11使用`EntityModel`包装现有对象
例 11.使用`EntityModel`包装现有对象
```
Person person = new Person("Dave", "Matthews");
......@@ -214,16 +214,16 @@ EntityModel<Person> model = EntityModel.of(person);
对于概念上是集合的资源,可以使用`CollectionModel`。它的元素可以是简单对象,也可以是`RepresentationModel`实例。
例 12使用`CollectionModel`包装现有对象的集合
例 12.使用`CollectionModel`包装现有对象的集合
```
Collection<Person> people = Collections.singleton(new Person("Dave", "Matthews"));
CollectionModel<Person> model = CollectionModel.of(people);
```
## [](#server)3。服务器端支持
## 3.服务器端支持
### [](#server.link-builder.webmvc)3.1。[]()[]()在 Spring MVC 中构建链接
### 在 Spring MVC 中构建链接
现在我们已经有了域词汇表,但主要的挑战仍然是:如何创建实际的 URI,并以一种不那么脆弱的方式包装到`Link`实例中。现在,我们将不得不到处复制 URI 字符串。这样做是脆弱和不可维护的。
......@@ -277,7 +277,7 @@ headers.setLocation(linkTo(PersonController.class).slash(person).toUri());
return new ResponseEntity<PersonModel>(headers, HttpStatus.CREATED);
```
#### [](#fundamentals.obtaining-links.builder.methods)3.1.1。建立指向方法的链接
#### 3.1.1.建立指向方法的链接
你甚至可以构建指向方法的链接,或者创建虚拟控制器方法调用。第一种方法是将`Method`实例交给`WebMvcLinkBuilder`。下面的示例展示了如何做到这一点:
......@@ -302,11 +302,11 @@ assertThat(link.getHref()).endsWith("/people/2");
* 传递到方法中的参数通常被忽略(通过`@PathVariable`引用的参数除外,因为它们构成了 URI)。
### [](#server.link-builder.webflux)3.2。在 Spring WebFlux 中构建链接
### 3.2.在 Spring WebFlux 中构建链接
TODO
### [](#server.affordances)3.3。启示
### 3.3.启示
> > > >
> 环境所能提供的就是它所提供的……它所提供的或提供的,不管是好是坏。词典中有动词“to afford”,但名词“affordance”没有。这是我编的。
......@@ -320,7 +320,7 @@ TODO
下面的代码展示了如何使用**自我**链接并关联另外两个启示:
例 13连接到`GET /employees/{id}`的启示
例 13.连接到`GET /employees/{id}`的启示
```
@GetMapping("/employees/{id}")
......@@ -346,7 +346,7 @@ public EntityModel<Employee> findOne(@PathVariable Integer id) {
使用`.andAffordance(afford(…​))`,你可以使用控制器的方法将`PUT``PATCH`操作连接到`GET`操作。假设上面的相关方法**提供**看起来是这样的:
例 14响应`updateEmpoyee``PUT /employees/{id}`方法
例 14.响应`updateEmpoyee``PUT /employees/{id}`方法
```
@PutMapping("/employees/{id}")
......@@ -354,7 +354,7 @@ public ResponseEntity<?> updateEmployee( //
@RequestBody EntityModel<Employee> employee, @PathVariable Integer id)
```
例 15响应`PATCH /employees/{id}``partiallyUpdateEmployee`方法
例 15.响应`PATCH /employees/{id}``partiallyUpdateEmployee`方法
```
@PatchMapping("/employees/{id}")
......@@ -364,11 +364,11 @@ public ResponseEntity<?> partiallyUpdateEmployee( //
指向那些使用`afford(…)`方法的方法将导致 Spring Hateoas 分析请求主体和响应类型并捕获元数据,以允许不同的媒体类型实现使用该信息将其转换为输入和输出的描述。
#### [](#server.affordances.api)3.3.1。人工构建可供参考的功能
#### 3.3.1.人工构建可供参考的功能
虽然注册链接的主要方法是提供支持,但可能有必要手动构建其中的一些。这可以通过使用`Affordances`API 来实现:
例 16使用`Affordances`API 手动注册启示
例 16.使用`Affordances`API 手动注册启示
```
var methodInvocation = methodOn(EmployeeController.class).all();
......@@ -396,7 +396,7 @@ var link = Affordances.of(linkTo(methodInvocation).withSelfRel()) (1)
启示由特定于媒体类型的启示模型支持,该模型将一般的启示元数据转换为特定的表示形式。请务必检查[媒体类型](#mediatypes)部分中有关启示的部分,以找到有关如何控制该元数据的公开的更多详细信息。
### [](#server.link-builder.forwarded-headers)3.4。转发头处理
### 3.4.转发头处理
[RFC-7239 转发头](https://tools.ietf.org/html/rfc7239)通常用于应用程序位于代理、负载均衡器或云中。实际接收 Web 请求的节点是基础设施的一部分,*向前*是对应用程序的请求。
......@@ -407,7 +407,7 @@ var link = Affordances.of(linkTo(methodInvocation).withSelfRel()) (1)
要启用转发头处理,你需要在应用程序中注册 Spring MVC 的`ForwardedHeaderFilter`(details[here](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#filters-forwarded-headers))或 Spring WebFlux 的`ForwardedHeaderTransformer`(details[here](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-forwarded-headers))。在 Spring 引导应用程序中,这些组件可以简单地声明为 Spring bean,如[here](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container-servlets-filters-listeners-beans)所述。
例 17注册`ForwardedHeaderFilter`
例 17.注册`ForwardedHeaderFilter`
```
@Bean
......@@ -420,7 +420,7 @@ ForwardedHeaderFilter forwardedHeaderFilter() {
对于 Spring WebFlux 应用程序,对应的反应性是`ForwardedHeaderTransformer`:
例 18注册`ForwardedHeaderTransformer`
例 18.注册`ForwardedHeaderTransformer`
```
@Bean
......@@ -433,7 +433,7 @@ ForwardedHeaderTransformer forwardedHeaderTransformer() {
有了上面所示的配置,通过`X-Forwarded-…`头的请求将会看到那些反映在生成的链接中的请求:
例 19使用`X-Forwarded-…`头的请求
例 19.使用`X-Forwarded-…`头的请求
```
curl -v localhost:8080/employees \
......@@ -442,7 +442,7 @@ curl -v localhost:8080/employees \
-H 'X-Forwarded-Port: 9001'
```
例 20相应的响应与所生成的链接一起来考虑那些报头
例 20.相应的响应与所生成的链接一起来考虑那些报头
```
{
......@@ -474,7 +474,7 @@ curl -v localhost:8080/employees \
}
```
### [](#server.entity-links)3.5。[]()使用 EntityLinks 接口
### 使用 EntityLinks 接口
| |`EntityLinks`及其各种实现目前还没有为 Spring WebFlux 应用程序提供开箱即用的。<br/>`EntityLinks`SPI 中定义的契约最初是针对 Spring Web MVC 的,并不考虑反应器类型。<br/>开发支持反应式编程的类似契约仍在进行中。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
......@@ -491,7 +491,7 @@ Link link = links.linkToItemResource(Customer.class, 1L);
通过在 Spring MVC 配置中激活`@EnableHypermediaSupport`,通过依赖注入可以使用`EntityLinks`。这将导致`EntityLinks`的各种默认实现被注册。最基本的是`ControllerEntityLinks`,它检查 SpringMVC 控制器类。如果你想注册你自己的`EntityLinks`的实现,请查看[本节](#server.entity-links.spi)
#### [](#server.entity-links.controller)3.5.1。基于 Spring MVC 控制器的实体链接
#### 3.5.1.基于 Spring MVC 控制器的实体链接
激活实体链接功能将检查当前`ApplicationContext`中可用的所有 Spring MVC 控制器的`@ExposesResourceFor(…)`注释。注释公开了控制器管理的模型类型。除此之外,我们假定你遵循以下 URI 映射设置和约定:
......@@ -550,13 +550,13 @@ class PaymentController {
如你所见,你可以引用管理`Order`实例的资源,而不必显式地引用`OrderController`实例。
#### [](#server.entity-links.api)3.5.2。详细介绍 EntityLinks API
#### 3.5.2.详细介绍 EntityLinks API
从根本上说,`EntityLinks`允许将`LinkBuilder`s 和`Link`实例构建为实体类型的集合和项资源。以`linkFor…`开头的方法将产生`LinkBuilder`实例,供你扩展和增加额外的路径段、参数等。方法以`linkTo`为起点,生产制备充分的`Link`实例。
虽然对于集合资源来说,提供一个实体类型就足够了,但是指向项资源的链接将需要提供一个标识符。这通常看起来是这样的:
例 21获取到项目资源的链接
例 21.获取到项目资源的链接
```
entityLinks.linkToItemResource(order, order.getId());
......@@ -574,11 +574,11 @@ entityLinks.linkToItemResource(order, idExtractor); (2)
|-----|----------------------------------------------------------------------------------------|
|**2**|使用抽取器进行链接查找。|
##### [](#server.entity-links.api.typed)typedentylinks
##### typedentylinks
由于控制器实现通常是围绕实体类型进行分组的,因此你经常会发现自己在整个控制器类中使用相同的提取器函数(有关详细信息,请参见[详细介绍 EntityLinks API](#server.entity-links.api))。我们可以通过获得一个`TypedEntityLinks`实例来集中标识符提取逻辑,从而一次提供提取器,这样实际的查找就完全不必再处理提取了。
例 22使用 typedentitylinks
例 22.使用 typedentitylinks
```
class OrderController {
......@@ -604,11 +604,11 @@ class OrderController {
|**2**|表示你将使用特定的标识符提取器函数查找`Order`实例。|
|**3**|基于唯一的`Order`实例查找项目资源链接。|
#### [](#server.entity-links.spi)3.5.3。作为 SPI 的 EntityLink
#### 3.5.3.作为 SPI 的 EntityLink
`@EnableHypermediaSupport`创建的`EntityLinks`实例的类型为`DelegatingEntityLinks`,它将在`ApplicationContext`中以 bean 的形式获取所有其他`EntityLinks`实现。它被注册为 primary Bean,因此当你通常注入`EntityLinks`时,它始终是唯一的注入候选。`ControllerEntityLinks`是将包含在设置中的默认实现,但是用户可以自由地实现和注册自己的实现。使那些可用于`EntityLinks`实例可用于注入是将你的实现注册为 Spring Bean 的问题。
例 23声明自定义 EntityLinks 实现
例 23.声明自定义 EntityLinks 实现
```
@Configuration
......@@ -623,7 +623,7 @@ class CustomEntityLinksConfiguration {
这种机制的可扩展性的一个例子是 Spring data rest 的[`RepositoryEntityLinks`](https://github.com/ Spring-projects/ Spring-data-rest/blob/3a0cba94a2cc8739375ECF 24086da2f7c3bbf038/ Spring-data-rest-webmvc/mvc/main/main/java/org/repositorframework/data/data/repositforemframework/rest/spramework/sprint/springmvc/springmvc/support/support/sup 同时,它甚至还公开了其他类型资源的其他查找方法。如果你想要利用这些,只需显式地注入`RepositoryEntityLinks`
### [](#server.representation-model-assembler)3.6。[]()表示模型汇编器
### 3.6.表示模型汇编器
由于必须在多个地方使用从实体到表示模型的映射,因此创建一个专门的类来负责这样做是有意义的。转换包含非常自定义的步骤,但也包含一些样板步骤:
......@@ -670,7 +670,7 @@ PersonModel model = assembler.toModel(person);
CollectionModel<PersonModel> model = assembler.toCollectionModel(people);
```
### [](#server.processors)3.7。表示模型处理器
### 3.7.表示模型处理器
有时,你需要在超媒体表示[assembled](#server.representation-model-assembler)之后对其进行调整。
......@@ -758,7 +758,7 @@ public class PaymentProcessingApp {
同样,在这个示例中,`PaymentProcessor`改变了提供的`EntityModel<Order>`。你还可以用另一个对象替换它。请注意,API 要求返回类型等于输入类型。
### [](#server.rel-provider)3.8。[]()使用`LinkRelationProvider`API
### 3.8.使用`LinkRelationProvider`API
在构建链接时,通常需要确定要为该链接使用的关系类型。在大多数情况下,关系类型与(域)类型直接关联。我们封装了详细的算法来查找`LinkRelationProvider`API 背后的关系类型,该 API 允许你确定单个资源和集合资源的关系类型。查找关系类型的算法如下:
......@@ -772,15 +772,15 @@ public class PaymentProcessingApp {
当你使用`@EnableHypermediaSupport`时,`LinkRelationProvider`会自动暴露为 Spring Bean。你可以通过实现接口并将它们依次以 Spring bean 的形式公开来插入自定义提供程序。
## [](#mediatypes)4。媒体类型
## 4.媒体类型
### [](#mediatypes.hal)4.1。HAL-超文本应用程序语言
### 4.1.HAL-超文本应用程序语言
[JSON 超文本应用程序语言](https://tools.ietf.org/html/draft-kelly-json-hal-08)或 HAL 是最简单和最广泛采用的超媒体媒体类型之一,当不讨论特定的 Web 堆栈时采用。
这是 Spring Hateoas 采用的第一种基于规范的媒体类型。
#### [](#mediatypes.hal.models)4.1.1。HAL 表示模型的构建
#### 4.1.1.HAL 表示模型的构建
从 Spring Hateoas1.1 开始,我们提供了一个专用的`HalModelBuilder`,它允许通过一个 HAL 的惯用 API 创建`RepresentationModel`实例。这些是它的基本假设:
......@@ -884,13 +884,13 @@ HalModelBuilder.emptyHalModel()
}
```
#### [](#mediatypes.hal.configuration)4.1.2。配置链接呈现
#### 4.1.2.配置链接呈现
在 HAL 中,`_links`条目是一个 JSON 对象。属性名是[链接关系](#fundamentals.link-relations),每个值都是[链接对象或链接对象数组](https://tools.ietf.org/html/draft-kelly-json-hal-07#section-4.1.1)
对于具有两个或多个链接的给定的链接关系,规范在表示上是明确的:
例 24具有与一个关系相关联的两个链接的 HAL 文档
例 24.具有与一个关系相关联的两个链接的 HAL 文档
```
{
......@@ -908,7 +908,7 @@ HalModelBuilder.emptyHalModel()
默认情况下, Spring Hateoas 使用最简洁的方法,并呈现这样的单链接关系:
例 25以单个链接呈现为对象的 HAL 文档
例 25.以单个链接呈现为对象的 HAL 文档
```
{
......@@ -921,7 +921,7 @@ HalModelBuilder.emptyHalModel()
一些用户在使用 HAL 时不喜欢在数组和对象之间切换。他们更喜欢这种类型的渲染:
例 26以数组形式呈现单链路的 HAL
例 26.以数组形式呈现单链路的 HAL
```
{
......@@ -934,7 +934,7 @@ HalModelBuilder.emptyHalModel()
如果你希望自定义此策略,那么你所要做的就是在应用程序配置中注入`HalConfiguration` Bean。有多种选择。
例 27全局 HAL 单链路呈现策略
例 27.全局 HAL 单链路呈现策略
```
@Bean
......@@ -949,7 +949,7 @@ public HalConfiguration globalPolicy() {
如果你只希望覆盖某些特定的链接关系,那么可以创建一个`HalConfiguration` Bean,如下所示:
例 28基于链路关系的 HAL 单链路呈现策略
例 28.基于链路关系的 HAL 单链路呈现策略
```
@Bean
......@@ -968,7 +968,7 @@ public HalConfiguration linkRelationBasedPolicy() {
如果这两种方法都不符合你的需求,那么你可以使用 Ant 样式的路径模式:
例 29基于模式的 HAL 单链路呈现策略
例 29.基于模式的 HAL 单链路呈现策略
```
@Bean
......@@ -987,13 +987,13 @@ public HalConfiguration patternBasedPolicy() {
所有这些`HalConfiguration`威瑟斯可以组合成一个全面的政策。一定要广泛地测试你的 API,以避免出现意外。
#### [](#mediatypes.hal.i18n)4.1.3。链接标题国际化
#### 4.1.3.链接标题国际化
HAL 为其链接对象定义了`title`属性。这些标题可以通过使用 Spring 的资源包抽象和名为`rest-messages`的资源包来填充,以便客户可以直接在其 UIS 中使用它们。这个包将被自动设置,并在 HAL 链接序列化期间使用。
要为链接定义标题,请使用下面的键模板`_links.$relationName.title`:
例 30样本`rest-messages.properties`
例 30.样本`rest-messages.properties`
```
_links.cancel.title=Cancel order
......@@ -1002,7 +1002,7 @@ _links.payment.title=Proceed to checkout
这将产生以下 HAL 代表:
例 31定义了链接标题的 HAL 示例文档
例 31.定义了链接标题的 HAL 示例文档
```
{
......@@ -1019,7 +1019,7 @@ _links.payment.title=Proceed to checkout
}
```
#### [](#mediatypes.hal.curie-provider)4.1.4。[]()使用`CurieProvider`API
#### 使用`CurieProvider`API
[网络链接 RFC](https://tools.ietf.org/html/rfc8288#section-2.1)描述了注册和扩展链接关系类型。已注册的 REL 是用[IANA 链接关系类型注册表](https://www.iana.org/assignments/link-relations/link-relations.xhtml)注册的众所周知的字符串。扩展`rel`URI 可以被不希望注册关系类型的应用程序使用。每个 URI 都是唯一标识关系类型的 URI。`rel`URI 可以序列化为紧凑的 URI 或[Curie](https://www.w3.org/TR/curie)。例如,一个`ex:persons`的居里表示链接关系类型`[example.com/rels/persons](https://example.com/rels/persons)`,如果`ex`被定义为`[example.com/rels/{rel}](https://example.com/rels/{rel})`。如果使用 curies,则基本 URI 必须存在于响应范围中。
......@@ -1064,7 +1064,7 @@ public class Config {
由于`CurieProvider`API 的目的是允许自动创建居里,因此每个应用程序范围只能定义一个`CurieProvider` Bean。
### [](#mediatypes.hal-forms)4.2。HAL-表格
### 4.2.HAL-表格
[HAL-FORMS](https://rwcbook.github.io/hal-forms/)旨在向[HAL 媒体类型](#mediatypes.hal)添加运行时表单支持。
......@@ -1079,7 +1079,7 @@ public class Config {
要启用此媒体类型,请在代码中加入以下配置:
例 32HAL-支持表单的应用程序
例 32.HAL-支持表单的应用程序
```
@Configuration
......@@ -1091,7 +1091,7 @@ public class HalFormsApplication {
每当客户机提供带有`application/prs.hal-forms+json``Accept`头时,你可以预期这样的情况:
例 33HAL-表格样本文件
例 33.HAL-表格样本文件
```
{
......@@ -1140,7 +1140,7 @@ public class HalFormsApplication {
至于单项(`EntityModel`)和聚合根集合(`CollectionModel`), Spring Hateoas 将它们以相同的方式呈现为[HAL 文件](#mediatypes.hal)
#### [](#mediatypes.hal-forms.metadata)4.2.1。定义 HAL-表单元数据
#### 4.2.1.定义 HAL-表单元数据
HAL-表单允许描述每个表单字段的标准。 Spring Hateoas 允许通过为输入和输出类型塑造模型类型并在其上使用注释来定制这些类型。
......@@ -1167,7 +1167,7 @@ class CustomConfiguration {
此设置将使类型`CreditCardNumber`的表示模型属性的 HAL-Forms 模板属性声明一个`regex`字段,其值`[0-9]{16}`
#### [](#mediatypes.hal-forms.i18n)4.2.2。表单属性的国际化
#### 4.2.2.表单属性的国际化
HAL 窗体包含用于人工解释的属性,例如模板的标题或属性提示。这些可以使用 Spring 的资源包支持和由 Spring Hateoas 默认配置的`rest-messages`资源包来定义和国际化。
......@@ -1175,7 +1175,7 @@ HAL 窗体包含用于人工解释的属性,例如模板的标题或属性提
要定义模板标题,请使用以下模式:`_templates.$affordanceName.title`。注意,在 HAL 表单中,模板的名称是`default`,如果它是唯一的一个。这意味着你通常必须使用 Affordance 描述的本地或完全限定输入类型名称来限定密钥。
例 34定义 HAL-表单模板标题
例 34.定义 HAL-表单模板标题
```
_templates.default.title=Some title (1)
......@@ -1197,7 +1197,7 @@ com.acme.Employee._templates.default.title=Create employee (4)
还可以通过由 Spring Hateoas 自动配置的`rest-messages`资源包来解析属性提示。这些键可以全局定义、局部定义或完全限定,并且需要将`._prompt`连接到实际的属性键:
例 35`email`属性定义提示
例 35.`email`属性定义提示
```
firstName._prompt=Firstname (1)
......@@ -1212,7 +1212,7 @@ com.acme.Employee.firstName._prompt=Firstname (3)
同时定义了模板标题和属性提示的样例文档将如下所示:
例 36带有国际化模板标题和属性提示的示例 HAL 表单文档
例 36.带有国际化模板标题和属性提示的示例 HAL 表单文档
```
{
......@@ -1240,7 +1240,7 @@ com.acme.Employee.firstName._prompt=Firstname (3)
}
```
### [](#mediatypes.http-problem)4.3。HTTP 问题详细信息
### 4.3.HTTP 问题详细信息
[HTTP API 的问题细节](https://tools.ietf.org/html/rfc7807)是一种媒体类型,用于在 HTTP 响应中包含机器可读的错误详细信息,以避免需要为 HTTP API 定义新的错误响应格式。
......@@ -1324,7 +1324,7 @@ Problem.create(result.getDetails());
}
```
### [](#mediatypes.collection-json)4.4。Collection+JSON
### 4.4.Collection+JSON
[Collection+JSON](http://amundsen.com/media-types/collection/format/)是在 IANA 批准的媒体类型`application/vnd.collection+json`中注册的 JSON 规范。
......@@ -1339,7 +1339,7 @@ Problem.create(result.getDetails());
Collection+JSON 提供了一种统一的方式来表示单个项目资源以及集合。要启用此媒体类型,请在代码中加入以下配置:
例 37支持 Collection+JSON 的应用程序
例 37.支持 Collection+JSON 的应用程序
```
@Configuration
......@@ -1353,7 +1353,7 @@ public class CollectionJsonApplication {
下面的规范示例显示了一个单独的项目:
例 38集合 +JSON 单项示例
例 38.集合 +JSON 单项示例
```
{
......@@ -1430,7 +1430,7 @@ Spring Hateoas 更具体地说将:
* 每个条目级别`links`将包含来自`CollectionModel.content`的每个条目的所有其他链接。
### [](#mediatypes.uber)4.5。UBER-交换表示的统一基础
### 4.5.UBER-交换表示的统一基础
[UBER](https://rawgit.com/uber-hypermedia/specification/master/uber-hypermedia.html)是一种实验性的 JSON 规范
......@@ -1445,7 +1445,7 @@ Spring Hateoas 更具体地说将:
UBER 提供了一种统一的方式来表示单个项目资源以及集合。要启用此媒体类型,请在代码中加入以下配置:
例 39启用 UBER+JSON 的应用程序
例 39.启用 UBER+JSON 的应用程序
```
@Configuration
......@@ -1457,7 +1457,7 @@ public class UberApplication {
此配置将使你的应用程序使用`Accept``application/vnd.amundsen-uber+json`响应请求,如下所示:
例 40UBER 样本文件
例 40.UBER 样本文件
```
{
......@@ -1485,7 +1485,7 @@ public class UberApplication {
| |**UBER 媒体类型**与乘车共享公司**UBERTechnologies Inc.。**没有任何关联。|
|---|-----------------------------------------------------------------------------------------------------------|
### [](#mediatypes.alps)4.6。ALP-应用程序级配置文件语义
### 4.6.ALP-应用程序级配置文件语义
[ALPS](https://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-01)是一种媒体类型,用于提供有关另一资源的基于配置文件的元数据。
......@@ -1503,7 +1503,7 @@ public class UberApplication {
阿尔卑斯山不需要特殊的激活。相反,你“构建”一个`Alps`记录,并从 Spring MVC 或 Spring WebFlux Web 方法返回它,如下所示:
例 41创建`Alps`记录
例 41.创建`Alps`记录
```
@GetMapping(value = "/profile", produces = ALPS_JSON_VALUE)
......@@ -1537,7 +1537,7 @@ Alps profile() {
这个片段插入了测试数据。它产生了这样的 JSON:
例 42。阿尔卑斯山 JSON
例 42.ALPS JSON
```
{
......@@ -1586,11 +1586,11 @@ Alps profile() {
如果你愿意的话,你可以手工编写它们,而不是“自动”地将每个字段链接到域对象的字段。也可以使用 Spring 框架的消息包和`MessageSource`接口。这使你能够将这些值委托给特定于区域的消息包,甚至使元数据国际化。
### [](#mediatypes.community)4.7。基于社区的媒体类型
### 4.7.基于社区的媒体类型
由于[创建自己的媒体类型的能力](#mediatypes.custom),有几个社区领导的努力,以建立额外的媒体类型。
#### [](#mediatypes.community.json:api)4.7.1。JSON:API
#### 4.7.1.JSON:API
* [规格](https://jsonapi.org)
......@@ -1630,7 +1630,7 @@ implementation 'com.toedter:spring-hateoas-jsonapi:{see project page for current
如果你想要发布快照,请访问项目页面了解更多详细信息。
#### [](#mediatypes.community.siren)4.7.2。警报器
#### 4.7.2.警报器
* [规格](https://github.com/kevinswiber/siren)
......@@ -1661,7 +1661,7 @@ Gradle 坐标
implementation 'de.ingogriebsch.hateoas:spring-hateoas-siren:{see project page for current version}'
```
### [](#mediatypes.custom)4.8。注册自定义媒体类型
### 4.8.注册自定义媒体类型
Spring Hateoas 允许你通过 SPI 集成自定义媒体类型。这种实现的基本要素是:
......@@ -1671,7 +1671,7 @@ Spring Hateoas 允许你通过 SPI 集成自定义媒体类型。这种实现的
3. 一小部分基础设施配置,它将允许 Spring Hateoas 找到自定义实现并获取它。
#### [](#mediatypes.custom.configuration)4.8.1。自定义媒体类型配置
#### 4.8.1.自定义媒体类型配置
Spring Hateoas 通过扫描应用程序上下文以查找`HypermediaMappingInformation`接口的任何实现来获取自定义的媒体类型实现。每个媒体类型都必须实现这个接口,以便:
......@@ -1712,17 +1712,17 @@ Jackson 模块通常声明`Serializer`和`Deserializer`实现用于表示模型
| |以前的参考文档版本已经提到实现`MediaTypeConfigurationProvider`接口并将其注册为`spring.factories`<br/>这是不必要的。<br/>此 SPI 仅用于 Spring Hateoas 提供的开箱即用媒体类型。<br/>仅实现`HypermediaMappingInformation`接口将它注册为 Spring Bean 是所有需要的。|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### [](#mediatypes.custom.recommendation)4.8.2。建议
#### 4.8.2.建议
实现媒体类型表示的首选方法是提供与预期格式匹配的类型层次结构,并且可以按原样由 Jackson 序列化。在`Serializer``Deserializer``RepresentationModel`注册的实现中,将实例转换为特定于媒体类型的模型类型,然后为这些类型查找 Jackson 序列化器。
默认情况下支持的媒体类型使用与第三方实现相同的配置机制。因此,值得研究[the`mediatype`包](https://github.com/ Spring-projects/ Spring-hateoas/tree/master/SRC/main/java/org/springframework/hateoas/mediatype)中的实现。请注意,内置的媒体类型实现保持其配置类包的私有,因为它们是通过`@EnableHypermediaSupport`激活的。定制实现可能应该将这些公开,以确保用户可以从他们的应用程序包中导入这些配置类。
## [](#configuration)5。配置
## 5.配置
本节描述如何配置 Spring Hateoas。
### [](#configuration.at-enable)5.1。使用`@EnableHypermediaSupport`
### 5.1.使用`@EnableHypermediaSupport`
要让`RepresentationModel`子类型根据各种超媒体表示类型的规范来呈现,可以通过`@EnableHypermediaSupport`激活对特定超媒体表示格式的支持。注释以`HypermediaType`枚举作为参数。目前,我们支持[HAL](https://tools.ietf.org/html/draft-kelly-json-hal)以及默认呈现。使用注释将触发以下操作:
......@@ -1734,22 +1734,22 @@ Jackson 模块通常声明`Serializer`和`Deserializer`实现用于表示模型
* 它会自动拾取`RelProvider`中的所有`ApplicationContext`实现,并将它们捆绑到可以自动连接的`DelegatingRelProvider`中。它在 Spring MVC 控制器以及域类型上注册要考虑`@Relation`的提供者。如果[EVO 折弯机](https://github.com/atteo/evo-inflector)在 Classpath 上,则集合`rel`值是通过使用在库中实现的多元化算法派生的(参见[[[spis.rel-provider]])。
#### [](#configuration.at-enable.stacks)5.1.1。显式地启用对专用 Web 堆栈的支持
#### 5.1.1.显式地启用对专用 Web 堆栈的支持
默认情况下,`@EnableHypermediaSupport`将反射地检测你正在使用的 Web 应用程序堆栈,并将其钩入为这些组件注册的 Spring 组件,以支持超媒体表示。然而,在某些情况下,你只需要明确地激活对特定堆栈的支持。例如,如果你的 Spring 基于 WebMVC 的应用程序使用 WebFlux’`WebClient`发出请求,而其中一个不应该与超媒体元素一起工作,那么你可以通过在配置中显式声明 WebMVC 来限制所启用的功能:
例 43显式地激活对特定 Web 堆栈的超媒体支持
例 43.显式地激活对特定 Web 堆栈的超媒体支持
```
@EnableHypermediaSupport(…, stacks = WebStack.WEBMVC)
class MyHypermediaConfiguration { … }
```
## [](#client)6。客户端支持
## 6.客户端支持
本节描述 Spring Hateoas 对客户的支持。
### [](#client.traverson)6.1。特拉弗森
### 6.1.Traverson
Spring Hateoas 为客户端服务遍历提供了一个 API。它的灵感来自[Traverson JavaScript 函式库](https://blog.codecentric.de/en/2013/11/traverson/)。下面的示例展示了如何使用它:
......@@ -1816,7 +1816,7 @@ CollectionModel<Item> itemResource = traverson.//
它不是获取单个资源,而是将集合反序列化为`CollectionModel`
### [](#client.link-discoverer)6.2。使用`LinkDiscoverer`实例
### 6.2.使用`LinkDiscoverer`实例
在使用启用超媒体的表示时,一个常见的任务是在其中找到具有特定关系类型的链接。 Spring Hateoas 提供了基于的接口的实现方式,用于呈现或开箱即用的默认表示或 HAL。当使用`@EnableHypermediaSupport`时,我们会自动将支持配置的超媒体类型的实例公开为 Spring Bean。
......@@ -1831,11 +1831,11 @@ assertThat(link.getRel(), is("foo"));
assertThat(link.getHref(), is("/foo/bar"));
```
### [](#client.web-client)6.3。配置 WebClient 实例
### 6.3.配置 WebClient 实例
如果你需要配置一个`WebClient`来说超媒体,这很容易。获取`HypermediaWebClientConfigurer`,如下所示:
例 44自己配置`WebClient`
例 44.自己配置`WebClient`
```
@Bean
......@@ -1853,7 +1853,7 @@ WebClient.Builder hypermediaWebClient(HypermediaWebClientConfigurer configurer)
如果你正在使用 Spring boot,还有另一种方法:`WebClientCustomizer`
例 45让 Spring 引导配置事物
例 45.让 Spring 引导配置事物
```
@Bean (4)
......@@ -1872,13 +1872,13 @@ WebClientCustomizer hypermediaWebClientCustomizer(HypermediaWebClientConfigurer
在此阶段,每当你需要一个具体的`WebClient`时,只需将`WebClient.Builder`注入到你的代码中,并使用`build()``WebClient`实例将能够使用超媒体进行交互。
### [](#client.web-test-client)6.4。配置`WebTestClient`实例
### 6.4.配置`WebTestClient`实例
在使用启用超媒体的表示时,一个常见的任务是使用`WebTestClient`运行各种测试。
要在测试用例中配置`WebTestClient`的实例,请查看以下示例:
例 46在使用 Spring hateoas 时配置`WebTestClient`
例 46.在使用 Spring hateoas 时配置`WebTestClient`
```
@Test // #1225
......@@ -1925,7 +1925,7 @@ void webTestClientShouldSupportHypermediaDeserialization() {
如果你正在使用 Spring 引导,还有其他选项,例如:
例 47在使用 Spring 引导时配置`WebTestClient`
例 47.在使用 Spring 引导时配置`WebTestClient`
```
@SpringBootTest
......@@ -1956,11 +1956,11 @@ class WebClientBasedTests {
还有许多其他方法来设计测试用例。`WebTestClient`可以绑定到控制器、函数和 URL。这一节并不是要展示这一切。相反,这为你提供了一些可以开始使用的示例。重要的是,通过应用`HypermediaWebTestClientConfigurer`,可以修改`WebTestClient`的任何实例来处理超媒体。
### [](#client.rest-template)6.5。配置 RESTTemplate 实例
### 6.5.配置 RESTTemplate 实例
如果你想创建自己的`RestTemplate`副本,并将其配置为说超媒体语言,则可以使用`HypermediaRestTemplateConfigurer`:
例 48配置`RestTemplate`自己
例 48.配置`RestTemplate`自己
```
/**
......@@ -1992,7 +1992,7 @@ RestTemplate hypermediaRestTemplate(HypermediaRestTemplateConfigurer configurer)
要注册基于超媒体的消息转换器,请在代码中添加以下内容:
例 49让 Spring 引导配置事物
例 49.让 Spring 引导配置事物
```
@Bean (4)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册