Rest 使用修补程序设计用于执行部分更新的端点

Rest 使用修补程序设计用于执行部分更新的端点,rest,http,Rest,Http,考虑一个名为entity的大实体。它公开了100种不同的更新操作,包括添加和删除属性、更新属性等 在使用单个URI和应用程序服务器路由处理的许多情况之间,应该优先选择什么: PATCH /entity/[id] {"type":"a","key1":"val1","key2":"val2"} or {"type":"b","key3":"val3","key4":"val4"} or ... 。。。使用多个URI,每个应用服务器路由处理一个案例: PA

考虑一个名为entity的大实体。它公开了100种不同的更新操作,包括添加和删除属性、更新属性等

在使用单个URI和应用程序服务器路由处理的许多情况之间,应该优先选择什么:

PATCH /entity/[id]  {"type":"a","key1":"val1","key2":"val2"} or
                    {"type":"b","key3":"val3","key4":"val4"} or ...
。。。使用多个URI,每个应用服务器路由处理一个案例:

PATCH /entity/[id]/a  {"key1":"val1","key2":"val2"}
PATCH /entity/[id]/b  {"key3":"val3","key4":"val4"}
或者使用PUT?需要对实体进行非常部分的更新

考虑到REST遵从性、负载平衡器、缓存、KISS等因素,最好的方法是什么?如果您有任何想法,我们将不胜感激。

tl;博士 只要做得对,使用单端点支持补丁应该没问题

补丁请求有效负载应包含一组用于修改目标资源的指令。表示这组指令的合适格式是和,它们允许修改目标JSON文档中的嵌套值

对资源的状态执行修改 要对资源执行修改,可以使用PUT或PATCH,也可以同时使用两者。但是,这些方法之间的差异反映在服务器处理请求有效负载以修改目标资源的方式上:

在PUT请求中,有效负载是存储在服务器上的资源的修改版本。客户端正在请求将存储的版本替换为新版本。因此,它可能不完全适用于部分修改

在补丁请求中,请求负载包含一组指令,描述如何修改当前存储在服务器上的资源以生成新版本。这意味着它是对资源执行部分修改的最合适的方法

为了清楚起见,我在下面列出了一些例子

使用PUT 例如,您正在创建一个API来管理联系人。在服务器上,您有一个可以用以下JSON文档表示的资源:

{ id:1, 姓名:John Appleseed, 工作:{ 职称:工程师, 公司名称:Acme }, 电话:[ { 电话:0000000000, 类型:流动电话 } ] } 假设John已晋升为高级工程师,您希望不断更新您的联系人列表。我们可以使用PUT请求修改此资源,如下所示:

PUT/contacts/1http/1.1 主持人:example.org 内容类型:application/json { id:1, 姓名:John Appleseed, 工作:{ 职称:高级工程师, 公司名称:Acme }, 电话:[ { 电话:0000000000, 类型:流动电话 } ] } 使用PUT,即使需要修改资源的单个字段,也必须将资源的新状态的完整表示发送到服务器,这在某些情况下可能不可取

从:

PUT方法请求创建目标资源的状态,或将其替换为请求消息负载中包含的表示所定义的状态。[……]

使用补丁 然而,补丁方法定义除了提到请求有效负载应包含一组说明如何修改资源的指令,并且该组指令由定义服务器应如何应用补丁的媒体类型标识之外,没有强制要求有效负载的任何格式

从:

补丁方法请求将请求实体中描述的一组更改应用于由请求URI标识的资源。这组更改以一种称为“补丁文档”的格式表示,由媒体类型标识。[……]

下面列出了描述此类变更的一些合适格式:

JSON补丁 它表示要应用于JSON文档的操作序列。它在中定义,并由应用程序/json修补程序+json媒体类型标识

JSON补丁文档表示一个对象数组,每个对象表示应用于目标JSON文档的单个操作

JSON修补程序文档的计算从目标JSON文档开始,操作按它们在数组中出现的顺序应用。序列中的每个操作都应用于目标文档,生成的文档成为下一个操作的目标。评估将继续进行,直到成功应用所有操作或遇到错误条件

操作对象必须只有一个成员,其值指示要执行的操作:

:添加目标位置处的值;如果该值存在于给定位置,则将替换该值。 :删除目标位置处的值。 :替换目标位置处的值。 :删除指定位置的值并将其添加到目标位置。 :将指定位置的值复制到目标位置。 :测试目标位置的值是否等于 l设置为指定的值。 任何其他值都被视为错误

话虽如此,修改John职务的请求可以是:

补丁/contacts/1http/1.1 主持人:example.org 内容类型:应用程序/json修补程序+json [ {op:replace,路径:/work/title,值:高级工程师} ] JSON合并补丁 它是一种描述对目标JSON文档所做更改的格式,使用的语法与正在修改的文档非常相似。它在中定义,并由应用程序/合并修补程序+json媒体类型标识

