HATEOAS的RESTful服务。 超媒体:REST的秘密要素

在这篇文章中,我们将介绍有关HATEOAS的RESTful服务的综合文章。 超媒体是REST的秘密成分。

1.简介

在本教程的前一部分中,我们花了一些时间来刷新有关REST体系结构样式的基本原理的知识。 业界对REST状态的批判性眼光揭示了一个令人失望的事实,即它经常被完全忽略,它的关键约束之一,即作为应用程序状态引擎( HATEOAS )的超媒体 。

目录

1.简介 2.这些“噪音”是什么? 3.野外的HATEOAS
3.1。 RFC 5988(网络链接) 3.2。 哈尔 3.3。 JSON:API 3.4。 JSON-LD 3.5。 警笛 3.6。 集合+ JSON 3.7。 优步 3.8。 亚哈皮 3.9。 石匠 3.10。 离子
4. HATEOAS的成本 5.案例研究 6。结论 7.接下来

超媒体由嵌入在信息表示中或作为信息表示之上的应用程序控制信息的存在来定义。 分布式超媒体允许将表示和控制信息存储在远程位置。

https://www.ics.uci.edu/~fielding/pubs/dissertation/web_arch_domain.htm#sec_4_1_3

这部分的主题是超媒体 ,尤其是HATEOAS 。 希望我们不仅可以确信它的重要性,而且可以支持许多策略,以利用超媒体功能丰富我们的REST Web服务和API。

2.这些“噪音”是什么?

众所周知,无状态是REST体系结构风格的强制性约束之一。 另一方面,绝大多数现实世界的Web服务和API必须处理状态管理。 看起来REST忽略了现代软件系统的现实和需求吗?

绝对不是, REST体系结构风格承认状态管理的重要性,并以超媒体 (应用程序状态引擎)的形式提出了解决方案。 在服务器端, 超媒体的使用不仅通告资源之间的关系,而且通告可能潜在地应用于该资源的动作。 在客户端, 超媒体的存在带来了可发现性方面的下一步行动,步骤或要进行的状态转换。 理想情况下,客户端只需要知道一个URI入口点,其他所有内容都可以通过hypermedia来自服务器。

显然,客户端必须足够聪明,才能以可行的方式浏览超媒体控件。 正如许多经验丰富的Web服务和API开发人员已经注意到的那样,服务器上的超媒体支持并不是那么困难,而客户端则要困难得多。

但是,在Web服务和API的上下文中, 超媒体到底是什么? 我们可以将其视为服务器随响应发送给客户端的附加元信息。 它主要包括相关资源的链接,最重要的是,适用于所讨论资源以更改其状态的上下文操作。

当我说超文本时,我的意思是信息和控件的同时呈现,从而使信息成为用户通过其获得选择和选择动作的能力。 超媒体只是文本在媒体流中包含时间锚点的扩展。 大多数研究人员已经放弃了区分。

https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-718

总之,这些元数据片段告诉客户端在哪里获取更多数据或在当前上下文中哪种操作有效。 如果您觉得这很刺激,那确实是。

因此,我们讨论了什么是超媒体以及它在REST体系结构风格中的重要地位,现在该是我们讨论超媒体的“方式”的时候了。

3.野外的HATEOAS

仅重申我们在上一部分中所说的内容, REST体系结构样式要求使用超媒体 ,但未指定如何使用它。 显然,这个漏洞必须关闭,并且多年来导致了各种样式和规格的泛滥。 许多公司走得更远,提出了自己的超媒体类型,蓝图和建议。

超媒体类型是MIME媒体类型,其中包含导致应用程序流的本机超链接语义。 例如,HTML是一种超媒体类型。 XML不是。

http://amundsen.com/hypermedia/

令人惊讶的是,到目前为止,还没有一个普遍接受的标准可以遵循,以使用超媒体元素来授权Web服务和API。 一些或多或少被广泛采用,而另一些则占据相当狭窄的位置。 而且,大多数规范仍在发展之中,并且在进行中时被广告宣传。

为什么会有这么多规格,主要区别是什么? 总的来说,罪恶源于细节,更具体地说,是描述相关资源,链接和动作/操作。 如何找到最适合您的? 坦白地说,选择合适的规范会直接影响支持该规范所需的工作量。 如果是未开发的Web服务或API,您几乎可以自由选择。 相比之下,当您维护现有的Web服务或API并通过超媒体支持对其进行丰富的任务时,选择突然变得非常有限(除非您拥有完全重写的特权)。

从实现的角度来看,大多数规范都倾向于使用JSON格式来表示资源状态和超媒体控件。 但是,有些异常值会改用HTTP协议标头。 这当然不是REST架构风格所决定的,而是来自现代Web服务和API的现实,它们都是面向HTTP的。

