首页 > 解决方案 > Swagger 和 HATEOAS 的区别

问题描述

谁能解释 Swagger 和 HATEOAS 之间的区别。我可以搜索很多次但没有朋友可以解释这两个方面的正确详细答案。

标签: restspring-mvcswaggerspring-hateoas

解决方案


Swagger 和 HATEOAS IMO 之间的主要区别(未包含在已接受的答案中)是,仅 RPC'esque API 需要 Swagger。然而,这些 API 实际上与 REST 几乎没有任何关系。

还有一个更广泛的误解,即通过 HTTP 交换的任何内容都自动是 RESTful(~ 根据 REST 架构风格),但事实并非如此。REST 只是定义了一组约束,这些约束不是选择或选项,而是强制性的。从开始到结束。不使用 RESTful 并没有错,但是将这样的架构称为 REST 是错误的。

Swagger 描述了可以在端点上执行的操作以及需要发送到服务的有效负载(包括标头和预期的表示格式),还描述了客户端可能期望的响应。这使得 Swagger 既可以用作文档,也可以用作 API 的测试框架。由于 Swagger 与 API 的紧密耦合,它的行为很像典型的 RPC 服务描述,即类似于 SOAP 中的 WSDL 文件或 RMI 或 CORBA 中的存根或骨架类。如果端点发生更改或负载中的某些内容发生更改,则针对 Swagger 文档实现的客户端可能会随着时间的推移而中断,只是重新引入典型的 RPC 实现所具有的相同问题。

另一方面,REST 和 HATEOAS 是为发现和进一步开发而设计的。REST 不是一种协议,而是一种架构风格,它描述了分布式系统中客户端和服务器之间的交互流程。它基本上采用了使 Web 如此成功的概念并将其转化为应用层。因此,适用于可浏览 Web 的相同概念也适用于 REST。因此,HATEOAS(链接、链接关系和链接名称的使用和支持)的行为与 Web 相似也就不足为奇了。

在设计 REST 架构时,考虑一个状态机是有益的,在该状态机中,服务器提供客户端采取进一步操作所需的所有信息。Asbjørn Ulsberg 在 2016 年举行了一场精彩的演讲,他解释了可供性以及如何通过 HATEOAS 实现状态机。除了通用或标准化的媒体类型和关系名称之外,不需要带外知识来进一步与服务交互。以Asbjørn在他的演讲中给出的烤面包机示例为例,烤面包机可能具有 , 和 状态,打开烤off面包机将导致状态从过渡到onheatingidleoffonheatingidle并在 和 之间切换idleheating直到烤面包机关闭。

HATOAS 将向客户端提供有关当前状态的信息,并包括客户端可以调用以转换到下一个状态(即再次关闭烤面包机)的链接。在这里需要强调的是,客户端是由服务器提供的,客户端接下来可能执行的每个操作。客户端实现者无需查阅任何专有 API 文档即可使客户端能够与 REST 服务交互。此外,URI 不必有意义或设计为传达语义表达结构,因为客户端将确定通过链接关系名称调用该 URI 是否有意义。此类关系名称要么由IANA指定,要么通过Dublin Coreschema.org等常用方法指定或者通过充当扩展属性的绝对 URI,这些属性可能指向人类可读的描述,进一步可能通过鼠标悬停工具提示等传播给用户。

我希望你自己能看到,Swagger 只需要描述 RPC Web-API,而不是遵循 REST 架构设计的应用程序。通过 REST API 交换的消息应包括客户端在下一次状态转换时做出明智选择所需的所有信息。因此,将此类消息流和交互设计为状态机是有益的。


更新:

Swagger 和 HATEOAS 是如何相互排斥的?前者记录您的端点(使自动生成代码成为可能),后者将元信息添加到您的端点,告诉消费者他们可以做什么(即哪些其他端点可用)。这些是非常不同的事情。

我从来没有说过它们是相互排斥的,只是它们有两个不同的目的,如果你遵循一种方法,另一种方法或多或少无用。两者都使用没有任何意义。

让我们将讨论转移到 Web 领域,因为这可能更容易理解,而 REST 实际上只是 Web 上使用的概念的概括,因此执行此步骤是很自然的,并且在设计 REST 架构方面也是一个很好的建议一般的。想一想您作为用户想要向服务器发送一些数据的情况。您以前从未使用过该服务,因此您基本上不知道请求的外观。

在 Swagger 中,您将调用端点文档,选择最有可能解决您的任务的选项,阅读请求的外观并将测试用例破解到您的应用程序中,最终生成一个发送到的 HTTP 请求各自的位置。自动生成代码可能会为您节省一些破解时间,尽管您仍然需要将存根类集成到您的应用程序中并至少测试一次整个事情以确保安全。如果您稍后需要集成该 API 或其他 API 的第二个服务,您需要从头开始并查找 Swagger 文档,生成或破解交互代码并将其集成到您的域中。涉及大量手动步骤,并且在 API 更改的情况下,您需要更新您的客户端,否则它可能会停止工作。

然而,在 Web 示例中,您只需启动浏览器/Web 客户端,调用允许您将数据发送到服务器的相应 URI,服务器很可能会向您发送一个 HTML 表单,您只需填写并单击发送按钮自动将请求发送到将开始处理它的服务器。这是仇恨。您使用给定的控件来驱动您的工作流程。服务器会教您的客户端发出有效请求所需的每一个小细节。它为您的客户端提供目标 URI 以将请求发送到,它应该使用的 HTTP 方法,以及最常见的隐式有效负载应该在的媒体类型。除此之外,它还为您的客户端提供了预期的框架和/或有效负载应包含的受支持元素。即表格可能要求您填写几个输入字段,在一组给定的选项中进行选择或使用其他一些控件,例如为您转换为有效日期或时间表示的日期或时间选择器值。您需要做的就是调用 Web 客户端中的相应资源。没有自动生成,没有集成到您的浏览器/应用程序中。使用其他服务(来自相同或不同的提供商)很可能只是以相同的方式工作,因此只要支持交换媒体类型的请求和响应,就无需更改或更新您的 HTTP 客户端(浏览器)。

在您依赖 Swagger RPC'esque 文档的情况下,该文档是关于如何与服务交互的真相。混入一些 HATEOAS 信息不会给您带来任何好处。在 Swagger 案例中,由于参考文档中提供了所有必需的信息,因此携带额外的元信息会无缘无故地增加请求/响应,这在一定程度上会导致人们开始质疑该服务的开发人员并要求减少有效负载。只看这里一段时间,你会发现足够多的问题,询问如何进一步优化交互并将消息大小减少到最小,因为它们处理每个小请求并且根本不使用响应缓存。在 HATEOAS 案例中,指向外部引用是没有用的,因为这种架构中的对等点很可能已经支持所需的必需品,例如 URI、HTTP 和相应的媒体类型,实现在其中。在使用自定义媒体类型的情况下,可以在运行时通过插件或附加组件动态添加支持(如果支持)。

因此,Swagger 和 HATEOAS 并不是相互排斥的,但是一旦您决定选择一条路线或另一条路线,另一个就会或多或少地变得无用。


推荐阅读