处理JSON合并修补程序文档的服务器通过将提供的修补程序的内容与目标文档的当前内容进行比较来确定请求的确切更改集:

如果合并修补程序包含未出现在目标文档中的成员,则会添加这些成员。 如果目标确实包含该成员,则替换该值。 合并修补程序中的null值表示要删除目标文档中的现有值。 目标文档中的其他值将保持不变。 据此,修改John职务的请求可以是:

补丁/contacts/1http/1.1 主持人:example.org 内容类型:应用程序/合并修补程序+json { 工作:{ 职称:高级工程师 } } 底线 当涉及到修改资源的状态时,PUT和PATCH的使用最终取决于您的需要。选择一个、另一个或两者。但在支持这些标准时,要坚持这些标准:

如果选择支持PUT,则请求负载必须是资源的新表示形式,以便服务器将替换资源的状态

如果您选择支持补丁,请为有效负载使用标准格式,例如JSON补丁或JSON合并补丁,其中包含一组指令,告诉服务器如何修改资源的状态

有很多库可以解析JSON修补程序文档,所以不要重新发明轮子。如果您认为JSON补丁对于您的需求来说过于复杂,那么就使用JSON合并补丁。如果您可以同时使用这两种格式,那么没有什么可以阻止您支持这两种格式

而且,由于这两种格式都允许您修改JSON文档中的嵌套值,因此即使您必须允许修改嵌套值或资源,也可以使用单个端点进行修补

正在验证资源的状态 如果您关心如何在将补丁应用到您的资源后保持一致,我建议您看看这个。简而言之,建议您将表示API资源的模型与表示域的模型解耦

因此,在处理修补程序请求时:

获取要更新的域模型实例。 将域模型转换为相应的API资源模型。 将修补程序应用于API资源模型。 将带有更新的API资源模型转换回域模型。 验证域模型的状态: 如果状态有效,则接受请求并保留对域模型所做的更改。 否则,拒绝请求。 您可能还希望参阅,以了解有关何时处理修补程序请求的详细信息

如果您使用Java和Spring,请特别深入阅读 如果您使用Java和Spring,您可能希望从我的博客中看到这一点。如果您不使用Java或Spring,尽管我在回答中很好地总结了主要思想,但本文第一部分中关于使用PUT或PATCH修改资源的注意事项可能仍然会引起您的兴趣。

tl;博士 只要做得对,使用单端点支持补丁应该没问题

补丁请求有效负载应包含一组用于修改目标资源的指令。表示这组指令的合适格式是和,它们允许修改目标JSON文档中的嵌套值

对资源的状态执行修改 要对资源执行修改,可以使用PUT或PATCH,也可以同时使用两者。但是,这些方法之间的差异反映在服务器处理请求有效负载以修改目标资源的方式上:

在PUT请求中,有效负载是存储在服务器上的资源的修改版本。客户端正在请求将存储的版本替换为新版本。因此,它可能不完全适用于部分修改

在补丁请求中,请求负载包含一组指令,描述如何修改当前存储在服务器上的资源以生成新版本。这意味着它是对资源执行部分修改的最合适的方法

为了清楚起见,我在下面列出了一些例子

使用PUT 例如,您正在创建一个API来管理联系人。在服务器上,您有一个可以用以下JSON文档表示的资源:

{ id:1, 姓名:John Appleseed, 工作: { 职称:工程师, 公司名称:Acme }, 电话:[ { 电话:0000000000, 类型:流动电话 } ] } 假设John已晋升为高级工程师,您希望不断更新您的联系人列表。我们可以使用PUT请求修改此资源,如下所示:

PUT/contacts/1http/1.1 主持人:example.org 内容类型:application/json { id:1, 姓名:John Appleseed, 工作:{ 职称:高级工程师, 公司名称:Acme }, 电话:[ { 电话:0000000000, 类型:流动电话 } ] } 使用PUT,即使需要修改资源的单个字段,也必须将资源的新状态的完整表示发送到服务器,这在某些情况下可能不可取

从:

PUT方法请求创建目标资源的状态,或将其替换为请求消息负载中包含的表示所定义的状态。[……]

使用补丁 然而,补丁方法定义除了提到请求有效负载应包含一组说明如何修改资源的指令,并且该组指令由定义服务器应如何应用补丁的媒体类型标识之外,没有强制要求有效负载的任何格式

从:

补丁方法请求将请求实体中描述的一组更改应用于由请求URI标识的资源。这组更改以一种称为“补丁文档”的格式表示,由媒体类型标识。[……]

下面列出了描述此类变更的一些合适格式:

JSON补丁 它表示要应用于JSON文档的操作序列。它在中定义,并由应用程序/json修补程序+json媒体类型标识

JSON补丁文档表示一个对象数组,每个对象表示应用于目标JSON文档的单个操作