因此,这些规格是什么?

RFC 5988(网络链接)

我们将从RFC-5988:Web链接开始 。 它为Web链接指定关系类型,为它们定义注册表,还定义HTTP头中带有特殊Link头的此类链接的使用。 这是一个简单的示例:

Link: <https://rentals.jcg.com/reservations>; rel="self"; title="reservations"

可以肯定的是, Link头(或多个Link头)中编码的Link可能不止一个,例如:

Link: <https://rentals.jcg.com/reservations?page=1>; rel="previous"; title="previous page", 
<https://rentals.jcg.com/reservations?page=3>; rel="next"; title="next page"

Web链接是引入超媒体支持的最基本,最简单的方法。 不管是使用新的还是现有的API,都可以很容易地将其接受,但是从功能角度来看, Web链接提供的选项集非常有限,主要是简单的关系,并且不支持动作和集合 。

哈尔

JSON超媒体API语言或HAL建立使用JSON表示超媒体控件(链接和资源)的约定。 它由Mike Kelly于2011年创建。Web服务和API发出HAL文档,以便客户端可以提取适当的链接,并根据它们的关系类型在它们之间进行导航。

尽管HAL规范仍处于起草阶段 ,但其设计原理使其成为了由超媒体驱动的现代Web服务和API的最佳选择之一。

HAL的主要设计目标是通用性和简单性。 HAL可以应用于许多不同的域,并施加了满足超媒体API关键要求所需的最少结构量。

https://tools.ietf.org/id/draft-kelly-json-hal-02.html

您可能会猜到,资源表示形式是JSON格式的HAL文档 ,这些文档使用专用的媒体类型application/hal+json

{"_embedded": {"reservations": [ {"id": "ce5886acbb87","vehicle": "Volkswagen Golf 1.2 TSI","from": "2020-02-01","to": "2020-02-12","_links": {"self": {"href": "https://rentals.jcg.com/reservations/ce5886acbb87"},"customer": {"href": "https://rentals.jcg.com/customers/fed195a03e9d"}}}, {"id": "fc14e8ef90f5","vehicle": "BMW 325i","from": "2020-01-10","to": "2020-01-12","_links": {"self": {"href": "https://rentals.jcg.com/reservations/fc14e8ef90f5"},"customer": {"href": "https://rentals.jcg.com/customers/fed195a03e9d"}}} ]},"_links": {"first": {"href": "https://rentals.jcg.com/reservations?page=0&size=10"},"self": {"href": "https://rentals.jcg.com/reservations?page=0&size=10"},"next": {"href": "https://rentals.jcg.com/reservations?page=1&size=10"},"last": {"href": "https://rentals.jcg.com/reservations?page=1&size=10"}},"page": {"size": 10,"totalElements": 13,"totalPages": 2,"number": 0}
}

除此之外, HAL还支持URI模板和链接关系文档。 不幸的是, HAL不提供任何行动支持(您可能听说过的另一个名字是Provided )。 试图填补HAL空白的衍生规范之一是HAL-FORMS 。 从本质上讲,它只是HAL的扩展,通过表达方法和属性的能力来增强它。

{                                                                       "id": "13e1892765c5",                                                "vehicle": "Honda Civic 2020",                                       "from": "2020-01-01",                                                "to": "2020-01-05",                                                  "_links": {                                                          "customer": {                                                      "href": "https://rentals.jcg.com/customers/fed195a03e9d"           },                                                                  "self": {                                                          "href": "https://rentals.jcg.com/reservations/13e1892765c5"        }                                                                   },                                                                    "_templates": {                                                      "default": {                                                       "method": "put",                                                 "properties": [ {                                                "name": "from","regex" : "yyyy-MM-dd","required": true}, {                                                              "name": "to","regex" : "yyyy-MM-dd","required": true}, {                                                              "name": "vehicle"                                              } ]                                                               },                                                                  "delete": {                                                        "method": "delete",                                              "properties": [ ]                                                }                                                                   }                                                                     
}

请注意, HAL-FORMS旨在仅显示针对同一资源(或URI)可用的操作。 如果是JSON表示形式,则会为HAL-FORMS分配专用的媒体类型application/prs.hal-forms+json

JSON:API

JSON:API是受超媒体支持的Web服务和API的最广泛支持的标准之一。 它最初是由Yehuda Katz于2013年起草的,此后越来越受欢迎。 您可能会猜到,它仅适用于JSON表示形式。

JSON:API旨在最大程度地减少请求数量和客户端与服务器之间传输的数据量。 在不影响可读性,灵活性或可发现性的情况下实现了这种效率。

https://jsonapi.org/format/

JSON:API规范描述了链接,资源关系和资源修改(相当于动作)的语义。 另外,它涵盖了表示错误的方式。

