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

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

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

{"@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年以来,该规范似乎处于Hibernate状态。分配给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 超媒体元素,它发现它可以通过在有效负载中提交包含fromtovehicle属性的HTTP POST请求来创建新的保留(因为它是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

restful rest

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

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

相关文章

漫画:什么是单例设计模式

转载自 永远爱大家的 程序员小灰 ————— 第二天 ————— 单例模式第一版&#xff1a; 1234567891011public class Singleton {private Singleton() {} //私有构造函数private static Singleton instance null; //单例对象//静态工厂方法public static Singleton ge…

如何在工作繁重、睡眠较少的情况下保持旺盛精力?

作者&#xff1a;陈炬 链接&#xff1a;https://www.zhihu.com/question/23177623/answer/47785761 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 本人也在创业&#xff0c;结合《精力管理》一书&#xff0c;说说我…

mockito接口没法赋值_Mockito:无法实例化@InjectMocks字段:类型是接口

mockito接口没法赋值使用Mockito进行Java类的模拟和存根的任何人&#xff0c;可能都熟悉InjectMocks -annotation。 在要测试的类上使用此批注&#xff0c;Mockito将尝试通过构造函数注入&#xff0c;setter注入或属性注入来注入模拟。 魔术成功了&#xff0c;它无声地失败了&a…

tomcat(10)安全性

【0】README0.0&#xff09;本文部分描述转自“深入剖析tomcat”&#xff0c;旨在学习 tomcat(10)安全性 的基本知识&#xff1b;0.1&#xff09;servlet技术支持通过配置部署描述器&#xff08;web.xml&#xff09;文件来对这些内容进行访问控制&#xff1b;&#xff08;干货—…

SonarQube 8.3.x中的Maven项目的测试覆盖率报告

几年前&#xff0c;我写了一篇博客文章&#xff0c;介绍如何在SonarQube中生成测试报告&#xff0c;该报告独立于单元测试和集成测试的测试报告中。 从SonarQube 6.2开始&#xff0c;测试报告不再在这些类别中分开&#xff08;请参阅SonarQube的博客文章 &#xff09;。 SonarQ…

单例模式懒汉、饿汉和登记

转载自 JAVA设计模式之单例模式本文继续介绍23种设计模式系列之单例模式。 概念&#xff1a;  java中单例模式是一种常见的设计模式&#xff0c;单例模式的写法有好几种&#xff0c;这里主要介绍三种&#xff1a;懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点…

量角器中Selenium定位器的完整指南(示例)

在测试网站的功能时&#xff0c;特别是Web元素&#xff08;例如单选按钮&#xff0c;文本框&#xff0c;下拉列表等&#xff09;&#xff0c;您需要确保能够访问这些元素。 Selenium定位器正是出于这个目的&#xff0c;通过使用此命令&#xff0c;我们可以识别这些Web元素DOM&a…

MySQL的自然联结+外部联结(左外连接,右外连接)+内部联结

【0】README0.1&#xff09;本文旨在review MySQL的自然联结外部联结&#xff08;左外连接&#xff0c;右外连接&#xff09;内部联结 的相关知识&#xff1b;【1】自然联结1&#xff09;自然联结定义&#xff1a;无论何时对表进行联结&#xff0c;应该至少有一个列出现不止一个…

MySQL 添加列+修改列+删除列

【0】REAMDE 0.1&#xff09;本文部分文字描述转自 http://blog.163.com/zhangjie_0303/blog/static/99082706201191911653778/ 0.2&#xff09;本文旨在review mysql 对列的相关操作&#xff1a;如添加&#xff0c;修改&#xff0c;删除以及重命名表名等操作&#xff1b; 【1】…

compose应用_带有PostgreSQLDocker Compose for Spring Boot应用程序

compose应用在此博客文章中&#xff0c;您将学习如何使用PostgreSQL配置Spring Boot应用程序以与Docker Compose一起运行。 这篇博客文章涵盖&#xff1a; Spring Boot应用程序Dockerfile配置&#xff0c;在依赖项和资源之间进行了清晰的分离 用于通过PostgreSQL运行应用程序…

单例模式面试题

转载自 单例模式面试题&#xff08;特点、理解&#xff09; (1)单例模式特点&#xff08;什么是单例模式&#xff09;&#xff1f;  a.单例类只能有一个实例。  b.单例类必须自己创建自己的唯一实例。  c.单例类必须给所有其他对象提供这一实例。 (2)单例模式的作用&#x…

MySQL的source命令不加分号和delimiter的使用

【0】README 0.1&#xff09;本文旨在 review source 命令&#xff0c; 这一直是我的痛&#xff0c;为什么一直导入 sql 文件不成功&#xff0c;一直没有写 blog 吧他 记录下来&#xff08;事实上&#xff0c;也间接证明我就是个小白&#xff09;&#xff1b; 0.2&#xff09…

selenium自动化测试_维持Selenium测试自动化的完美方法

selenium自动化测试毫无疑问&#xff0c; 自动浏览器测试已改变了软件开发的工作方式。 如果不是Selenium&#xff0c;我们将无法像我们一样使用各种各样的无错误的Web应用程序。 但是有时&#xff0c;甚至IT部门也误解了自动化一词。 大多数人认为计算机将为他们完成所有测试…

单例模式的优与劣

转载自 大话设计模式(四)单例模式的优与劣前言首先来明确一个问题&#xff0c;那就是在某些情况下&#xff0c;有些对象&#xff0c;我们只需要一个就可以了&#xff0c;比如&#xff0c;一台计算机上可以连好几个打印机&#xff0c;但是这个计算机上的打印程序只能有一个&…

MySQL存储过程+游标+触发器

【0】README0.1&#xff09;本文旨在 arrange mysql 存储过程及如何在存储中使用游标 的相关知识&#xff1b;0.2&#xff09;delimieter的用法&#xff1a;参见 http://blog.csdn.net/pacosonswjtu/article/details/51407756&#xff1b;【1】存储过程基础1&#xff09;intro…

java迭代器退出迭代_使用Java迭代器修改数据时要小心

java迭代器退出迭代随着本学期的结束&#xff0c;我想我会分享一个关于如何非常熟悉Java迭代器的小故事。 现实世界语境 就上下文而言&#xff0c;我开设了第二年软件组件课程&#xff0c;这是尝试进入该专业的学生的最后障碍。 当然&#xff0c;这门课程对学生来说压力很大&a…

pojo 带参构造函数_带有Java Pojo作为输入输出示例的AWS Lambda函数

pojo 带参构造函数在上一个教程中&#xff0c;我们看到了如何使用Java创建AWS Lambda函数&#xff0c;我们传递了String作为输入&#xff0c;还返回了String作为Output。如果您是第一次创建lambda函数&#xff0c;我建议先阅读该教程。 在本教程中&#xff0c;我们将看到如何传…

MySQL检索数据(过滤+通配符+正则表达式)

【0】README0.1&#xff09;本文部分文字描述转自“MySQL 必知必会”&#xff0c;旨在review “MySQL的基础知识”&#xff1b;【1】检索数据1&#xff09;检索单个列&#xff1a;select a_name from table_name;2&#xff09;检索多个列&#xff1a;select a_name,b_name from…

创建者模式

转载自 设计模式之创建者模式创建者模式又叫建造者模式&#xff0c;是将一个复杂的对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程&#xff0c;它把复杂对象的创建过程加以抽象&#xff0c;通过子类继承或者重…

buildpack_使用Buildpack容器化Spring Boot应用程序

buildpack在本文中&#xff0c;我们将看到如何使用Buildpacks容器化Spring Boot应用程序。 在先前的一篇文章中&#xff0c;我讨论了Jib 。 Jib允许我们在不使用Dockerfile的情况下将任何Java应用程序构建为Docker映像。 现在&#xff0c;从Spring Boot 2.3开始&#xff0c;我们…