我参与了一个项目,其中一些高级团队成员认为REST API必须符合HATEOAS标准并实现所有Richardson的成熟度级别(http://martinfowler.com/articles/richardsonMaturityModel.html)!
AFAIK大多数REST实现都不符合HATEOAS标准,应该有更多人没有这样做的充分理由。我可以想到增加复杂性,缺乏框架(服务器和客户端),性能问题和......等原因。
你怎么看?您是否在实际项目中有过HATEOAS的经验?答案 0 :(得分:178)
REST社区中没有人说REST很容易。 HATEOAS只是增加REST架构难度的一个方面。
由于您提出的所有原因,人们不会做HATEOAS:这很困难。它增加了服务器端和客户端的复杂性(如果你真的想从中受益)。
然而,数十亿人今天体验到了REST的好处。你知道亚马逊的“结账”网址是什么吗?我不。然而,我每天都可以结账。该网址已更改?我不知道,我不在乎。
你知道吗?任何写过屏幕的人都会刮掉亚马逊的自动化客户端。有些人可能会煞费苦心地嗅探网络流量,阅读HTML页面等,以找到在有效载荷和有效载荷时调用哪些链接。
一旦亚马逊改变了内部流程和URL结构,那些硬编码客户端就会失败 - 因为链接已经崩溃。
然而,休闲的网上冲浪者整天都可以购物而且没有任何障碍。
这就是REST的实际应用,它只是通过能够解释和直观基于文本的界面,识别带有购物车的小图形,以及实际意味着什么的人来增强。
大多数编写软件的人都不这样做。大多数写自动客户的人都不在乎。大多数人发现在他们破解时更容易修复他们的客户,而不是设计应用程序而不是首先破坏他们。大多数人在重要的地方根本没有足够的客户。
如果您正在编写内部API,以便在两个系统之间进行通信,并在流量的两端提供专家技术支持和IT,谁能够快速,可靠地和变更计划进行通信,那么REST会为您购买没有。你不需要它,你的应用程序还不够大,并且它的存在时间不够长。
拥有大量用户群的大型网站确实存在此问题。他们不能只是要求人们在与系统交互时随心所欲地更改客户端代码。服务器开发计划与客户端开发计划不同。 API的突然变化对所有参与者来说都是不可接受的,因为它会破坏双方的流量和操作。
因此,像这样的操作很可能会受益于HATEOAS,因为它更易于版本化,更容易迁移旧客户端,更容易向后兼容。
将大部分工作流委托给服务器的客户端,对服务器更改的操作比没有服务器更改的客户端更加健壮。
但大多数人不需要这种灵活性。他们正在为2或3个部门编写服务器代码,这些都是内部使用的。如果它破裂了,他们会修复它,并且他们已经考虑到了正常的操作。
灵活性,无论是来自REST还是其他任何东西,都会增加复杂性。如果你想要它简单,快速,那么你就不要灵活,你“只是做”,并且完成。当你添加抽象和解除引用系统时,东西变得更加困难,更多的锅炉板,更多的代码来测试。
大部分REST都失败了“你不需要它”的要点。当然,直到你做到了。
如果您需要它,那么使用它,并按照它的布局使用它。 REST不会在HTTP上来回传递信息。它从未如此,它的水平远高于此。
但是当你确实需要REST时,你确实使用了REST,那么HATEOAS就是必需品。它是软件包的一部分,也是使其工作的关键。
答案 1 :(得分:19)
是的,我在API中有过超媒体的经验。以下是一些好处:
可探索的API: 这可能听起来微不足道,但不要低估可探索API的强大功能。浏览数据的能力使客户端开发人员更容易构建API及其数据结构的心理模型。
内联文档: 使用URL作为链接关系可以将客户端开发人员指向文档。
简单的客户端逻辑: 简单地遵循URL而不是自己构建URL的客户端应该更容易实现和维护。
服务器获取URL结构的所有权: 超媒体的使用消除了客户端对服务器使用的URL结构的硬编码知识。
将内容加载到其他服务: 将内容卸载到其他服务器(例如CDN)时,必须使用超媒体。
使用链接进行版本控制: 超媒体有助于API的版本化。
同一服务/ API的多个实现: 当存在相同服务/ API的多个实现时,超媒体是必需的。例如,服务可以是具有用于添加帖子和评论的资源的博客API。如果根据链接关系而不是硬编码URL指定服务,则可以在不同的URL处多次实例化相同的服务,由不同的公司托管,但仍可通过单个客户端通过相同的良好定义的链接集访问。
您可以在此处找到对这些要点的深入解释:http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html
(这里有一个类似的问题:https://softwareengineering.stackexchange.com/questions/149124/what-is-the-benefit-of-hypermedia-hateoas我给出了相同的解释)
答案 2 :(得分:9)
理查森的成熟度等级3很有价值,应该采用。 JørnWildt已经总结了一些优点,Wilt的另一个答案非常好地补充了它。
然而,理查森的成熟度等级3与菲尔丁的HATEOAS不同。 Richardson的成熟度等级3仅与API设计有关。 Fielding的HATEOAS也是关于API设计的,但也规定客户端软件不应该假设资源具有超出媒体类型定义的结构的特定结构。这需要一个非常通用的客户端,如Web浏览器,它不了解特定网站。由于Roy Fielding创造了术语REST并将HATEOAS设置为符合REST的要求,因此问题是:我们是否希望采用HATEOAS,如果没有,我们仍然可以调用我们的API RESTful吗?我想我们可以。让我解释一下。
假设我们已经实现了HATEOAS。应用程序的客户端现在非常通用,但很可能,用户体验很糟糕,因为在不了解资源的语义的情况下,无法定制资源的表示以反映这些语义。如果资源'car'和资源'house'具有相同的媒体类型(例如application / json),那么它们将以相同的方式呈现给用户,例如作为属性表(名称/值对)。 / p>
但是,我们的API确实是RESTful。
现在,假设我们在此API之上构建第二个客户端应用程序。第二个客户端违反了HATEOAS的想法,并且有关于资源的硬编码信息。它以不同的方式显示汽车和房屋。
API仍然可以称为RESTful吗?我认同。它的一个客户违反了HATEOAS,这不是API的错。
我建议构建RESTful API,即可以在理论上实现通用客户端的API ,但在大多数情况下,您需要一些硬编码信息客户端中的资源,以满足可用性要求。尽管如此,尽量少尝试硬编码,以减少客户端和服务器之间的依赖关系。
我在我的REST实现模式中包含了一个名为JAREST的HATEOAS部分。
答案 3 :(得分:4)
我们正在构建REST级别3 API,我们的响应是在HAL-Json中进行的。 HATEOAS对于前端和后端都非常有用,但同时也带来了挑战。我们还进行了一些自定义/添加,还可以在HAL-Json响应中管理ACL(不违反HAL-Json标准)。
我看到的HATEOAS的最大优点是,我们不需要在前端应用程序中编写/猜测任何url。您只需要一个入口点(https://hostname
),然后就可以使用响应中提供的链接或模板链接浏览资源。
像这样,可以轻松处理版本控制,重命名/替换url,使用其他关系扩展资源而不会破坏前端代码。
使用自我链接在前端缓存资源是小菜一碟。 我们还通过套接字连接将资源推送到客户端,因为这些资源也是在HAL中呈现的,因此我们可以轻松地以相同的方式添加它们以缓存。
使用HAL-Json的另一个优点是,由于应该遵循一个成文的标准,因此很清楚响应模型应该是什么样子。
我们的一项自定义操作是,我们在自链接对象内添加了一个action对象,该对象向前端暴露了允许已验证用户对相应资源执行的操作或CRUD操作(create:POST
,{ {1}},read:GET
,update:PUT
,edit:PATCH
)。像这样,我们的前端ACL完全由我们的REST API响应决定,将这一责任完全转移到了后端模型上。
举个简单的例子,您可以在HAL-Json中创建一个post对象,看起来像这样:
delete:DELETE
现在我们在前端要做的就是使用{
"_links": {
"self": {
"href": "https://hostname/api/v1/posts/1",
"actions": {
"read": "GET",
"update": "PUT",
"delete": "DELETE"
}
}
},
"_embedded": {
"owner": {
"id": 1,
"name": "John Doe",
"email": "john.doe@example.com",
"_links": {
"self": {
"href": "https://hostname/api/v1/users/1",
"actions": {
"read": "GET"
}
}
}
}
},
"subject": "Post subject",
"body": "Post message body"
}
方法构建一个AclService
的方法,该方法检查我们要执行的动作是否在action对象中。
目前在前端,它看起来很简单:isAllowed
我认为REST 3级很棒,但是它可能会引起一些麻烦。您将需要对REST有深刻的了解,如果您想使用3级REST,我建议您严格遵循REST概念,否则在实施它时很容易迷路。
在我们的案例中,我们的优势在于我们同时在前端和后端进行构建,但原则上不应该有所作为。 但是我在我们的团队中看到的一个常见陷阱是,一些开发人员试图通过更改后端模型来解决前端问题(体系结构),从而“满足”前端需求。
答案 4 :(得分:2)
我在一些真实的项目中使用了HATEOAS,但与Richardson的解释不同。如果那是你老板想要的,那么我想你应该这样做。我认为HATEOAS意味着您的资源应包含HTML文档类型,相关资源的超链接和HTML表单,以公开除GET之外的动词的功能。 (这是Accept类型是text / html时 - 其他内容类型不需要这些额外内容。)我不知道整个应用程序中的所有REST资源必须粘在一起的信念来自哪里。网络应用程序应包含多个可能或可能不直接相关的资源。或者为什么认为XML,JSON和其他类型需要遵循这一点。 (HATEOAS是特定于HTML的。)