【问题标题】:REST: How to update a row and create zero or more of other resource on same request?REST:如何更新一行并根据同一请求创建零个或多个其他资源?
【发布时间】:2016-11-06 17:15:02
【问题描述】:

我会尽量让这件事变得简单,这可能是个愚蠢的问题。

我正在重写一个已有 7 年历史的 Web 应用程序(帮助台软件)。需要使其成为 REST API 以供不同客户端 Web 浏览器和移动应用程序使用。还需要使业务逻辑尽可能接近原始的,目前运行良好。

目前关于 REST 的斗争:

我需要更新资源让我们说/tickets/47321

如果此资源的status_id 发生更改,则需要保存此更改的记录,两者都在同一个数据库事务中,因为它需要all-or-nothing。这就是原始应用程序的工作方式,我们希望保持这种行为。

所以问题是:

我可以PUTtickets/47321 整个资源或部分状态表示来更新驻留在服务器中的资源并创建历史更改的新记录(如果status_id 不同)并将它们都返回给客户端作为 JSON:

 {
    ticket: {}, // new ticket state
    history: {} // the new created record of history change 
 }

这样客户端可以更新ticket并将历史添加到历史更改列表中(如果有任何返回)?

【问题讨论】:

  • 是的,您可以这样做。在 Java 中,一些轻量级的 REST 框架包括 Restlets 和 JAX-RS,而 Spring 在较重的方面是一个很好的框架。
  • 那么这种行为在 REST API 中发生是否正常?在PUT 上发送部分表示而不是整个资源来更新呢?
  • 为什么要发送部分表示?
  • 思考如果我只需要更改最多 1~3 个字段而不是全部。我知道有PATCH,但它需要以不同的方式使用,发送如何修改它的说明而不是更新状态

标签: rest restful-architecture httpverbs


【解决方案1】:

从技术上讲,是的,您可以这样做。但是,它可能不像简单地并排返回 2 个对象那么简单;看着Richardson Maturity Model (Level 1),人们会期望在之后收到相同类型的资源 调用 (PUT) 一个 api 端点。

话虽如此,您可以嵌入额外资源(按照Hypertext Application Language (HAL) 建议的draft 规范将历史更改附加到票证),或者更好(如果您的目标是 REST 级别3)、提供链接关系,符合Web Linking规范(RFC 5988)中定义的“Target IRI”从ticket:

  • /api:history?ticketId=47321 将返回属于该工单的所有历史记录,例如按创建日期分页和排序(您可以选择最新的)
  • /api:history?id=123 你会在服务器上做一些工作,以确保这直接指向最新的历史记录(与该票证 ID 相关)

关于部分更新,查看RFC 6902(定义补丁标准),从客户端的角度来看,API 可以这样调用

PATCH /ticket/47321

[
    { "op": "replace", "path": "/author", "value": "David"},
    { "op": "replace", "path": "/statusId", "value": "1"}
]

更多例子可以在here找到。

【讨论】:

  • 看起来一切都很好,但解决每个操作的补丁也很麻烦
猜你喜欢
  • 2015-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
相关资源
最近更新 更多