{                                                                                                             "data": {                                                                                                  "id": "13e1892765c5",                                                                                    "type": "reservation",                                                                                   "links": {                                                                                               "self": "https://rentals.jcg.com/reservations/13e1892765c5"},                                                                                                        "attributes": {                                                                                          "from": "2020-01-01",                                                                                  "to": "2020-01-05",                                                                                    "vehicle": "Honda Civic 2020"                                                                          },                                                                                                        "relationships": {                                                                                       "customer": {                                                                                          "links": {                                                                                           "self": "https://rentals.jcg.com/reservations/13e1892765c5/relationships/customer",              "related": "https://rentals.jcg.com/reservations/13e1892765c5/customer"                          }                                                                                                     }                                                                                                       }                                                                                                         }
}

使JSON:API脱颖而出的原因是,考虑了诸如排序,过滤,稀疏字段集和分页之类的获取(查询)模式,这些模式也是规范的一部分。

{"data": [{"id": "ce5886acbb87","type": "reservation","links": {"self": "https://rentals.jcg.com/reservations/ce5886acbb87"},"attributes": {"from": "2020-01-01","to": "0120-01-12","vehicle": "Volkswagen Golf 1.2 TSI"},"relationships": {"customer": {"links": {"self": "https://rentals.jcg.com/reservations/ce5886acbb87/relationships/customer","related": "https://rentals.jcg.com/reservations/ce5886acbb87/customer"}}}},{"id": "fc14e8ef90f5","type": "reservation","links": {"self": "https://rentals.jcg.com/reservations/fc14e8ef90f5"},"attributes": {"from": "2020-01-10","to": "2020-01-12","vehicle": "BMW 325i"},"relationships": {"customer": {"links": {"self": "https://rentals.jcg.com/reservations/fc14e8ef90f5/relationships/customer","related": "https://rentals.jcg.com/reservations/fc14e8ef90f5/customer"}}}}],"links": {"first": "https://rentals.jcg.com/reservations?page[limit]=2","last": "https://rentals.jcg.com/reservations?page[limit]=2&page[offset]=2","next": "https://rentals.jcg.com/reservations?page[limit]=2&page[offset]=2"},"meta": {"totalResourceCount": 3}
}

公平地说, JSON:API具有非常简单,可读和可理解的格式。 为了实现这种折衷,它做出了一些明智的决定。 例如,您不会直接在JSON:API文档中看到操作。 实际上,它们根据HTTP协议是隐式和隐式的: POST用于创建, PATCH用于修改, DELETE用于删除。 这可能给客户带来一些解释上的困难,例如, PUT在哪里 ?

尽管JSON:API规范的1.0版在2015年开始亮相,但它正在积极地研究之中,并被认为是一个不断发展的文档。 JSON:API已正确注册了媒体类型名称application/vnd.api+json并且还拥有自己的JSON模式 定义 。

JSON-LD

JSON-LD是链接数据的基于JSON的序列化,在2014年就获得了W3C候选正式建议的地位。它可能是最活跃的社区,而该规范的最新版本JSON-LD 1.1的字面意思是已发布。一个月前。 JSON-LD设计背后的关键原则强调能够轻松集成到已经使用JSON的现有系统中,并使用JSON-LD语义对其进行扩充,而不会破坏已建立的联系。

可以肯定地说, JSON-LD与链接数据有关的不是超媒体,而是其表达信息,上下文和关系的丰富功能非常适合某些超媒体承诺。

{                                                               "@context": {                                                "@vocab": "http://schema.org/"                             },                                                            "@type": "Reservation",                                      "id": "13e1892765c5",                             "vehicle": "Honda Civic 2020",                               "from": "2020-01-01",                      "to": "2020-01-05",                        "customer": {                                                "@id": "https://rentals.jcg.com/customers/fed195a03e9d"      },                                                            "@id": "https://rentals.jcg.com/reservations/13e1892765c5"     
}

JSON-LD的缺点之一是它缺乏对动作的支持。 Hydra解决了JSON-LD的主要缺点, Hydra是超媒体驱动的Web服务和API的词汇。

Hydra的基本思想是提供一个词汇表,该词汇表可使服务器将有效的状态转换通告给客户端。 然后,客户端可以使用此信息来构造HTTP请求,该请求将修改服务器的状态,从而实现某个所需的目标。

http://www.hydra-cg.com/spec/latest/core/#hydra-at-a-glance

为了了解它是如何工作的,让我们看一下使用Hydra语义丰富的JSON-LD文档的快速示例。

