REST 中的任意组 [英] Arbitrary Groups In REST

查看:30
本文介绍了REST 中的任意组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近被 Jim Webber 推荐了一场演讲.其中有一个非常有趣的点.

I was recently recommended a talk by Jim Webber. And there was a very interesting point in there.

Jim 说,当您认为数据库中的行、领域对象和 REST 服务中的资源之间存在 1-1 对应关系时.当想要跨可耕种组处理工作时,这会变得很困难.

Jim says that when you think that there is a 1-1 correspondence between rows in your database, domain objects and resources in REST service. This makes it hard when want to transact work across arability groups.

不,他继续指出,如果您说有 3 个用户并想要更新他们,那么您可以按顺序进行更新,这非常糟糕,因为您必须跟踪每个用户并处理问题,如果 3 个用户中有 1 个(或您希望发生多少笔交易).

No he goes on to point that if you have say 3 users and want to update them, you do then sequentially and it is very poor because you have to track each of them and handle issues if 1 out of the 3 (or how many transactions you want occur).

他提到你应该处理这个问题的方法是为所有 3 个用户创建一个资源.资源既便宜又无限(您可以随心所欲地制作),因此请使用它们.因此,创建该资源并在单个操作中更新其状态.

He mentioned the way you should handle this is to make a resource, for all of the 3 users. Resources are cheap and infinite (you can make as many as you want) so use them. So create that resource and in a single operation put their status update.

这对我来说是一个非常有趣的点,因为有时我想对我认为是单一的多个事物执行操作.

This is an extremely interesting point to me as there have been times where I have wanted to perform an operation on multiple things that i considered to be singular.

所以这是一个例子:假设我有一个用户列表.说 100.用户将是他们自己的东西/资源.我想从该列表中挑选 x 数量的用户(比如随机 10 个)并为他们应用 50 点.我想将这些点应用于域中没有唯一连接的这些用户,他们只是随机的一组用户.任意组.

So here is an example: Say I have a list of users. Say 100. Users would be their own thing/resource. I want to pick x amount of users out of that list (say 10 randomly) and apply 50 points to them. I want to apply these points to these users that have no unique connection in the domain, they are just a random group of users. a arbitrary group.

我将如何像 Jim Webber 暗示的那样创建一个休息端点/资源来处理这个操作?

How would I create a rest endpoint/resource as Jim Webber is implying to handle this operation?

现在,在我公认的旧思维框架中,我会制作一个特定的资源,如用户/积分/批量/(或其他东西),并传入用户 ID 和我将应用它们的积分列表.我永远不会有将它们视为资源的心态,我只会有一个 hacky 命令休息端点来执行它.

Now In my admittedly old frame of mind I would go about it making a specific resource like users/points/bulk/ (or something) and pass in a list of user id's and the points I would apply them. I would never have had the mindset of treating them as a resource, I would have just had an hacky command rest endpoint to perform it.

Jim 指出的这一点真的是我从来没有考虑过的,这是一种思维方式的改变,它真的会让事情变得更干净.

This point Jim has pointed out is really something I never considered and is such a change of mindset, that it would really make things cleaner.

有人可以解释一下这是什么意思并举例说明它的外观

Could someone explain this to mean and give an example to how it would look

谢谢

推荐答案

他提到你应该处理这个问题的方法是为所有 3 个用户创建一个资源.资源既便宜又无限(您可以随心所欲地制作),因此请使用它们.因此,创建该资源并在单个操作中更新其状态.

He mentioned the way you should handle this is to make a resource, for all of the 3 users. Resources are cheap and infinite (you can make as many as you want) so use them. So create that resource and in a single operation put their status update.

...

我将如何像 Jim Webber 暗示的那样创建一个休息端点/资源来处理这个操作?

How would I create a rest endpoint/resource as Jim Webber is implying to handle this operation?

这里的基本经验法则是:您将如何在网络上进行操作?由于 REST 只是 Web 允许扩展到今天规模的交互模型的泛化,因此在 Web 上被证明是成功的概念可以(并且应该)用于 REST 架构.

The basic rule of thumb here is: How would you do it on the Web? As REST is just a generalization of the interaction model the Web allowed to grow to its todays size, the same concpet that proven to be successful on the Web can (and should) be used in a REST architecture.

