在你的例子中,看起来Connections
是资源。目前还不完全清楚是否Orders
是真正的资源。我猜可能是的,但是要有一个Order
你需要一个Client
and Connection
。所以,要创建一个Order
您将需要公开一个集合,可能来自Client
or Connection
,可能两者都有。
我认为这种脱节源于“现在我们已经有了可用连接的列表,客户端可以选择一个并创建一个Order
这是完全正确的,但它是远程过程调用 (RPC) 思维,而不是 REST。客观上,两者都不比另一个更好,除非在一组特定的项目需求的背景下,并且通常它们不应该混合在一起。
使用 RPC 思维方式,定义创建订单方法(例如使用 OpenAPI),并且任何客户端都应该使用一些带外信息来确定所需的正确形式(即通过阅读 OpenAPI 规范)。
凭借 REST/HATEOAS 心态,正确的方法是公开Orders
收集自Connection
. Each Connection
集合中有一个self
链接和一个Order
集合(链接或对象,根据应用程序要求定义)。每一项的Order
has a self
链接,这就是指定可供性的地方。一个Order
是一种已知类型(即使使用 REST/HATEOAS,客户端和服务也必须至少就共享词汇表达成一致),客户端大概知道如何定义。该词汇表可以使用任何有效的机制来定义——json-ld、XSD 等。
HATEOAS 要求结果包含客户端更新状态所需的所有内容。不能有带外信息(共享词汇表除外)。因此,要解决您的问题,您要么需要公开一组Order
s from Connection
或者你需要允许Order
通过发布到创建Connection
。如果后者看起来有点像黑客,那么它可能就是这样。
例如,在 HAL-Forms 中,我会执行以下操作:
{
"connections": [{
"id": "aaa",
"carrier": "Fast Bus",
"price": 3.20,
"departure": "2019-04-05T12:30"
"_links": {
"self": { ... }, // link to this connection
"orders": {} // link to collection of orders for this connection
}
},
, ...],
"_links": {
"self": { ... } // link to the collection
},
"_templates": { ... } // post/put/patch/delete connection
}
客户将点击链接orders
从那里会得到_templates
包含管理说明的集合Order
资源。这Order
POST 可能需要连接标识符和客户端信息。这HAL-Forms 规范 https://rwcbook.github.io/hal-forms/定义一个正则表达式属性,可用于指定为任何特定表单元素提供的数据类型。由于您已通过特定连接导航到达订单,因此您可以在您的_templates
对于该订单,需要哪些字段。例如/orders?connectionType=aaa
将返回一组不同的必需属性/orders?connectionType=bbb
但两者都使用相同的self
的链接/orders?connectionType={type}
并且您可以在 POST/PUT/PATCH 上验证它。
我应该注意到 Spring-HATEOAS 超出了 HAL-Forms 规范并允许多个_links
and _templates
. See 这个 GitHub 问题 https://github.com/mamund/hal-forms/issues/24.
看起来 HATEOAS/REST 可能比简单的 OpenAPI/RPC API 需要更多的工作,而且确实如此。但是,假设客户设计良好,您将放弃简单性,获得灵活性和弹性。哪种方法是正确的取决于很多因素,其中大多数不是技术因素(团队技能、预期消费者、您对客户的控制程度、维护等)。