{"@context": {"@vocab": "http://schema.org/","hydra": "http://www.w3.org/ns/hydra/core#"},"@type": "hydra:Collection","hydra:collection": [ {"@type": "hydra:Collection","@id": "https://rentals.jcg.com/reservations","hydra:manages": {"hydra:property": "self","hydra:subject": "https://rentals.jcg.com/reservations"},"hydra:operation": [ {"hydra:method": "GET"} ]} ],"hydra:member": [ {"@type": "Reservation","vehicle": "Volkswagen Golf 1.2 TSI","from": "2020-02-01","to": "2020-02-12","customer": {"@id": "https://rentals.jcg.com/customers/fed195a03e9d","hydra:operation": [ {"hydra:method": "GET"} ]},"@id": "https://rentals.jcg.com/reservations/ce5886acbb87","hydra:operation": [ {"hydra:method": "GET"}, {"hydra:method": "PUT","hydra:expects": {"@type": "UpdateReservation","hydra:supportedProperty": [ {"hydra:property": "from"}, {"hydra:property": "to"}, {"hydra:property": "vehicle"} ]}}, {"hydra:method": "DELETE"} ],"id": "ce5886acbb87"}, {"@type": "Reservation","vehicle": "BMW 325i","from": "2020-01-10","to": "2020-01-12","customer": {"@id": "https://rentals.jcg.com/customers/fed195a03e9d","hydra:operation": [ {"hydra:method": "GET"} ]},"@id": "https://rentals.jcg.com/reservations/fc14e8ef90f5","hydra:operation": [ {"hydra:method": "GET"}, {"hydra:method": "PUT","hydra:expects": {"@type": "UpdateReservation","hydra:supportedProperty": [ {"hydra:property": "from"}, {"hydra:property": "to"}, {"hydra:property": "vehicle"} ]}}, {"hydra:method": "DELETE"} ],"id": "fc14e8ef90f5"} ],"hydra:totalItems": 3,"hydra:view": {"@type": "hydra:PartialCollectionView","hydra:next": "https://rentals.jcg.com/reservations?page=1&size=2","hydra:first": "https://rentals.jcg.com/reservations?page=0&size=2","hydra:last": "https://rentals.jcg.com/reservations?page=1&size=2"}
}

再重申一次, JSON-LD的最强之处是数据链接。 与Hydra结合使用,您的Web服务和API将获得成熟的超媒体功能,但是集成可能并不像人们期望的那么容易。 JSON-LD具有保留的媒体application/ld+json

警笛

Siren由Kevin Swiber于2012年撰写,是用于表示实体的超媒体规范。 Siren词汇表中的实体是URI可寻址资源,具有与之关联的属性,操作和可导航链接。 值得注意的是, Siren是专门为Web服务和API设计的,例如,动作可以直接映射到HTTP协议动词。

{                                                                                                    "class": [ "reservation" ],                                                                       "properties": {                                                                                   "id": "13e1892765c5",                                                                "from": "2020-01-01","to": "2020-01-05", "vehicle": "Honda Civic 2020"                                                                   },                                                                                                 "entities": [ {                                                                                   "rel": [ "customer" ],                                                                          "href": "https://rentals.jcg.com/customers/fed195a03e9d"                                          }, {                                                                                               "class": [ "customer" ],                                                                        "rel": [ "http://schema.org/customer" ],                                                        "properties": {                                                                                 "firstName": "John",                                                                          "lastName": "Smith",                                                                          "id" : "fed195a03e9d"                                                                  }                                                                                                } ],                                                                                               "actions": [ {                                                                                    "name": "update",                                                                               "method": "PUT",                                                                                "href": "https://rentals.jcg.com/reservations/13e1892765c5",                                      "fields": [ {                                                                                   "name": "from",                                                                               "type": "date"                                                                                }, {                                                                                             "name": "to",                                                                                 "type": "date"                                                                                }, {                                                                                             "name": "vehicle",                                                                            "type": "text"                                                                                } ]                                                                                              }, {                                                                                               "name": "delete",                                                                               "method": "DELETE",                                                                             "href": "https://rentals.jcg.com/reservations/13e1892765c5"                                       } ],                                                                                               "links": [ {                                                                                      "rel": [ "self" ],                                                                              "href": "https://rentals.jcg.com/reservations/13e1892765c5"                                       } ]                                                                                                
}

尽管年代久远, Siren仍被列为进行中的作品。 它本身不像HAL或JSON:API那样流行,但是它相对简单和Web API优先语义使其成为值得考虑的选项。 Siren JSON表示形式的媒体类型为application/vnd.siren+json

集合+ JSON

由Mike Amundsen在2011年创建的Collection + JSON规范旨在成为一种超媒体类型,旨在支持读取,编写和查询简单集合。 它在某种程度上受到Atom联合格式(RFC-4287)和Atom发布协议(RFC-5023)的启发。 关于Collection + JSON的一个有趣事实是,它将所有内容都视为一个集合,因此,单个项目表示为一个元素的集合。

