在[ Building links in Spring MVC](#server.link-builder.webmvc)和[Building links in Spring WebFlux](#server.link-builder.webflux)中找到有关如何创建指向 Spring MVC 和 Spring WebFlux 控制器的链接的更多信息。
### 2.2.URI 模板
对于 Spring Hateoas`Link`,超文本引用不仅可以是一个 URI,而且根据[RFC-6570](https://tools.ietf.org/html/rfc6570)也可以是一个 URI 模板。URI 模板包含所谓的模板变量,并允许扩展这些参数。这允许客户机将参数化模板转换为 URI,而无需了解最终 URI 的结构,只需了解变量的名称即可。
例 4.使用带有模板化 URI 的链接
```
Link link = Link.of("/{segment}/something{?parameter}");
Spring 为了方便地创建富含超媒体的表示,Hateoas 提供了一组在其根上带有`RepresentationModel`的类。它基本上是一个`Link`s 集合的容器,并且有方便的方法将它们添加到模型中。模型稍后可以呈现为各种媒体类型格式,这些格式将定义超媒体元素在表示中的外观。有关此的更多信息,请查看[媒体类型](#mediatypes)。
`WebMvcLinkBuilder`在引擎盖下使用 Spring 的`ServletUriComponentsBuilder`从当前请求中获得基本的 URI 信息。假设你的应用程序运行在`[localhost:8080/your-app](http://localhost:8080/your-app)`,那么这正是你正在构建附加部分的 URI。构建器现在检查给定的控制器类的根映射,并以`[localhost:8080/your-app/people](http://localhost:8080/your-app/people)`结束。你还可以构建更多的嵌套链接。下面的示例展示了如何做到这一点:
```
Person person = new Person(1L, "Dave", "Matthews");
// /person / 1
Link link = linkTo(PersonController.class).slash(person.getId()).withSelfRel();
基于 REST 的资源不仅提供数据,还提供控制。形成灵活服务的最后一个要素是关于如何使用各种控件的详细说明**启示**。 Spring 由于提供与链接相关联,Hateoas 提供了一个 API,以便根据需要将尽可能多的相关方法附加到链接上。正如你可以通过指向 Spring MVC 控制器方法来创建链接一样(有关详细信息,请参见[ Building links in Spring MVC](#server.link-builder.webmvc)),你…
下面的代码展示了如何使用**自我**链接并关联另外两个启示:
例 13.连接到`GET /employees/{id}`的启示
```
@GetMapping("/employees/{id}")
public EntityModel<Employee> findOne(@PathVariable Integer id) {
[RFC-7239 转发头](https://tools.ietf.org/html/rfc7239)通常用于应用程序位于代理、负载均衡器或云中。实际接收 Web 请求的节点是基础设施的一部分,*向前*是对应用程序的请求。
你的应用程序可能运行在`localhost:8080`上,但是对于外部世界来说,你应该运行在`reallycoolsite.com`上(以及 Web 的标准端口 80 上)。通过使代理包括额外的头(许多人已经这样做了), Spring Hateoas 可以在使用 Spring 框架功能来获得原始请求的基本 URI 时正确地生成链接。
| |任何可以根据外部输入改变根 URI 的内容都必须得到适当的保护,<br/>这就是为什么,默认情况下,转发头处理是**已禁用**。<br/>你必须使其能够运行。<br/>如果你要部署到云或控制代理和负载均衡器的配置中,那么你肯定想要使用此功能。|
要启用转发头处理,你需要在应用程序中注册 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)所述。
由`@EnableHypermediaSupport`创建的`EntityLinks`实例的类型为`DelegatingEntityLinks`,它将在`ApplicationContext`中以 bean 的形式获取所有其他`EntityLinks`实现。它被注册为 primary Bean,因此当你通常注入`EntityLinks`时,它始终是唯一的注入候选。`ControllerEntityLinks`是将包含在设置中的默认实现,但是用户可以自由地实现和注册自己的实现。使那些可用于`EntityLinks`实例可用于注入是将你的实现注册为 Spring Bean 的问题。
例 23.声明自定义 EntityLinks 实现
```
@Configuration
class CustomEntityLinksConfiguration {
@Bean
MyEntityLinks myEntityLinks(…) {
return new MyEntityLinks(…);
}
}
```
这种机制的可扩展性的一个例子是 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`。
在 HAL 中,`_links`条目是一个 JSON 对象。属性名是[链接关系](#fundamentals.link-relations),每个值都是[链接对象或链接对象数组](https://tools.ietf.org/html/draft-kelly-json-hal-07#section-4.1.1)。
HAL 为其链接对象定义了`title`属性。这些标题可以通过使用 Spring 的资源包抽象和名为`rest-messages`的资源包来填充,以便客户可以直接在其 UIS 中使用它们。这个包将被自动设置,并在 HAL 链接序列化期间使用。
要为链接定义标题,请使用下面的键模板`_links.$relationName.title`:
例 30.样本`rest-messages.properties`
```
_links.cancel.title=Cancel order
_links.payment.title=Proceed to checkout
```
这将产生以下 HAL 代表:
例 31.定义了链接标题的 HAL 示例文档
```
{
"_links" : {
"cancel" : {
"href" : "…"
"title" : "Cancel order"
},
"payment" : {
"href" : "…"
"title" : "Proceed to checkout"
}
}
}
```
#### 使用`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 必须存在于响应范围中。
由默认`RelProvider`创建的`rel`值是扩展关系类型,因此必须是 URI,这可能会导致大量的开销。`CurieProvider`API 负责这一点:它允许你将一个基本 URI 定义为一个 URI 模板和一个代表该基本 URI 的前缀。如果存在`CurieProvider`,则`RelProvider`前置所有带有居里前缀的`rel`值。此外,`curies`链接被自动地添加到 HAL 资源中。
Jackson 模块通常声明`Serializer`和`Deserializer`实现用于表示模型类型`RepresentationModel`、`EntityModel`、`CollectionModel`和`PagedModel`。如果需要对 Jackson`ObjectMapper`进行进一步的自定义(如自定义`HandlerInstantiator`),则可以替代地覆盖`configureObjectMapper(…)`。
| |以前的参考文档版本已经提到实现`MediaTypeConfigurationProvider`接口并将其注册为`spring.factories`。<br/>这是不必要的。<br/>此 SPI 仅用于 Spring Hateoas 提供的开箱即用媒体类型。<br/>仅实现`HypermediaMappingInformation`接口将它注册为 Spring Bean 是所有需要的。|
实现媒体类型表示的首选方法是提供与预期格式匹配的类型层次结构,并且可以按原样由 Jackson 序列化。在`Serializer`和`Deserializer`为`RepresentationModel`注册的实现中,将实例转换为特定于媒体类型的模型类型,然后为这些类型查找 Jackson 序列化器。
* 它会自动拾取`RelProvider`中的所有`ApplicationContext`实现,并将它们捆绑到可以自动连接的`DelegatingRelProvider`中。它在 Spring MVC 控制器以及域类型上注册要考虑`@Relation`的提供者。如果[EVO 折弯机](https://github.com/atteo/evo-inflector)在 Classpath 上,则集合`rel`值是通过使用在库中实现的多元化算法派生的(参见[[[spis.rel-provider]])。
#### 5.1.1.显式地启用对专用 Web 堆栈的支持
默认情况下,`@EnableHypermediaSupport`将反射地检测你正在使用的 Web 应用程序堆栈,并将其钩入为这些组件注册的 Spring 组件,以支持超媒体表示。然而,在某些情况下,你只需要明确地激活对特定堆栈的支持。例如,如果你的 Spring 基于 WebMVC 的应用程序使用 WebFlux’`WebClient`发出请求,而其中一个不应该与超媒体元素一起工作,那么你可以通过在配置中显式声明 WebMVC 来限制所启用的功能:
在使用启用超媒体的表示时,一个常见的任务是在其中找到具有特定关系类型的链接。 Spring Hateoas 提供了基于的接口的实现方式,用于呈现或开箱即用的默认表示或 HAL。当使用`@EnableHypermediaSupport`时,我们会自动将支持配置的超媒体类型的实例公开为 Spring Bean。