Ser*_*nin 8 rest restful-architecture
我有一个具有多个属性的实体,比如说"项目".除了简单的属性,项目可能有一个«状态»列表,其中最后一个是当前的.我有一个Web表单来创建/编辑项目.可以在此表单中更改此项目的所有属性,并且用户还可以为项目添加新状态(但不能更改或删除旧状态).
项目状态是纯粹的复合实体,它们在项目范围之外没有任何独特的含义或标识,并且它们不能直接处理,因此它们显然不值得使用特殊的根REST资源.
根据REST架构,我创建了一个名为/ projects的资源.POST用于创建新项目,PUT用于更改现有项目.
但是,我不希望客户端将项目与其所有历史状态一起推送,首先是因为此集合太重,其次是因为业务逻辑仅允许添加状态,而不是更改或删除它们,因此将项目设置为PUT无论如何,连同其所有状态都没有任何意义.
仅具有新状态的项目也不是一种选择,因为它违反了PUT的幂等性.
我也不喜欢在第二个HTTP请求中发布状态的想法,例如/ project/{id}/status,因为这会从用户的角度打破更新操作的原子性.如果第二个请求在线路上丢失,则项目将与编辑它的用户不一致(属性已更改,但状态保持不变).创建RESTful"事务"对于更新看似单一的实体这一简单任务来说似乎有点过分(并且也容易出错).
这种问题在我的工作中非常普遍,并且可以如此概括:更新复杂的复合实体的REST非常正确和原子的方式是什么,业务逻辑只允许部分更新?
我认为如果你想进行部分更新(这实际上是你的情况),你应该使用该方法PATCH。这允许更新没有依赖项(状态)的项目或没有项目提示的依赖项。
您会注意到有一种格式来描述方法内要执行的操作PATCH。它称为 JSON 补丁(请参阅https://www.rfc-editor.org/rfc/rfc6902)。此格式描述了您想要在请求中执行的操作:添加元素、更新元素、删除元素……
我认为,如果您想要(例如)更新特定项目的名称、删除状态(这也是一个示例,因为我读到您想禁止此操作!)并在中添加一个新状态,您可以拥有类似的东西一个原子请求:
PATCH /projects/1
[
{
"op": "replace",
"path": "/name",
"value": "the new name of the project"
},
{
"op": "remove",
"path": "/statuses/1"
},
{
"op": "add",
"path": "/statuses/",
"value": {
"name": "my status",
(...)
}
}
]
Run Code Online (Sandbox Code Playgroud)
请注意,您可以将所需内容放入属性中name以标识资源状态中的相关元素。因此/statuses/1可以是数组中的第二个元素、具有 id 值的状态1或其他内容。
服务器端对请求的处理可以是原子的。
我写了一篇关于批量更新的博客文章:https://templth.wordpress.com/2015/05/14/implementing-bulk-updates-within-restful-services/。我认为“实施批量更新”部分可能符合您的要求。
希望它对你有帮助,蒂埃里
| 归档时间: |
|
| 查看次数: |
491 次 |
| 最近记录: |