{"collection": {"version": "1.0","href": "https://rentals.jcg.com/reservations/13e1892765c5","links": [ {"rel": "customer","href": "https://rentals.jcg.com/customers/fed195a03e9d"} ],"items": [ {"href": "https://rentals.jcg.com/reservations/13e1892765c5","data": [ {"name": "from","value": "2020-01-01"}, {"name": "id","value": "13e1892765c5"}, {"name": "to","value": "2020-01-05"}, {"name": "vehicle","value": "Honda Civic 2020"} ],"links": [ {"rel": "customer","href": "https://rentals.jcg.com/customers/fed195a03e9d"} ]} ],"template": {"data": [ {"name": "from","value": ""}, {"name": "to","value": ""}, {"name": "vehicle","value": ""} ]}}
}

您可能会猜到, Collection + JSON标准非常适合列表和集合。 它还包括对查询模板 (链接和关系)和写模板 (操作)的支持,以及标准化的错误报告。

在某些时候, Collection + JSON非常流行,但是与其他替代方案相比,它实现起来可能更困难。 同样,对“万物都是收藏”的偏见是不直观的。

Collection + JSON的媒体类型为application/vnd.collection+json

优步

UBER 超媒体类型描述了对简单状态转移和临时转移的支持。 它是由Mike Amundsen (是Collection + JSON的作者)和Irakli Nadareishvili于2014年左右共同创建的,同时针对XML和JSON变体。

那么,作者提出另一种超媒体类型的动机是什么? 迈克·阿蒙森 ( Mike Amundsen)的这则推文使推理过程更加清晰。

Collection + JSON是高度结构化的CRUD格式。 HAL适用于内联超媒体, Siren具有丰富的obj模型。 UBER开放且极简。

https://twitter.com/mamund/status/456508872832716800

UBER文档支持链接关系,操作和错误报告机制。 该规范旨在与多种协议一起使用,但包括有关基于HTTP的实现和解释的详细指南。

{"uber": {"version": "1.0","data": [ {"name": "customer","rel": [ "customer" ],"url": "https://rentals.jcg.com/customers/fed195a03e9d"}, {"name": "self","rel": [ "self" ],"url": "https://rentals.jcg.com/reservations/13e1892765c5"}, {"name": "update","rel": [ "update" ],"url": "https://rentals.jcg.com/reservations/13e1892765c5","action": "replace","model": "from={from}&to={to}&vehicle={vehicle}"}, {"name": "delete","rel": [ "delete" ],"url": "https://rentals.jcg.com/reservations/13e1892765c5","action": "remove","model": ""}, {"name": "reservation","data": [ {"name": "from","value": "2020-01-01"}, {"name": "id","value": "13e1892765c5"}, {"name": "to","value": "2020-01-05"}, {"name": "vehicle","value": "Honda Civic 2020"} ]} ]}
}

自2016年以来,它仍被标记为草稿(准确地说是稳定的草稿),并且没有太大变化。它没有正式注册的媒体类型,因此,如果使用JSON表示,则必须使用application/vnd.amundsen-uber+json

亚哈皮

有许多鲜为人知的超媒体规范值得关注。 我们将从 2014年首次发布的Another Hypermedia(ish)API规范( Yahapi )开始,该规范本质上是启用 超媒体的约定的列表。

最后, Yahapi只是使您的API看起来漂亮,简单且一致的首选项列表。

https://github.com/Yahapi/yahapi

Yahapi提供了分页,排序,部分结果和错误格式的准则列表,支持链接和关系,但不幸的是不支持操作。 它很少在野外发现并且不是真正活跃。 Yahapi文档的媒体类型仅为application/json

石匠

Mason是一种基于JSON的格式,用于将超媒体元素引入经典的JSON数据表示中。 特别是,它包括用于链接和动作的超媒体元素以及标准化的错误处理。 Mason在媒体类型注册表中注册为application/vnd.mason+json

离子

Ion将自身定位为REST的一种基于JSON的直观超媒体类型。 它涵盖了关系类型的链接以及使用表单的操作 。 不幸的是,自2018年以来,该规范似乎处于休眠状态。分配给Ion内容的媒体类型为application/ion+json

4. HATEOAS的成本

此时,您应该对将超媒体和HATEOAS应用于RESTful Web服务和API时的作用有一个很好的了解。 而且,如果您是从事典型企业项目的经验丰富的软件开发人员,您可能很难记得上一次遇到HATEOAS时的情况。 让我们面对现实:没有人知道如何使用超媒体 。

在REST体系结构的上下文中, HATEOAS是必须的,但它不是免费的,并且会产生成本,有时非常重要。 不仅在实施方面,而且在前期设计方面。 在这方面,服务器相对容易,但是客户端确实很困难(充其量您可能会获得Link标头的支持)。 实际上,这意味着即使您开发完美的RESTful Web服务或API,其他开发人员也有很大可能选择完全不在其客户端中使用超媒体。

