【问题标题】:HATEOAS: concise descriptionHATEOAS:简洁的描述
【发布时间】:2012-02-08 11:44:11
【问题描述】:

我试图对 HATEOAS 有一个清晰而简洁的理解,我绝不是 WRT REST 专家。 (我想我明白了,感谢http://www.looah.com/source/view/2284)。

谁能推荐一篇同样具有启发性的博客/文章 WRT HATEOAS?

【问题讨论】:

  • 我建议您阅读《实践中的 REST》一书。
  • 简短、甜蜜、完整:blogs.oracle.com/craigmcc/entry/why_hateoas
  • REST 链接不再起作用。我相信here 可以进行相同的对话。
  • 仅供读者参考 - HATEOAS 是 Hypermedia As The Engine Of Application State 的首字母缩写

标签: rest hateoas


【解决方案1】:

超媒体约束(以前称为 HATEOAS)是用于为用户代理提供方向的约束。

通过在返回的表示中包含链接,服务器可以减轻用户代理根据当前应用程序状态确定可以采取的操作并知道按顺序与谁交互的负担来实现这个目标。

由于服务器不知道用户代理的当前状态,除了它在请求中收到的内容之外,用户代理尽量避免使用服务器返回的表示以外的状态,这一点很重要。这可以确保服务器提供的可用操作尽可能基于对用户代理状态的最完整理解。

符合超媒体约束的用户代理就像一个状态机,其中状态转换是由当前表示中可用的链接引起的。返回的表示成为新的状态。

这种方法的好处可以是一个非常轻量级的用户代理。它只需要很少的代码来管理状态,因为它的操作应该完全基于接收到的响应和检索该响应的链接。 用户代理代码变得声明性和反应性,而不是 GET this 然后执行此操作然后执行此操作的命令序列,您只需拥有跟踪链接的机制,以及当您收到此然后执行此操作的许多实例.

对于其工作原理的示例,您只需查看您的网络浏览器和不使用 Javascript 的网站即可。浏览器会根据 HTML 中的链接为您提供选项。当您点击该链接时,浏览器会将其当前状态替换为您点击该链接时检索到的新状态。后退按钮有效(或至少应该有效),因为您正在从历史记录中的链接中检索状态。浏览器不应该关心你是如何到达页面的,因为状态应该完全基于检索到的表示。

这种“状态管理”模型可能非常有限,因为您当前的应用程序状态基于单个服务器响应。但是,可以通过使用一组协同工作的用户代理来构建复杂的应用程序。这是 AJAX 实现的一部分,因为它允许使用不同的用户代理来发出单独的请求,因此实际上管理另一个状态机。不幸的是,大多数时候人们在开始发出 javascript 请求时会求助于 RPC 样式,考虑到 Javascript 的自然异步性,这是不幸的。

【讨论】:

  • 很好的答案,谢谢。在我完全理解你的答案之前,我当然有一些阅读要做。你能推荐任何在线可用的东西吗?
  • @MylesMcDonnell Mike Amundsen 有很多帖子涵盖了这个主题 amundsen.com/blog/archives/?category=22
  • 感谢 Mike 的应用程序/html 表示的超链接,它确实改变了我的应用程序状态!
  • @DarrelMiller:如果我理解正确的话,如果 HATEOAS 约束得到遵守,应用程序可能的有限过渡状态将绑定到当前表示中的 links。有什么遗漏吗?
  • @PK' 这似乎是一个不错的概要。
【解决方案2】:

HATEOAS 简而言之:在您输出的数据中,使用 URI 而不是 ID 来引用其他资源。

正如所有简短的定义一样,我刚才给出的定义在很多层面上都是错误的,但它应该让你明白 HATEOAS 的症结是什么。

现在,再解释一下。

HATEOAS 原则说应用程序的状态应该通过超文本链接进行。想想你在互联网上浏览。首先,您必须在地址栏中输入地址。从那时起,您的导航几乎只能通过点击链接取得进展:您点击一个链接,您最终会进入另一个页面。再点击一次,这里就会出现另一个页面。浏览器如何将您从第一页移动到第二页到第三页?它使用了在<a> 元素中编码的 URL。

同样,如果您的 REST 应用程序生成此结果

<accomodation>
  <hotel info="http://example/hotel/0928374" price="200"/>
  <guest-house info="http://example/guest-h/7082" price="87"/>
</accomodation>

那么接收应用程序将无需访问任何外部知识源即可知道第一家酒店在http://example/hotel/0928374 和第二家在http://example/guest-h/7082 可用。

另一方面,如果您的应用程序生成具有类似 ID 的响应

<accomodation>
  <hotel id="0928374" price="200"/>
  <guest-house id="7082" price="87"/>
</accomodation>

接收应用程序必须提前知道 ID 必须如何与前缀组合以获取每个住宿信息可用的 URI(例如 "在每个请求中添加 http://example/,然后添加 @ 987654327@ 用于酒店,guest-h 用于宾馆")。您可以看到,这种机制与许多 DB 应用程序中发生的机制相似,但与浏览器的工作方式不同。

遵循 HATEOAS 原则很重要,因为它允许应用程序在不大幅更改接收应用程序的情况下增长。假设您要将 URI 从 http://example.com/hotel/0928374 更改为 https://reviews.example.com/accommodation/0928374。如果你遵循 HATEOAS 将是一个简单的更改:修改返回值并且它是:接收应用程序将继续工作而无需任何修改。相反,如果您有关于如何构建 URI 的单独文档,则必须联系所有应用程序开发人员并要求他们注意文档已更新,他们应该更改代码以反映更改。

免责声明:这是一个快速回答,只是触及了问题的表面。但如果你明白了这一点,你就掌握了 HATEOAS 原则的 80%。

【讨论】:

  • 不错。我没有在我的回答中提到超媒体提供的间接的好处,所以我认为我们的回答是相辅相成的。
  • 太好了,感谢您抽出宝贵时间来写这篇文章。有人向我建议,HATEOAS 存在固有问题(它在工作规范中。我正在考虑申请),你们中的任何一个都知道这可能是什么吗?
  • 有些人可能会认为你暴露你的 URI 是一个问题,你泄露了一些信息。对此的回应是,如果您关心这一点,您应该有两组 URI:公共和私有,就像使用 ID 一样。还有网络方面的考虑,但这些变得没有意义,因为任何其他风格只要它们变得像做得好的 REST API 一样具有表现力,就会使用相同数量的网络请求。打开另一个问题:人们肯定会对 HATEOAS 的缺点发表很多评论。
  • @gioele URI 的模糊性永远不应该成为系统安全的来源,真正的私人信息也不应该被编码在 URI 中。不过,这不是 HATEOAS 原则。它比这更基本。
  • @MylesMcDonnell 我看到 HATEOAS 固有的问题是您不能强迫客户使用它。没有什么可以阻止客户端在其客户端应用程序中硬编码 URI 结构。没有什么可以阻止他们根据他们对 URI 空间的假设来制造自己的 URI。没有什么可以阻止他们假设,因为今天的响应提供了媒体类型 X,它将始终返回媒体类型 X。HATEOAS 是客户端和服务器之间的合同,客户端可以轻松破坏。
【解决方案3】:

这篇文章帮助我彻底理解了它。 http://restcookbook.com/Basics/hateoas/

简单而优雅。

HATEOAS 代表 Hypertext As The Engine Of Application State。这意味着应该使用超文本来找到通过 API 的方式。一个例子:

GET /account/12345 HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0"?>
<account>
    <account_number>12345</account_number>
    <balance currency="usd">100.00</balance>
    <link rel="deposit" href="/account/12345/deposit" />
    <link rel="withdraw" href="/account/12345/withdraw" />
    <link rel="transfer" href="/account/12345/transfer" />
    <link rel="close" href="/account/12345/close" />
</account>

除了我们的账户中有 100 美元(美元)之外,我们可以看到 4 个选项:存入更多资金、提取资金、将资金转移到另一个账户或关闭我们的账户。 “链接”标签允许我们找出指定操作所需的 URL。现在,假设我们银行里没有 100 美元,但实际上我们处于亏损状态:

GET /account/12345 HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0"?>
<account>
    <account_number>12345</account_number>
    <balance currency="usd">-25.00</balance>
    <link rel="deposit" href="/account/12345/deposit" />
</account>

现在我们亏了 25 美元。您是否看到现在我们失去了许多选择,只有存钱才有效?只要我们处于亏损状态,我们就不能关闭我们的账户,也不能从账户中转移或提取任何资金。超文本实际上是在告诉我们什么是允许的,什么是不允许的:HATEOAS

【讨论】:

    【解决方案4】:

    REST 和 HATEOAS 的一个问题是对接口定义的困难和缺乏可见性和控制。对于更传统的 RPC 样式交互,通常有一个人工制品(例如 IDL 或 WSDL)来定义 API,并且可以由项目控制和管理。

    使用 HATEOAS,API 是动态可发现的,它可以被描述为一组行为(状态变化)。这些行为在代码中进行了描述。 API 描述 (WADL) 是从代码生成的,而不是从接口描述生成的代码。

    【讨论】:

      【解决方案5】:

      根据我使用 HATEOAS 引擎的个人经验,最大的不同在于设计本身的理念。

      如果我们要构建一个 Web 应用程序,有两种方法。一种是 RPC 风格,另一种是 REST 风格。

      如果必须以 RPC 样式测试状态,我们需要调用返回结果的 RPC 过程。使用这种设计方法,第一次调用后返回的参数必须存储在客户端上,以便后续调用可以使用返回的参数。这只是使客户端和服务器紧密耦合,使整个系统有状态。

      而在 REST 样式中,没有 RPC。重要的是客户端和服务器之间的交互。对于任何状态转换,客户端都必须与服务器交互以获取信息。唯一固定的交互是家庭交互。其余的都是由客户端在经历不同的交互时发现的。

      从计算机科学的角度来看,一种是程序风格,一种是算法风格。 REST 风格是一种交互范式。任何采用交互范式作为语言的系统都将提供 HATEOAS 系统。

      【讨论】:

        猜你喜欢
        • 2010-12-04
        • 1970-01-01
        • 2019-09-29
        • 1970-01-01
        • 2011-08-07
        • 1970-01-01
        • 2022-10-14
        • 2016-07-21
        • 1970-01-01
        相关资源
        最近更新 更多