资源组究竟是什么?!如果您考虑大多数以团队形式进行的体育活动,例如足球等,几乎所有运动员都可以分为某些组.IE.A队的球员和B队的球员或所有防守球员所有进攻球员.每个玩家都是自己的资源,但每个可用的组都是自己的资源,我们也可以给它一个名字.我们可以进一步谈论团体而不是个人球员.这使我们无需单独引用所有玩家,而是将所有玩家都包含在一个简短的声明中.诸如Team A 击败Team B"之类的语句很可能会假设Team A 中的每个玩家都在玩比对手队伍中的对手更好.

What is a group of resources actually?! If you think about most sport activities that are played in teams, such as football or the like, almost all players can be divided into certain groups. I.e. players of Team A and players of Team B or all defensive players or all attacking players. Each of the players is its own resource but each of the available groups is its own resource as well as we could give it a name also. We can further talk about the group instead of the individual player. Which allows us to instead of reference all of the players individually, to include all of them within a single, short statement. A statement such as "Team A beat the crap out of Team B" will most likey subsume that each of the players on Team A was playing better than their counterparts in the opponent team.

现在只需为客户提供将资源组合在一起的工具集即可.在典型的 HTML 页面中,您可以使用表格表示所有球队的本赛季所有现役足球运动员,并带有一个复选框来选择某些球员和一些控制元素,例如提交按钮,允许您创建一个组选定的球员.支持 HTML 表单不仅包含您可以从中选择特定玩家的实际数据集和提交按钮,还包含一个目标 URI,请求必须发送到该 URI 以及要使用的请求方法.HTML 默认使用 application/x-www-form-urlencoded 作为表示格式将数据发送到服务器,服务器知道根据调用的端点、使用的 HTTP 操作和接收的媒体类型如何相应地处理数据.

It is now only a matter of providing clients with the toolset to group resources together. In a typical HTML page you could i.e. have a table representation of all the active football players of this season across all teams with a checkbox to select certain players and some control element, such as a submit button, that allows you to create a group for the selected players. The backing HTML form contains not only the actual data set you could select sepcific players from and a submit button but also a target URI where the request has to be sent to as well as a request method to use. HTML by default uses application/x-www-form-urlencoded as representation format to send the data to the server, which knows depending on the invoked endpoint, the HTTP operation used and the media type received how to process the data accordingly.

由于先前的分组请求将创建一个新资源,服务器将使用 201 Created 响应代码和 Location HTTP 标头响应,其值是指向新创建的分组可访问的位置的 URI.客户端现在可能会自动重定向到该 URI,或者它可以使用返回的 URI 调用对该资源的进一步操作.由于域模型确实(并且可能应该)不需要匹配资源或可供性模型,因此每个个人玩家资源以及团队资源都可以使用相同的数据库条目将数据呈现给客户端.在更新一个资源(单个玩家或整个团队)时,其他资源也可能受到此操作的影响.

As a new resource will be created as a consequence to the previous grouping request, the server will respond with a 201 Created response code and a Location HTTP header whose value is a URI pointing to the location the newly created grouping is accessible. A client may now get redirected to that URI automatically or it can use the returned URI to invoke further operations on that resource. As the domain-model does (and probably should) not need to match a resource or affordance model, each of the invidvidual player resources as well as the team-resource may use the same database entries to present the data to the client. On updating one resource (either an individual player or the team as a whole) other resources may get influenced by this operation as well.

如果你看一下 PUT 的定义HTTP 规范,您可以阅读如下内容:

If you take a look at the definition of PUT in the HTTP specification, you can read something like this:

应用于目标资源的 PUT 请求可能会对其他资源产生副作用.

A PUT request applied to the target resource can have side effects on other resources.

由于这种副作用,通过 PUT 执行的更新可能会达到类似于部分更新的效果:

Due to this side-effect it is possible for an update performed via PUT to achive somthing similar to a partial-update:

通过将状态与较大资源的一部分重叠的单独标识的资源作为目标,或者使用专门为部分更新定义的不同方法(例如,RFC5789).

Partial content updates are possible by targeting a separately identified resource with state that overlaps a portion of the larger resource, or by using a different method that has been specifically defined for partial updates (for example, the PATCH method defined in RFC5789).

即如果您通过 PUT 更新 Team APlayer 1,它会创建一个副作用,即 Team A 的状态的部分更新 因为这只是使用数据模型为该特定玩家提供的相同数据.