在本教程的这一部分中,我们讨论了许多不同的超媒体规范。 除少数例外,其中大多数带有“进行中”或“不稳定”的标签。 总的来说,这意味着仍有黑暗的水域在航行,而您最终到达那里的机会很高。 这就是为什么要持续不断地创建新规范的原因之一。 显然,每个规范需要非常不同的设计和实现工作量。 希望您的编程语言或平台生态系统已经有了一些库和框架来帮助您入门,但总的来说并非如此。

在服务器和客户端之间的数据交换方面, 超媒体可能会导致更多往返,以获取链接和关系背后的其他详细信息。 由于需要包括链接和操作,这也可能导致资源表示的大小显着增加。

您可能会问自己一个有趣的问题,即REST架构风格(尤其是HATEOAS)如何与微服务架构融合? 为了说明问题,请考虑一个只有两个微 Customer Service的系统,即Customer ServiceReservation Service 。 由于客户不需要任何额外的知识或前期知识,他们如何发现有多种服务? Reservation Service如何整合与客户相关的超媒体元素,反之亦然? 很有可能由另一层(如API网关或/和聚合器)负责 ,当然这听起来并不简单。

如果此时您不惧怕超媒体和HATEOAS ,请不要担心。 收益大大超过了所需的成本和精力,尤其是从长期来看。 作为对此的确认,让我们看一下简短而简单的案例研究。

5.案例研究

我们将要分析的示例应用程序是一个汽车租赁平台,该平台目前仅实现两个RESTful Web API来管理reservationscustomers 。 与任何客户端共享的唯一知识是平台的入口点,出于演示目的,假设在伪造的URL https://rentals.jcg.com后面有服务器。

该端点仅接受HTTP GET请求并返回超媒体文档(使用HAL和HAL-FORMS ),示例如下所示。

$ curl https://rentals.jcg.com/
{                                                        "_links": {                                           "self": {                                           "href": "https://rentals.jcg.com/"                  },                                                   "reservations": {                                   "href": "https://rentals.jcg.com/reservations"      },                                                   "customers" : {                                      "href": "https://rentals.jcg.com/customers"         }                                                    }                                                      
}

一旦了解超媒体的客户收到此类文档,便可以清楚地了解到可以从那里导航到两个链接: reservationscustomers 。 在这种情况下,客户对reservations感兴趣,因此就去了那里。

$ curl -iv https://rentals.jcg.com/reservations
{"_embedded": {"reservations": [ {"id": "ce5886acbb87","vehicle": "Volkswagen Golf 1.2 TSI","from": "2020-02-01","to": "2020-02-12","_links": {"customer": {"href": "https://rentals.jcg.com/customers/fed195a03e9d"},"self": {"href": "https://rentals.jcg.com/reservations/ce5886acbb87"}},"_templates": {"default": {"method": "put","properties": [ {"name": "from","regex" : "yyyy-MM-dd","required": true}, {"name": "to","regex" : "yyyy-MM-dd","required": true}, {"name": "vehicle","required": true} ]},"delete": {"method": "delete","properties": [ ]}}}, ...]},"_links": {"self": {"href": "https://rentals.jcg.com/reservations"}},"_templates": {"default": {"method": "post","properties": [ {"name": "from","regex" : "yyyy-MM-dd","required": true}, {"name": "to","regex" : "yyyy-MM-dd","required": true}, {"name": "vehicle","required": true} ]}}
}

这次服务器返回强大的资源表示形式(为简单起见,集合中仅保留一个保留项),其中包含许多超媒体元素,因此客户端有多种选择。

例如,通过检查_templates 超媒体元素,它可以发现它可以通过提交HTTP POST请求来创建新的保留,该请求中包含有效载荷中的fromtovehicle属性(因为它是HAL-FORMS ,请使用application/x-www-form-urlencoded表单编码)。 您可能会注意到,尽管存在一些约束,但没有任何迹象表明fromtovehicle属性的类型(字符串?日期?数字?)是什么。

"_templates": {"default": {"method": "post","properties": [ {"name": "from","regex" : "yyyy-MM-dd","required": true}, {"name": "to","regex" : "yyyy-MM-dd","required": true}, {"name": "vehicle","required": true} ]}
}

备选地,客户端可以通过自省相关联的_templates 超媒体元素来表达对特定保留的兴趣。

"_templates": {"default": {"method": "put","properties": [ {"name": "from","regex" : "yyyy-MM-dd","required": true}, {"name": "to","regex" : "yyyy-MM-dd","required": true}, {"name": "vehicle","required": true} ]},"delete": {"method": "delete","properties": [ ]}
}

