【问题标题】:REST - Updating partial dataREST - 更新部分数据
【发布时间】:2016-12-18 10:01:53
【问题描述】:

我目前正在编写一个 REST 服务和一个主要使用该 REST 服务的网站。

型号:

public class User {
    private String realname;
    private String username;
    private String emailAddress;
    private String password;
    private Role role;
    ..
}

查看:

要更新的表单

  • 实名
  • 电子邮件地址
  • 用户名

更新角色的另一种形式

还有第三种修改密码的方式

.

专注于第一个视图,哪种模式是一个好的做法?

PUT /user/{userId}

恕我直言,不是因为表单只包含部分数据(不是角色,不是密码)。所以它不能发送整个用户对象。

PATCH /user/{userId}

可能没问题。是实现它的好方法,例如:

1) 读取当前用户实体

2)

if(source.getRealname() != null) // Check if field was set (partial update)
dest.setRealname(source.getRealname());
.. for all available fields

3) 保存目的地

POST /user/{userId}/generalInformation

作为实名、电子邮件、用户名的摘要

.

谢谢!

【问题讨论】:

    标签: rest spring-mvc restful-url


    【解决方案1】:

    这种方法的一个问题是用户不能取消可选字段,因为如果(输入为空且值)为空,代码不会应用该值。 这对于密码或其他必需的实体字段可能没问题,但例如,如果您有一个可选的 Note 字段,则用户无法“清理”该字段。

    此外,如果您使用的是普通 FORM,则不能使用 PATCH 方法,只能使用 GET 或 POST。

    如果您使用 Ajax,您可能会对 JSON Merge Patch(更简单)和/或 JavaScript Object Notation (JSON) Patch(最完整)感兴趣;有关在部分更新和使用 PATCH 时可以找到的问题的概述,另请参阅 this page

    有一点是,表单只能发送空值或填充值,而 JSON 对象属性可以有三种状态:值(更新)、空(设置为空)和无属性(忽略)。

    我成功使用的一个实现是ZJSONPATCH

    【讨论】:

    • 谢谢。我已经使用 JSON(序列化的 html 表单)。我真的很喜欢补丁方法。你有没有为此使用过任何 java api?
    【解决方案2】:

    专注于第一个视图,哪种模式是一个好的做法?

    我的建议从一个简单的想法开始:作为 HTML 中的网页,您将如何做到这一点?

    您可能从提供用户视图的页面开始,其中包含“更新个人资料”、“更新角色”、“更改密码”等超链接。单击更新配置文件将加载一个 html 表单,可能已经填写了一堆默认值。操作员将进行更改,然后提交表单,该表单将向知道如何解码消息正文和更新的端点发送消息模型。

    前两个步骤是“安全的”——操作员没有提出任何更改。在最后一步中,运营商提出了更改建议,因此安全方法不合适。

    HTML,作为一种超媒体格式,仅限于两种方法(GET、POST),所以我们可能会看到浏览器做类似的事情

    GET  /user/:id
    GET  /forms/updateGeneralInformation?:id
    POST /updates/generalInformation/:id
    

    您可以使用多种不同的拼写方式,具体取决于您更喜欢如何组织资源。浏览器不在乎,因为它只是跟随链接。

    您的 API 具有同样的灵活性。工具包中的第一个技巧应该始终是“我可以用新资源解决这个问题吗?”。

    Ian S Robinson 观察到:specialization and innovation depend on an open set。如果您将自己限制在 HTTP 方法的封闭词汇表中,那么您需要创新的开放集需要位于其他地方:RESTful 方法是使用开放的资源集。

    配置文件的更新听起来确实像是一个应该是幂等的操作,所以如果可以的话,您希望使用 PUT。有什么问题吗:

    GET /user/:id/generalInformation
    PUT /user/:id/generalInformation
    

    它是一个写,它是幂等的,它完全替代了 generalInformation 资源,所以 HTTP 规范很高兴。

    是的,通过单个请求更改多个资源的当前表示是有效的 HTTP。其实这是RFC 7231描述的方法之一

    通过定位一个单独标识的资源,可以实现部分内容更新,该资源的状态与较大资源的一部分重叠

    如果您不喜欢支持资源的多个视图并在每个视图上支持 PUT,则可以通过引入命令队列来应用相同的启发式(“添加更多资源”)来处理对底层模型的更改。

    GET /user/:id/generalInformation
    PUT /changeRequests/:uuid
    

    您是否希望将所有变更请求表示为同一集合中的条目,或者为操作子集提供专门的变更请求集合。番茄,番茄。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-27
      • 2017-04-27
      • 2020-04-12
      • 2019-07-13
      • 2015-03-02
      • 2018-09-01
      • 2021-07-27
      • 2019-04-28
      相关资源
      最近更新 更多