Swagger 和 HATEOAS 之间的区别
Difference between Swagger & HATEOAS
任何人都可以解释 Swagger 和 HATEOAS 之间的区别。我可以搜索很多次,但是没有哥们可以从这两个方面解释正确的详细答案。
Swagger:Swagger 有助于整个 API 生命周期的开发,从设计和文档到测试和部署。 (参考swagger.io)
HATEOAS:作为应用程序状态引擎的超媒体
Ion 表单是一个集合对象,其中值成员数组包含表单字段。 Ion Forms 确保可以自动发现支持数据提交的资源转换(链接)(通俗地称为 HATEOAS)。 (参考https://ionspec.org/)
一个是支持API设计和测试的框架,另一个是API设计架构。
Swagger 和 HATEOAS IMO 之间的主要区别(未包含在已接受的答案中)是,只有 RPC 式 API 才需要 Swagger。然而,这样的 API 实际上与 REST 几乎没有任何关系。
还有一个更广泛的误解,认为通过 HTTP 交换的任何东西都会自动 RESTful(~ 根据 REST 架构风格),但事实并非如此。 REST 只是定义了一组约束,这些约束不是选择或选项,而是强制性的。从开始到结束。不是 RESTful 并没有错,但是将这样的架构称为 REST 是错误的。
Swagger 描述了可以在端点上执行的操作和需要发送到服务的负载(包括 headers 和预期的表示格式),还描述了客户端可能期望的响应.这使得 Swagger 既可以用作文档,也可以用作 API 的 testing-framework。由于 Swagger 与 API 的紧密耦合,它的行为很像典型的 RPC 服务描述,即类似于 SOAP 中的 WSDL 文件或 RMI 或 CORBA 中的存根或骨架 类。如果端点发生变化或有效负载中的某些内容发生变化,根据 Swagger 文档实施的客户端可能会随着时间的推移而中断,只是重新引入典型 RPC 实施所具有的相同问题。
另一方面,REST 和 HATEOAS 是为发现和进一步开发而设计的。 REST 不是一种协议,而是一种架构风格,它描述了分布式系统中客户端和服务器之间的交互流。它基本上采用了使 Web 如此成功的概念,并将其转化为应用程序层。因此,适用于可浏览 Web 的相同概念也适用于 REST。因此,HATEOAS(links、link 关系和 link 名称的使用和支持)与 Web 的行为相似也就不足为奇了。
在设计 REST 架构时,考虑一个状态机是有益的,其中服务器提供客户端采取进一步操作所需的所有信息。 Asbjørn Ulsberg 在 2016 年举行了一场精彩的演讲,他 explains affordances and how a state machine might be implemented through HATEOAS。除了通用或标准化的 media-types 和关系名称之外,无需 out-of-band 知识即可与服务进一步交互。就 Asbjørn 在他的演讲中给出的烤面包机示例而言,烤面包机可能具有状态 off
、on
、heating
和 idle
,其中打开烤面包机将导致从 off
到 on
的状态转换,然后是到 heating
的状态转换,直到达到某个温度,此时状态转换到 idle
并在 idle
之间切换heating
直到烤面包机关闭。
HATOAS 将为客户端提供有关当前状态的信息,并包括 link 客户端可以调用以转换到下一个状态的信息,即再次关闭烤面包机。这里需要强调的是,服务器为客户端提供了客户端接下来可能执行的每个操作。客户端实现者无需查阅任何专有 API 文档即可使客户端能够与 REST 服务进行交互。此外,URI 不必有意义或旨在传达 semantical-expressive 结构,因为客户端将确定通过 link-relation 名称调用该 URI 是否有意义。此类关系名称由 IANA, by a common approach such as Dublin Core or schema.org or by absolut URIs acting as extension attributes 指定,它可能指向 human-readable 描述,进一步可能通过 mouse-over 工具提示等传播给用户。
希望大家亲眼看到,Swagger只需要描述RPCWeb-APIs,而不是遵循REST架构设计的应用。通过 REST APIs 交换的消息应该包括客户端在下一个状态转换时做出明智选择所需的所有信息。因此,将此类消息流和交互设计为状态机是有益的。
更新:
How are Swagger and HATEOAS mutually exclusive? The former documents your endpoints (making auto-generating code possible) and the latter adds meta-information to your endpoints which tell the consumer what they can do (i.e. which other endpoints are available). These are very different things.
我从来没有说过它们是相互排斥的,只是它们有两个不同的目的,如果你遵循一种方法,另一种方法或多或少会变得无用。但是,同时使用两者没有任何意义。
让我们将讨论转移到 Web 领域,因为这可能更容易理解,REST 实际上只是 Web 上使用的概念的概括,所以执行此步骤是很自然的,也是一个很好的建议一般设计 REST 架构。想一想您作为用户想要向服务器发送一些数据的情况。您以前从未使用过该服务,所以您基本上不知道请求的样子。
在 Swagger 中,您将调用端点文档,select 最有可能解决您的任务的选项,阅读请求的外观并将 test-case 入侵您的应用程序最终生成发送到相应位置的 HTTP 请求。 Auto-generating 代码可能会为您节省一些黑客时间,但您仍然需要o 将存根 类 集成到您的应用程序中,并至少测试一次以确保安全。如果您稍后需要集成 API 的第二个服务或一般的另一个 API 的第二个服务,您需要从头开始并查找 Swagger 文档,生成或破解交互代码并将其集成到您的域中。涉及大量手动步骤,如果发生 API 更改,您需要更新客户端,否则它可能会停止工作。
然而,在 Web 示例中,您只需启动 browser/Web 客户端,调用允许您将数据发送到服务器的相应 URI,服务器很可能会向您发送一个 HTML您只需要填写表格并单击发送按钮,它会自动将请求发送到服务器,服务器将开始处理它。这是 HATEOAS。您使用给定的控件来驱动您的工作流程。服务器会告诉您的客户端发出有效请求所需的每一个细节。它为您的客户端提供了要将请求发送到的目标 URI、它应该使用的 HTTP 方法,并且通常还隐式地提供了有效负载应该使用的媒体类型。除此之外,它还为您的客户端提供了预期 and/or 有效负载应包含的支持元素。 IE。该表单可能需要您填写几个输入字段,在一组给定的选项中 select 或使用一些其他控件,例如转换为有效日期或时间表示的日期或时间选择器值.您需要做的就是在您的 Web 客户端中调用相应的资源。没有 auto-generation,没有融入你的 browser/application。使用其他服务(来自相同或不同的提供商)很可能会以相同的方式工作,因此只要支持交换 media-type 请求和响应,就无需更改或更新您的 HTTP 客户端(浏览器) .
在您依赖 Swagger RPC 风格的文档的情况下,该文档是关于如何与服务交互的真相。混入一些 HATEOAS 信息不会给您带来任何好处。在 Swagger 案例中,携带额外的 meta-information 使 request/response 膨胀,没有明显的原因,因为参考文档中提供了所有必需的信息,肯定会导致人们开始质疑该服务开发人员的理智,并要求减少有效载荷。只要在这里看一会儿 SO,您就会发现足够多的问题,询问如何进一步优化交互并将消息大小减少到最小,因为它们处理每个小请求并且根本不使用响应缓存。在 HATEOAS 案例中,指向外部引用是无用的,因为这种架构中的对等点很可能已经支持所需的必需品,例如 URI、HTTP 和相应的媒体类型,并在其中实现。在使用自定义 media-types 的情况下,可以在运行时通过 plug-ins 或 add-ons 动态添加支持(如果支持)。
因此,Swagger 和 HATEOAS 并不相互排斥,但一旦您决定采用一条路线或另一条路线,另一个或多或少会变得无用。
建立一个RESTfulAPI并不是一个二元的概念。这就是为什么我们使用 Richardson 成熟度模型来衡量 RESTful 和 API 的原因。
基于此成熟度模型
- 在第 0 级,我们为 API 的客户端提供机制以调用服务器上的某些方法(简单 RPC)
- 在级别 1,我们在服务器上公开资源,因此 API 的客户端可以直接访问它需要的资源(公开资源)
- 在第 2 层,我们为 api 的客户端与 API(暴露的资源)进行交互提供了一种统一的方式,并且 HTTP 协议具有这些方法(使用 HTTP 动词与资源)。
- 最后一步是让我们的 api 可供客户探索。 HATEOAS 提供此类功能(通过 HTTP),这意味着它添加了可以在资源上执行的相关链接和可供性(额外方法),因此 API 的客户端可以理解其行为。
基于正确设计的这些定义 RESTful API 客户端和服务器之间没有耦合,客户端可以与暴露的端点交互并发现它们。
另一方面,swagger 是一种工具,可以帮助您记录您的 API 以及一些额外的好东西(代码生成器)。
我相信 Swagger(在 swagger Hub 的帮助下)提供了实现成熟度级别最高为 2 的 RESTful 端点的服务。但它没有更进一步,也没有提供适当的支持HATEOAS.
您可以在 (json/yml) 文件中定义您的资源和 HTTP 动词。并且基于这个定义,Swagger 可以生成 API 文档和额外的好东西(客户端存根和服务器的骨架实现 API)。
对于所有使用过 Java RMI、SOAP...的人来说,额外的好东西部分是对旧技术的提醒,在这些旧技术中,客户端和服务器之间存在紧密耦合,因为存根和骨架实现都是基于相同的 API 定义文件构建的。
任何人都可以解释 Swagger 和 HATEOAS 之间的区别。我可以搜索很多次,但是没有哥们可以从这两个方面解释正确的详细答案。
Swagger:Swagger 有助于整个 API 生命周期的开发,从设计和文档到测试和部署。 (参考swagger.io)
HATEOAS:作为应用程序状态引擎的超媒体
Ion 表单是一个集合对象,其中值成员数组包含表单字段。 Ion Forms 确保可以自动发现支持数据提交的资源转换(链接)(通俗地称为 HATEOAS)。 (参考https://ionspec.org/)
一个是支持API设计和测试的框架,另一个是API设计架构。
Swagger 和 HATEOAS IMO 之间的主要区别(未包含在已接受的答案中)是,只有 RPC 式 API 才需要 Swagger。然而,这样的 API 实际上与 REST 几乎没有任何关系。
还有一个更广泛的误解,认为通过 HTTP 交换的任何东西都会自动 RESTful(~ 根据 REST 架构风格),但事实并非如此。 REST 只是定义了一组约束,这些约束不是选择或选项,而是强制性的。从开始到结束。不是 RESTful 并没有错,但是将这样的架构称为 REST 是错误的。
Swagger 描述了可以在端点上执行的操作和需要发送到服务的负载(包括 headers 和预期的表示格式),还描述了客户端可能期望的响应.这使得 Swagger 既可以用作文档,也可以用作 API 的 testing-framework。由于 Swagger 与 API 的紧密耦合,它的行为很像典型的 RPC 服务描述,即类似于 SOAP 中的 WSDL 文件或 RMI 或 CORBA 中的存根或骨架 类。如果端点发生变化或有效负载中的某些内容发生变化,根据 Swagger 文档实施的客户端可能会随着时间的推移而中断,只是重新引入典型 RPC 实施所具有的相同问题。
另一方面,REST 和 HATEOAS 是为发现和进一步开发而设计的。 REST 不是一种协议,而是一种架构风格,它描述了分布式系统中客户端和服务器之间的交互流。它基本上采用了使 Web 如此成功的概念,并将其转化为应用程序层。因此,适用于可浏览 Web 的相同概念也适用于 REST。因此,HATEOAS(links、link 关系和 link 名称的使用和支持)与 Web 的行为相似也就不足为奇了。
在设计 REST 架构时,考虑一个状态机是有益的,其中服务器提供客户端采取进一步操作所需的所有信息。 Asbjørn Ulsberg 在 2016 年举行了一场精彩的演讲,他 explains affordances and how a state machine might be implemented through HATEOAS。除了通用或标准化的 media-types 和关系名称之外,无需 out-of-band 知识即可与服务进一步交互。就 Asbjørn 在他的演讲中给出的烤面包机示例而言,烤面包机可能具有状态 off
、on
、heating
和 idle
,其中打开烤面包机将导致从 off
到 on
的状态转换,然后是到 heating
的状态转换,直到达到某个温度,此时状态转换到 idle
并在 idle
之间切换heating
直到烤面包机关闭。
HATOAS 将为客户端提供有关当前状态的信息,并包括 link 客户端可以调用以转换到下一个状态的信息,即再次关闭烤面包机。这里需要强调的是,服务器为客户端提供了客户端接下来可能执行的每个操作。客户端实现者无需查阅任何专有 API 文档即可使客户端能够与 REST 服务进行交互。此外,URI 不必有意义或旨在传达 semantical-expressive 结构,因为客户端将确定通过 link-relation 名称调用该 URI 是否有意义。此类关系名称由 IANA, by a common approach such as Dublin Core or schema.org or by absolut URIs acting as extension attributes 指定,它可能指向 human-readable 描述,进一步可能通过 mouse-over 工具提示等传播给用户。
希望大家亲眼看到,Swagger只需要描述RPCWeb-APIs,而不是遵循REST架构设计的应用。通过 REST APIs 交换的消息应该包括客户端在下一个状态转换时做出明智选择所需的所有信息。因此,将此类消息流和交互设计为状态机是有益的。
更新:
How are Swagger and HATEOAS mutually exclusive? The former documents your endpoints (making auto-generating code possible) and the latter adds meta-information to your endpoints which tell the consumer what they can do (i.e. which other endpoints are available). These are very different things.
我从来没有说过它们是相互排斥的,只是它们有两个不同的目的,如果你遵循一种方法,另一种方法或多或少会变得无用。但是,同时使用两者没有任何意义。
让我们将讨论转移到 Web 领域,因为这可能更容易理解,REST 实际上只是 Web 上使用的概念的概括,所以执行此步骤是很自然的,也是一个很好的建议一般设计 REST 架构。想一想您作为用户想要向服务器发送一些数据的情况。您以前从未使用过该服务,所以您基本上不知道请求的样子。
在 Swagger 中,您将调用端点文档,select 最有可能解决您的任务的选项,阅读请求的外观并将 test-case 入侵您的应用程序最终生成发送到相应位置的 HTTP 请求。 Auto-generating 代码可能会为您节省一些黑客时间,但您仍然需要o 将存根 类 集成到您的应用程序中,并至少测试一次以确保安全。如果您稍后需要集成 API 的第二个服务或一般的另一个 API 的第二个服务,您需要从头开始并查找 Swagger 文档,生成或破解交互代码并将其集成到您的域中。涉及大量手动步骤,如果发生 API 更改,您需要更新客户端,否则它可能会停止工作。
然而,在 Web 示例中,您只需启动 browser/Web 客户端,调用允许您将数据发送到服务器的相应 URI,服务器很可能会向您发送一个 HTML您只需要填写表格并单击发送按钮,它会自动将请求发送到服务器,服务器将开始处理它。这是 HATEOAS。您使用给定的控件来驱动您的工作流程。服务器会告诉您的客户端发出有效请求所需的每一个细节。它为您的客户端提供了要将请求发送到的目标 URI、它应该使用的 HTTP 方法,并且通常还隐式地提供了有效负载应该使用的媒体类型。除此之外,它还为您的客户端提供了预期 and/or 有效负载应包含的支持元素。 IE。该表单可能需要您填写几个输入字段,在一组给定的选项中 select 或使用一些其他控件,例如转换为有效日期或时间表示的日期或时间选择器值.您需要做的就是在您的 Web 客户端中调用相应的资源。没有 auto-generation,没有融入你的 browser/application。使用其他服务(来自相同或不同的提供商)很可能会以相同的方式工作,因此只要支持交换 media-type 请求和响应,就无需更改或更新您的 HTTP 客户端(浏览器) .
在您依赖 Swagger RPC 风格的文档的情况下,该文档是关于如何与服务交互的真相。混入一些 HATEOAS 信息不会给您带来任何好处。在 Swagger 案例中,携带额外的 meta-information 使 request/response 膨胀,没有明显的原因,因为参考文档中提供了所有必需的信息,肯定会导致人们开始质疑该服务开发人员的理智,并要求减少有效载荷。只要在这里看一会儿 SO,您就会发现足够多的问题,询问如何进一步优化交互并将消息大小减少到最小,因为它们处理每个小请求并且根本不使用响应缓存。在 HATEOAS 案例中,指向外部引用是无用的,因为这种架构中的对等点很可能已经支持所需的必需品,例如 URI、HTTP 和相应的媒体类型,并在其中实现。在使用自定义 media-types 的情况下,可以在运行时通过 plug-ins 或 add-ons 动态添加支持(如果支持)。
因此,Swagger 和 HATEOAS 并不相互排斥,但一旦您决定采用一条路线或另一条路线,另一个或多或少会变得无用。
建立一个RESTfulAPI并不是一个二元的概念。这就是为什么我们使用 Richardson 成熟度模型来衡量 RESTful 和 API 的原因。
基于此成熟度模型
- 在第 0 级,我们为 API 的客户端提供机制以调用服务器上的某些方法(简单 RPC)
- 在级别 1,我们在服务器上公开资源,因此 API 的客户端可以直接访问它需要的资源(公开资源)
- 在第 2 层,我们为 api 的客户端与 API(暴露的资源)进行交互提供了一种统一的方式,并且 HTTP 协议具有这些方法(使用 HTTP 动词与资源)。
- 最后一步是让我们的 api 可供客户探索。 HATEOAS 提供此类功能(通过 HTTP),这意味着它添加了可以在资源上执行的相关链接和可供性(额外方法),因此 API 的客户端可以理解其行为。
基于正确设计的这些定义 RESTful API 客户端和服务器之间没有耦合,客户端可以与暴露的端点交互并发现它们。
另一方面,swagger 是一种工具,可以帮助您记录您的 API 以及一些额外的好东西(代码生成器)。
我相信 Swagger(在 swagger Hub 的帮助下)提供了实现成熟度级别最高为 2 的 RESTful 端点的服务。但它没有更进一步,也没有提供适当的支持HATEOAS.
您可以在 (json/yml) 文件中定义您的资源和 HTTP 动词。并且基于这个定义,Swagger 可以生成 API 文档和额外的好东西(客户端存根和服务器的骨架实现 API)。
对于所有使用过 Java RMI、SOAP...的人来说,额外的好东西部分是对旧技术的提醒,在这些旧技术中,客户端和服务器之间存在紧密耦合,因为存根和骨架实现都是基于相同的 API 定义文件构建的。