在这种情况下,服务器提供使用HTTP PUT请求(完全替换语义)更新保留或使用HTTP DELETE请求完全删除特定保留的选择。

超媒体–结论

在本教程的这一部分中,我们讨论了超媒体和HATEOAS ,这是任何RESTful Web服务或API的组成部分。 超媒体规范的前景并非一成不变,并且在不断变化。 我们进行了很多选择,但没有遇到明显的赢家。 这样做的原因是,每一个都有不同的权衡,您需要确定哪种超媒体规范最适合您的应用程序需求。 上下文很重要,因此请认真对待。 您可能会发现有关为API选择超媒体类型的文章-HAL,JSON-LD,Collection + JSON,SIREN,噢,我的天哪! 由Kevin Sookocheff提供的帮助很大。

7.接下来

在本教程的下一部分中,我们将讨论文档在由hypermedia支持的RESTful Web服务和API的生命周期中的作用。

翻译自: https://www.javacodegeeks.com/restful-services-with-hateoas-hypermedia-the-secret-ingredient-of-rest.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340287.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot 单测加入参数_Spring Boot集成Elasticsearch实战分享

作者|java梦想口服液|简书最近有读者问我能不能写下如何使用 Spring Boot 开发 Elasticsearch(以下简称 ES) 相关应用&#xff0c;今天就讲解下如何使用 Spring Boot 结合 ES。可以在 ES 官方文档中发现&#xff0c;ES 为 Java REST Client 提供了两种方式的 Client&#xff1a…

计算机主机安装系统安装系统安装软件,电脑安装软件时提示安装过程出错系统设置未被修改怎么办...

‍电脑安装软件&#xff0c;尤其是安全管理这一类软件&#xff0c;可能会出现安装失败的情况&#xff0c;提示安装过程出现错误&#xff0c;未修改系统设置等。这是怎么回事?这些软件在安装的时候可能会修改系统相关的核心设置&#xff0c;所以电脑系统会阻止其安装。下面让我…

python一个函数调用另一个函数_在Python中将函数作为另一个函数的参数传入并调用的方法...

在Python中&#xff0c;函数本身也是对象&#xff0c;所以可以将函数作为参数传入另一函数并进行调用 在旧版本中&#xff0c;可以使用apply(function, *args, **kwargs)进行调用&#xff0c;但是在新版本中已经移除&#xff0c;以function(*args, **kwargs)进行替代&#xff0…

ps图片拖不进去_PS教学:你的logo还不够高大上?7步教做出黄色金属质感logo

今天美迪君向大家分享一下&#xff0c;如何用ps简单制作带有黄色金属质感的logo方法&#xff0c;难度不仅不大&#xff0c;且制造出来的logo也是非常漂亮&#xff0c;值得大家学习。接下来就为大家演示一下制造的方法。1、打开PS&#xff0c;CtrlN新建一个1920*1080的画布(根据…

简单比对照片是否相同_小新说法 | 如何认定商标是否侵权?

如何认定商标是否侵权&#xff1f;原创 | 高姗 江苏东能律师事务所商标是商品的生产者、经营者在其生产、制造、加工、拣选或者经销的商品上或者服务的提供者在其提供的服务上采用的&#xff0c;用于区别商品或服务来源的&#xff0c;包括文字、图形、字母、数字、三维标志、颜…

验证码编写_编写干净的测试–验证或不验证

验证码编写在编写使用模拟对象的单元测试时&#xff0c;请遵循以下步骤&#xff1a; 配置我们的模拟对象的行为。 调用测试的方法。 验证是否已调用模拟对象的正确方法。 第三步的描述实际上有点误导&#xff0c;因为通常我们最终会验证是否调用了正确的方法以及未调用模拟…

单片机拼字程序怎么做_家装行业做小程序怎么样?

对于家装行业&#xff0c;给大家提到了很多获客引流的方式&#xff0c;无论是线上还是线下&#xff0c;只要坚持去做&#xff0c;最后肯定会取得成果的。关于线下的给大家提到最多的就是合作共赢的模式来拓客&#xff0c;线上主要就是打电话和表单或者进入平台的形式&#xff0…

计算机三级考试网络技术怎么复习,考前数天如何突破性通过计算机等级考试之三级网络技术篇...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼计算机等级考试只有几天的时间了&#xff0c;复习已久的你现在该做些什么?最新出版的书&#xff0c;结合近年等考真题&#xff0c;考三级网络技术的同学需要的可以看看&#xff0c;我找来了目录和内容简介&#xff0c;不错的一本书…

python 删除csv第一行_python 标准库学习之 csv