I.e. if you update Player 1 of Team A via PUT it creates as a side effect a partial-update of the state of Team A as this just uses the same data the data-model provides for that particular player.

为了在 REST 架构中实现相同的功能,如前所述,为客户端提供结构化数据的相同概念,它可以从中选择一个子集并对该子集执行操作,例如为这些数据创建一个新资源应使用选定的元素.与 HTML 占主导地位的 Web 相比,受支持的媒体类型在 REST 架构中可能会有很大差异.在这里,内容类型协商是一个非常重要的部分,因为它允许服务器选择客户端支持的最合适的表示格式.不应使用专有表示格式,而应使用标准化格式来增加不受您控制的客户端与您的系统进行交互的可能性.虽然目前正在努力引入支持客户端的媒体类型,其形式类似于 HTML 中使用的表单形式的客户端反馈,但除了 HTML 之外,没有事实上的标准表单表示,但仍被广泛接受.有几种特别基于 JSON 的方法,例如 hal-formshalo+json、IonHydra,在工作中,虽然,如上所述,没有什么是真正的在生产中广泛使用.

In order to achive the same functionality in a REST architecture, as mentioned before, the same concepts of providing a client with structured data it can select a subset from and perform operations on that subset, such as creating a new resource for these selected elements, should be used. In contrast to the Web where HTML is dominant, the supported media-types may varry drastically in a REST architecture. Here, content-type negotiation is a very important part as this allows the server to chose the most suitable representation format that is supported by the client. Instead of using proprietary representation formats, standardized formats should be used to increase the likelihood of clients not under your control to be able to interact with your system. While there is an ongoing effort on introducing media-types that support clients with client-feedback in the form of forms similar to the ones used in HTML, there is no de-facto standard form-representation, except for HTML, yet widely accepted. There are a couple of especially JSON-based approaches, such as hal-forms, halo+json, Ion or Hydra, in the working, though, as mentioned, nothing that is really used widely in production.

由于您的实际意图是原子地更新一堆资源,您可以使用 PATCH在这里,不需要创建新资源,因为 PATCH 被定义为原子地执行所有指令 - 要么全部成功,要么根本不执行.在规范中,PATCH 的定义类似于软件工程中对补丁的理解,通过将一系列指令应用于资源以将其转换为所需的输出.application/json-patch+json 是一种表示格式,它是非常接近实际定义,而 application/merge-patch+json 通过定义要应用的默认规则,对它有完全不同的看法,这取决于请求是包含修改过的还是无效的字段值.由于后一种表示格式只能在单个资源上工作,因此第一种表示格式可用于批量更新.通过直接定位集合资源,JSON 指针可用于寻址直接在该集合中的子资源.

As your acutal intention is to update a bunch of resources atomically, you could use PATCH here as well, without the need of creating new resources, as PATCH is defined to perform all of the instructions atomically - either all succeed or none at all. In the spec, PATCH is defined similar to how patching is understood in software engineering, by having a sequence of instructions that should be applied to a resource to transform it to a desired output. application/json-patch+json is a representation format that is quite close to the actual definition whereas application/merge-patch+json has a totally different take on it by defining default rules to apply, depending whether the request contained a modified or nullified field value. As the latter representation-format is able to only work on a single resource, the first representation-format could be used for a batch update. By targeting the collection-resource directly, JSON Pointers can be used to address the respective fields of the sub-resources in that collection directly.

为了避免通过 PATCH 操作丢失数据,由于在获取最新状态、计算应用的必要步骤和将请求发送到 API 之间的中间更新,应该采用乐观锁定方法使用可通过条件请求实现的,例如ETag.

To avoid data-loss via PATCH operations, due to intermediary updates between fetching the most recent state, calculating the necessary steps to apply and sending the request to the API, an optimistic locking approach should be used that is achievable via conditional requests, such as ETag.

虽然补丁为您提供了以原子方式应用更改的能力,但我觉得将资源分组在一起,如果它们自然形成一个组,例如在玩家 - 团队示例中,感觉更常见并且重用了 REST 提出的交互模型还有更好的 IMO.

While patching provides you with the capability to apply the changes atomically, I feel that grouping resources together, if they naturally form a group, such as in the player - team example, feels more common and reuses the interaction model proposed by REST also better IMO.

这篇关于REST 中的任意组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