Jim Webber最近向我推荐了一个演讲。 那里有一个非常有趣的地方。
Jim说,当您认为数据库中的行,REST服务中的域对象和资源之间存在1-1对应关系时。这使得想要在跨小组进行事务时变得很困难。
不,他继续指出,如果您说3个用户并要更新,则需要按顺序进行,这非常可怜,因为如果3个用户中有1个(或1个,则必须跟踪每个用户并处理问题)您想要进行多少交易)。
他提到您应该处理此问题的方法是为所有3个用户创建资源。资源便宜且无限(您可以根据需要创建任意数量),因此请使用它们。因此,创建该资源并通过一次操作即可更新其状态。
对我来说,这是一个非常有趣的观点,因为有时我想对我认为是单数的多个事物执行操作。
所以这是一个例子: 说我有一个用户列表。假设100。用户将是他们自己的东西/资源。我想从该列表中挑选出x个用户(随机说10个),并向他们应用50分。 我想将这些点应用于这些在域中没有唯一连接的用户,它们只是一组随机的用户。任意组。
当吉姆·韦伯(Jim Webber)暗示要处理此操作时,我将如何创建剩余端点/资源?
现在,以我公认的旧思维方式,我将使用它来制作特定的资源(例如用户/积分/批量/(或其他)),并传递用户ID列表以及我将应用它们的积分。我永远不会有将它们视为资源的心态,我只会有一个骇人的命令休息端点来执行它。
Jim指出的这一点确实是我从未考虑过的事情,并且改变了心态,确实可以使事情变得更干净。
有人可以解释一下这个意思并举一个例子吗?
谢谢
答案 0 :(得分:0)
他提到您应该处理此问题的方法是为所有3个用户创建资源。资源便宜且无限(您可以根据需要创建任意数量),因此请使用它们。因此,创建该资源并通过一次操作即可更新其状态。
...
当吉姆·韦伯(Jim Webber)暗示要处理此操作时,我将如何创建剩余端点/资源?
这里的基本经验法则是:如何在Web上进行操作?由于REST只是对交互模型的概括,因此Web可以扩展到今天的规模,因此可以(并且应该)在REST体系结构中使用经证明在Web上成功的相同功能。
什么是一组资源?如果您考虑大多数在团队中进行的体育活动,例如橄榄球等,几乎所有的球员都可以分为某些组。即Team A
的玩家和Team B
或all defensive players
或all attacking players
的玩家。每个参与者都是自己的资源,但是每个可用的组都是自己的资源,我们也可以给它起一个名字。我们可以进一步讨论小组而不是单个参与者。这样一来,我们便可以将所有参与者都包含在一个简短的声明中,而不必单独引用所有参与者。像“ Team A
击败了Team B
的废话这样的说法将最有可能地暗示Team A
上的每个玩家的表现都好于对手团队中的对手。
现在只需要为客户提供工具集即可将资源分组在一起。在典型的HTML页面中,您可以拥有一个表格,该表格表示所有球队中本赛季所有活跃的足球运动员,并带有一个复选框以选择某些运动员和一些控制元素(例如提交按钮),该控件可让您为选定的球员。支持HTML的表单不仅包含您可以从中选择单独播放器的实际数据集和一个提交按钮,还包含一个必须发送请求的目标URI以及要使用的请求方法。默认情况下,HTML使用application/x-www-form-urlencoded
作为表示格式将数据发送到服务器,该服务器根据所调用的端点知道所使用的HTTP操作以及所接收到的媒体类型如何相应地处理数据。
由于先前的分组请求将创建新的资源,因此服务器将使用201 Created
响应代码和Location
HTTP标头进行响应,该标头的值是指向该位置的URI新创建的分组是可访问的。现在,客户端可以自动重定向到该URI,也可以使用返回的URI对该资源调用进一步的操作。由于域模型确实(可能应该)不需要匹配资源或能力模型,因此每个单独的玩家资源以及团队资源都可以使用相同的数据库条目将数据呈现给客户端。在更新一个资源(单个玩家或整个团队)时,其他资源也可能会受到此操作的影响。
如果您查看HTTP规范中PUT的定义,则可以阅读如下内容:
应用于目标资源的PUT请求可能会对其他资源产生副作用。
由于这种副作用,通过PUT
执行的更新可能会达到类似于部分更新的状态:
可以通过以下方式实现部分内容更新:将单独标识的资源的状态与较大资源的一部分重叠,或者使用专门为部分更新定义的另一种方法(例如,{{ 3}})。
即如果您通过Player 1
更新Team A
中的PUT
,则会产生Team A
状态的部分更新,这是副作用,因为这只会使用数据模型中的相同数据提供给该特定玩家。
为了实现REST体系结构中的相同功能,如前所述,向客户端提供结构化数据的相同概念可以从中选择一个子集并对该子集执行操作,例如为这些子集创建新资源选择的元素,应该使用。与HTML占主导地位的Web相比,受支持的媒体类型在REST体系结构中可能会发生巨大变化。在这里,内容类型协商是非常重要的部分,因为这允许服务器选择客户端支持的最合适的表示格式。不应使用专有的表示格式,而应使用标准化格式来增加不受您控制的客户端与系统进行交互的可能性。尽管人们一直在努力引入媒体类型,以类似于HTML中使用的形式支持具有客户端反馈的客户端,但是除了HTML之外,还没有实际的标准形式表示,但被广泛接受。有两种基于JSON的特别有效的方法,例如RFC5789,hal-forms,halo+json或Ion,但是,如上所述,没有什么是真正的在生产中广泛使用。
由于您的主要目的是原子更新大量资源,因此您也可以在此处使用Hydra,而无需创建新资源,因为PATCH
被定义为执行所有指令从原子上讲-要么全部成功,要么根本没有成功。在规范中,PATCH
的定义类似于软件工程中的补丁理解方式,它具有一系列应应用于资源以将其转换为所需输出的指令序列。 PATCH是一种非常接近实际定义的表示格式,而application/json-patch+json
通过定义要应用的默认规则来完全不同,具体取决于请求包含修改的字段值还是无效的字段值。由于后一种表示形式格式只能在单个资源上工作,因此第一种表示形式格式可用于批量更新。通过直接定位集合资源,application/merge-patch+json
可用于直接解决该集合中子资源的各个字段。
为避免通过PATCH
操作造成的数据丢失,由于在获取最新状态,计算应用所需的必要步骤以及将请求发送到API之间的中间更新,应使用一种乐观的锁定方法,即可通过JSON Pointers(例如conditional requests)实现。
虽然修补程序为您提供了自动应用更改的功能,但我认为将资源自然地分组在一起(例如在播放器-团队示例中)将资源分组在一起感觉更普遍,并且可以重用REST建议的交互模型更好的IMO。