本文由作者 凭海临风 授权刊登。原文地址&#xff1a;https://jeffsui.github.io/2020/01/02/python-standard-library-csv/文档路径官方文档&#xff1a;https://docs.python.org/zh-cn/3.8/library/csv.htmlCSV 文件格式文件扩展名为.csv&#xff0c;通用的电子表格文件格式&…

Java 8之前和之后的Lambda表达式

Java 8之前和之后的几个示例程序的快速指南。Java8 Concepts进一步简化了代码&#xff0c;并且对核心逻辑&#xff08;而不是语法&#xff09;产生了深远影响。 1.简介 在本教程中&#xff0c;我们将学习如何使用Java 8编写程序 lambda和Stream概念以及示例。 许多开发人员认…

idea java主题_IDEA变身超级形态,需要这个酷炫主题

码个蛋(codeegg) 第 1090 次推文作者&#xff1a;CodeWhite7链接&#xff1a;https://blog.csdn.net/weixin_46146269/article/details/104793277前言IDEA&#xff0c;全称 IntelliJ IDEA &#xff0c;是 Java 语言的集成开发环境&#xff0c; IDEA 在业界被公认为是最好的 jav…

儿童python编程能给孩子带来哪些好处_python编程入门学习对孩子成长有哪些优势?...

python编程语言学习有意义吗&#xff1f; python编程语言是少儿编程培训课程中重要的组成部分&#xff0c;随着越来越多的孩子开始接触和学习编程&#xff0c;通过编程学习培养孩子良好的学习习惯和锻炼提升孩子逻辑思维能力。在python编程培训班学习过程中&#xff0c;通过pyt…

yii2 html ul,yii2导航小部件子菜单类

我使用adminLTE主题进行bootstrap,它使用treeview-menu类来操作子菜单.Nav::widget([options > [class > sidebar-menu treeview],items > [[label > Menu 1, url > [/a/index]],[label > Menu 2, url > [/custom-perks/index]],[label > Submenu, ite…

百度云盘照片导入华为相册里_必须知道的相册管理工具

相信很多人都会在手机上存许多值得回忆的照片&#xff0c;为了避免丢失&#xff0c;我们常常会使用网盘工具来管理我们的照片&#xff0c;例如&#xff0c;比较常用的有百度网盘、天翼云盘、115网盘这三款工具&#xff0c;那么这三款网盘在相册功能上有什么特色呢&#xff1f;今…

微信H5 回调_PHP实现微信H5支付

今头日条一小马奔腾 2019-09-27 18:44:37开发前配置进行代码接入前&#xff0c;需在微信后台填写授权回调域名&#xff0c;此域名必须经过ICP备案开发主要流程用户下单时选择微信支付商户进行业务逻辑处理并调用微信统一下单接口&#xff0c;微信H5交易类型为&#xff1a;trade…

freemarker html 乱码,Freemarker生成静态html文件及中文乱码的问题.pdf

Freemarker生成静态html文件及中文乱码的问题,freemarker静态化页面,freemarker静态化,freemarker乱码,freemarker静态方法,freemarker中文乱码,freemarker网页静态化,freemarker生成word,freemarker代码生成器,freemarker生成htmlFreeMarker 允许 Java servlet 保持图形设计同…

java 泛型嵌套泛型_Java泛型简介–第6部分

java 泛型嵌套泛型这是关于泛型的介绍性讨论的延续&#xff0c; 此处的先前部分可以在此处找到。 在上一篇文章中&#xff0c;我们讨论了关于类型参数的递归边界。 我们看到了递归绑定如何帮助我们重用了车辆比较逻辑。 在该文章的结尾&#xff0c;我建议当我们不够谨慎时&…

优化自定义函数_Pandas常见的性能优化方法

文章来源于Datawhale &#xff0c;作者阿水Pandas是数据科学和数据竞赛中常见的库&#xff0c;我们使用Pandas可以进行快速读取数据、分析数据、构造特征。但Pandas在使用上有一些技巧和需要注意的地方&#xff0c;如果你没有合适的使用&#xff0c;那么Pandas可能运行速度非常…

pycharm cant open file_PyCharm

1.创建项目PyCharm是一种Python IDE.PyCharm的功能到底有多强大&#xff0c;我也说不清楚&#xff0c;今天只是介绍一下关于Pycharm创建项目的问题.✦ PyCharm可以将一个文件夹作为工程(或项目)进行打开.如图1所示&#xff0c;先创建两个文件夹(pyc1和pyc2)&#xff0c;在文件夹…

adminlte支持html5吗,spring boot:用adminlte做前端

标签(空格分隔)&#xff1a; sringboot adminlte thymeleafspring boot 和 adminlte没有紧密的联系&#xff0c;只是最近在做的一个东西用spring boot做后端用adminlte做前端&#xff0c;所以就放到spring boot系列里面讲。架构原理adminlte只是一个库&#xff0c;说不上什么框…