JSON修补程序文档的计算从目标JSON文档开始,操作按它们在数组中出现的顺序应用。序列中的每个操作都应用于目标文档,生成的文档成为下一个操作的目标。评估将继续进行,直到成功应用所有操作或遇到错误条件

操作对象必须只有一个成员,其值指示要执行的操作:

:添加目标位置处的值;如果该值存在于给定位置,则将替换该值。 :删除目标位置处的值。 :替换目标位置处的值。 :删除指定位置的值并将其添加到目标位置。 :将指定位置的值复制到目标位置。 :测试目标位置的值是否等于指定值。 任何其他值都被视为错误

话虽如此,修改John职务的请求可以是:

补丁/contacts/1http/1.1 主持人:example.org 内容类型:应用程序/json修补程序+json [ {op:replace,路径:/work/title,值:高级工程师} ] JSON合并补丁 它是一种描述对目标JSON文档所做更改的格式,使用的语法与正在修改的文档非常相似。它在中定义,并由应用程序/合并修补程序+json媒体类型标识

处理JSON合并修补程序文档的服务器通过将提供的修补程序的内容与目标文档的当前内容进行比较来确定请求的确切更改集:

如果合并修补程序包含未出现在目标文档中的成员,则会添加这些成员。 如果目标确实包含该成员,则替换该值。 合并修补程序中的null值表示要删除目标文档中的现有值。 目标文档中的其他值将保持不变。 据此,修改John职务的请求可以是:

补丁/contacts/1http/1.1 主持人:example.org 内容类型:应用程序/合并修补程序+json { 工作:{ 职称:高级工程师 } } 底线 当涉及到修改资源的状态时,PUT和PATCH的使用最终取决于您的需要。选择一个、另一个或两者。但在支持这些标准时,要坚持这些标准:

如果选择支持PUT,则请求负载必须是资源的新表示形式,以便服务器将替换资源的状态

如果您选择支持补丁,请为有效负载使用标准格式,例如JSON补丁或JSON合并补丁,其中包含一组指令,告诉服务器如何修改资源的状态

有很多库可以解析JSON修补程序文档,所以不要重新发明轮子。如果您认为JSON补丁对于您的需求来说过于复杂,那么就使用JSON合并补丁。如果你是舒适的w 如果同时使用这两种格式,那么没有什么可以阻止您支持这两种格式

而且,由于这两种格式都允许您修改JSON文档中的嵌套值,因此即使您必须允许修改嵌套值或资源,也可以使用单个端点进行修补

正在验证资源的状态 如果您关心如何在将补丁应用到您的资源后保持一致,我建议您看看这个。简而言之,建议您将表示API资源的模型与表示域的模型解耦

因此,在处理修补程序请求时:

获取要更新的域模型实例。 将域模型转换为相应的API资源模型。 将修补程序应用于API资源模型。 将带有更新的API资源模型转换回域模型。 验证域模型的状态: 如果状态有效,则接受请求并保留对域模型所做的更改。 否则,拒绝请求。 您可能还希望参阅,以了解有关何时处理修补程序请求的详细信息

如果您使用Java和Spring,请特别深入阅读
如果您使用Java和Spring,您可能希望从我的博客中看到这一点。如果您不使用Java或Spring,您可能仍然会对本文第一部分中关于使用PUT或PATCH修改资源的考虑感兴趣,尽管我在回答中很好地总结了主要思想。

另一种来自Google API设计指南的修补方法:非常清楚,谢谢。我发现在补丁请求中定义op很好,它符合我的需要。这很清楚,但事实上,你没有完全回答这个问题:补丁/entity/123{…}之间是哪一个。VS PATCH/entity/123/path/456{…}?Thanks@Slim检查我的答案中提供的示例。在将修补程序与JSON修补程序和JSON合并修补程序一起使用时,可以修改JSON文档中的嵌套值。因此,您应该对问题中显示的第一个URI感到满意。好的,谢谢@cassiomolin。顺便说一下,我不习惯在贴片体中设置路径。您如何看待补丁请求中的回避路径?服务器可以只包含一个知道域问题的命令列表。补丁正文中的op可能包含大量的命令名。另一种补丁方法来自googleapi设计指南:非常清楚,谢谢。我发现在补丁请求中定义op很好,它符合我的需要。这很清楚,但事实上,你没有完全回答这个问题:补丁/entity/123{…}之间是哪一个。VS PATCH/entity/123/path/456{…}?Thanks@Slim检查我的答案中提供的示例。在将修补程序与JSON修补程序和JSON合并修补程序一起使用时,可以修改JSON文档中的嵌套值。因此,您应该对问题中显示的第一个URI感到满意。好的,谢谢@cassiomolin。顺便说一下,我不习惯在贴片体中设置路径。您如何看待补丁请求中的回避路径?服务器可以只包含一个知道域问题的命令列表。补丁体中的op可能包含多种命令名