这是Updating a value RESTfully with Post
的后续行动如何使用REST简单地附加到资源的属性。想象一下,我有customer.balance和balance是一个int。让我们说我只想告诉服务器将5添加到当前余额中。我可以这样做吗?如果是这样,怎么样?
请记住,客户不知道客户的现有余额,因此不能只是
(上面也会出现并发问题。)
答案 0 :(得分:4)
这是我answer to your other question的更简单变体。
如果您执行以下操作,我认为您仍处于REST的限制范围内。但是,我很好奇其他人对这种情况的看法,所以我希望听到别人的意见。
您的URI将是:
/customer/21/credits
您将信用资源(可能是<credit>5</credit>
)发布到URI,然后服务器可以获取客户的余额,并使用提供的值+=
。此外,您可以支持负面信用(例如<credit>-10</credit>
);
请注意,/customer/21/credits
不支持所有方法。仅支持POST是完全可以接受的。
但是,如果积分不是您系统中的真正资源,这会有点奇怪。 HTTP spec说:
如果在源服务器上创建了资源,则响应应该是201(已创建)并包含描述请求状态的实体,并引用新资源和Location头。
从技术上讲,您不是在这里创建资源,而是追加到客户的余额(实际上系统中所有先前信用的总和)。由于您没有保留信用(大概),您实际上无法返回对新“创建”信用资源的引用。您可能会返回客户的余额或<customer>
本身,但这对客户来说有点不直观。这就是为什么我认为将每个信用作为系统中的新资源更容易使用(见下文)。
这是根据你在其他问题中的回答改编的。在这里,我将尝试从客户端/服务器正在做的事情的角度来处理它:
客户端:
建立新的信用资源:
<credit>
<amount>5</amount>
</credit>
将资源发布到/customer/21/credits
在此处发帖意味着,“将此新<credit>
添加到此客户的<credit>
列表中。
服务器:
/customer/21/credits
+=
更改为客户的余额向客户发送回复:
<credit href="/customer/21/credits/credit-id-4321234">
<amount>5</amount>
<date>2009-10-16 12:00:23</date>
<ending-balance>45.03</ending-balance>
</credit>
这为您提供了以下优势:
/customer/21/credits/[id]
)如果您支持,客户可以检索有序的信用列表;例如GET /customer/21/credits
可能会返回:
<credits href="/customer/21/credits">
<credit href="/customer/21/credits/credit-id-7382134">
<amount>13</amount>
...
</credit>
<credit href="/customer/21/credits/credit-id-134u482">
...
</credit>
...
</credits>
答案 1 :(得分:0)
要以REST-ful的方式考虑这一点,您需要将行动本身视为一种资源。例如,如果这是银行业务,并且您想要更新帐户余额,则需要创建存款资源,然后添加其中一个。这样做的结果是更新客户的余额
这也有助于解决并发问题,因为您将提交+5操作,而不需要事先了解客户的余额。并且,您还可以回忆起该资源(例如存款/ 51存款,ID为51)并查看其他详细信息(即存款原因,存款日期等)。
编辑:意识到使用5的ID作为存款实际上会混淆问题,因此将其更改为51.
答案 2 :(得分:0)
嗯,除了@ Rob-Hruska的解决方案之外还有其他选择。
基本思路是一样的:将每个信用/借记操作视为独立交易。但是我曾经使用过支持在json中存储无模式数据的后端,因此我最终将API定义为带有动态字段名称的 PUT 。像这样:
PUT /customer/21
{"transaction_yyyymmddHHMMSS": 5}
我知道这在“信用/借记”上下文中是不合适的,因为活动帐户可能会有不断增长的交易记录。但在我的背景下,我使用这样的策略存储有限数据(实际上我在驾驶旅程中存储了不同批次的GPS路点)。
缺点:这种api风格严重依赖后端行为的无模式功能。
优点:从语义的角度来看,至少我的方法完全是RESTful。
相比之下,@ Rob-Hruska的“简单,稍微丑陋”的解决方案1没有在“201 Created”响应中返回有效的Location头,这不是常见的RESTful行为。 (或者,也许,我们可以让@ Rob-Hruska的解决方案1也返回一个虚拟的Location头,它指向“410 Gone”或“404 Not Found”页面。这更加RESTful吗?欢迎评论!)