在REST API实际场景中使用PUT和PATCH方法的区别

1232

首先,一些定义:

PUT在RFC 2616第9.6节中有定义:

PUT方法请求将封装的实体存储在提供的Request-URI下。如果Request-URI引用已经存在的资源,则应将封装的实体视为修改后的版本,驻留在原始服务器上。如果Request-URI没有指向现有资源,并且该URI能够由请求用户代理定义为新资源,则原始服务器可以使用该URI创建资源。

PATCH在RFC 5789中有定义:

PATCH方法请求将请求实体中描述的一组更改应用于由Request-URI标识的资源。

根据RFC 2616 Section 9.1.2,PUT是幂等的,而PATCH则不是。

现在让我们看一个真实的例子。当我使用数据{username: 'skwee357', email: 'skwee357@domain.example'}进行POST到/users,并且服务器能够创建资源时,它将响应201和资源位置(假设为/users/1),任何对GET /users/1的下一次调用都将返回{id: 1, username: 'skwee357', email: 'skwee357@domain.example'}

现在假设我想修改我的电子邮件。电子邮件的修改被视为“一组更改”,因此我应该使用“patch document”对“/users/1”进行PATCH请求。在我的情况下,它将是JSON文档:{email: 'skwee357@newdomain.example'}。然后服务器返回200(假设权限正常)。这带来了我的第一个问题:
  • PATCH不是幂等的。RFC 2616和RFC 5789都这样说。但是,如果我发出相同的PATCH请求(使用我的新电子邮件),我将获得相同的资源状态(我的电子邮件被修改为所请求的值)。那么为什么PATCH不是幂等的呢?

PATCH是一个相对较新的动词(RFC于2010年3月引入),它解决了“打补丁”或修改一组字段的问题。在引入PATCH之前,每个人都使用PUT来更新资源。但是在引入PATCH之后,我对PUT的用途感到困惑。这带来了我的第二个(也是主要的)问题:

PUT和PATCH之间的真正区别是什么?我在某处读到PUT可能用于替换特定资源下的整个实体,因此应该发送完整实体(而不是像使用PATCH一样的属性集)。这种情况的真正实际用途是什么?何时希望在特定资源URI上替换/覆盖实体,为什么这样的操作不被认为是更新/修补实体?我唯一看到PUT的实际用例是在集合上发出PUT,即/users以替换整个集合。在引入PATCH后,在特定实体上发出PUT没有意义。我错了吗?

3
a) 这是RFC 2616,而不是2612。b) RFC 2616已经过时,PUT的当前规范在http://greenbytes.de/tech/webdav/rfc7231.html#PUT中。c) 我不明白你的问题; PUT可用于替换任何资源,不仅限于集合。d) 在引入PATCH之前,人们通常使用POST。e) 最后,是的,特定的PATCH请求(取决于修补程序格式)可以具有幂等性;只是一般情况下不是这样。 - Julian Reschke
39
简单来说,POST用于创建集合中的一个项目,PUT用于替换一个项目,PATCH用于修改一个项目。当使用POST时,新项目的URL将被计算并返回响应,而PUT和PATCH需要在请求中指定URL。对吗? - Tom Russell
https://datatracker.ietf.org/doc/html/rfc5789#section-2PATCH 不具备幂等性。 - Daniel
@equivalent8,很抱歉链接已失效,无法访问该篇文章。 - theking2
1
抱歉 @theking2,URL已更改,应该是https://blog.eq8.eu/article/put-vs-patch.html。 - equivalent8
显示剩余2条评论
16个回答

1563
注意: 当我第一次花时间阅读有关REST的内容时,幂等性是一个让人困惑的概念。即使在我的原始回答中,进一步的评论和Jason Hoetger的答案也表明我还没有完全理解它。一段时间以来,我一直抵制大量更新这个答案,以避免实际上剽窃Jason的内容,但现在我正在编辑它,因为,好吧,在评论中有人要求我这样做。

在阅读我的回答后,我建议您还阅读Jason Hoetger对这个问题的优秀回答,我将尝试在不简单地抄袭Jason的情况下改善我的回答。

为什么PUT方法是幂等的?

正如你在RFC 2616中引用的那样,PUT方法被认为是幂等的。当你使用PUT方法更新一个资源时,以下两个假设生效:

  1. 你所引用的是一个实体,而不是一个集合。

  2. 你提供的实体是完整的(整个实体)。

让我们看看你的其中一个例子。

{ "username": "skwee357", "email": "skwee357@domain.example" }

如果按照您的建议将此文档POST到/users,那么您可能会收到如下实体:
## /users/1

{
    "username": "skwee357",
    "email": "skwee357@domain.example"
}

如果您想稍后修改此实体,可以选择使用PUT和PATCH。PUT的示例如下:

PUT /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // new email address
}

您可以使用PATCH完成相同的操作。可能是这样的:
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

这两者之间立即就会有一个区别。PUT请求包含该用户的所有参数,但PATCH仅包含被修改的一个参数(email)。

使用PUT方法时,默认您正在发送完整的实体,并且该完整实体 替换 了该URI上的任何现有实体。在上面的示例中,PUT和PATCH都实现了相同的目标:它们都改变了该用户的电子邮件地址。但PUT通过替换整个实体来处理它,而PATCH仅更新提供的字段,不会影响其他字段。

由于PUT请求包括整个实体,因此如果您重复发出相同的请求,它应始终具有相同的结果(您发送的数据现在是实体的完整数据)。因此,PUT方法是幂等的。

错误使用PUT方法

如果您在PUT请求中使用以上的PATCH数据会发生什么?

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@domain.example"
}
PUT /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

GET /users/1
{
    "email": "skwee357@gmail.com"      // new email address... and nothing else!
}

我假设这个服务器没有任何特定的必填字段,可以允许这种情况发生...但在现实中可能并非如此。由于我们使用了PUT方法,但只提供了“电子邮件”字段,所以现在这个实体中只有这一个字段。这导致了数据丢失。
这个例子是为了说明目的而提供的--千万不要真的这样做(除非你的意图是删除被省略的字段...那么你正在正确地使用PUT)。这个PUT请求在技术上是幂等的,但这并不意味着它不是一个可怕的、破碎的想法。
PATCH如何成为幂等操作?
在上面的例子中,PATCH确实是幂等的。你进行了一次更改,但如果你一遍又一遍地进行相同的更改,它总是会返回相同的结果:你将电子邮件地址更改为新值。
GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@domain.example"
}
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address
}

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // email address was changed
}
PATCH /users/1
{
    "email": "skwee357@gmail.com"       // new email address... again
}

GET /users/1
{
    "username": "skwee357",
    "email": "skwee357@gmail.com"       // nothing changed since last GET
}

我的原始示例,修正后更准确

我最初提供的示例被认为是展示非幂等性的,但它们是误导性/不正确的。我将保留这些示例,但用它们来说明另一件事情:对同一实体进行多个 PATCH 文档,修改不同属性,不会使 PATCH 请求变得非幂等。

假设在过去某个时间添加了一个用户。这是您要开始的状态。

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.example",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001"
}

进行 PATCH 操作之后,你会得到一个被修改的实体:

PATCH /users/1
{"email": "skwee357@newdomain.example"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.example",    // the email changed, yay!
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "10001"
}

如果您反复应用您的PATCH,则会继续获得相同的结果:电子邮件已更改为新值。A进去,A出来,因此这是幂等的。
一小时后,在您去冲杯咖啡休息之后,其他人会使用自己的PATCH。看起来邮局已经做了一些更改。
PATCH /users/1
{"zip": "12345"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.example",  // still the new email you set
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "12345"                      // and this change as well
}

由于这个来自邮局的PATCH只涉及邮政编码而不是电子邮件,如果重复应用它,它也会得到相同的结果:邮政编码被设置为新值。A进去,A出来,因此这也是幂等的。

第二天,您决定再次发送您的PATCH。

PATCH /users/1
{"email": "skwee357@newdomain.example"}

{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@newdomain.example",
  "address": "123 Mockingbird Lane",
  "city": "New York",
  "state": "NY",
  "zip": "12345"
}

您的补丁与昨天产生了相同的效果:它设置了电子邮件地址。输入A,输出A,因此这也是幂等的。

我在原回答中错误的地方

我想要强调一个重要的区别(这是我在原回答中犯的错误)。许多服务器会通过发送带有您修改后的新实体状态来响应您的REST请求。因此,当您收到此响应时,它与您昨天收到的不同,因为邮政编码不是上次收到的那个。但是,您的请求并不关心邮政编码,仅关心电子邮件。因此,您的PATCH文档仍然是幂等的 - 您在PATCH中发送的电子邮件现在是实体上的电子邮件地址。

那么,PATCH 什么时候不是幂等的呢?

关于这个问题的详细解答,请再次参考Jason Hoetger的答案


3
这句话不太正确:“但它是幂等的:无论何时A进入,B总是出来”。例如,如果您在邮局更新邮政编码之前进行GET /users/1,然后再次进行相同的GET /users/1请求,您将获得两个不同的响应(不同的邮政编码)。相同的“A”(GET请求)正在进入,但您正在获取不同的结果。但GET仍然是幂等的。 - Jason Hoetger
2
@DanLowe:GET方法绝对是幂等的。在RFC 2616的第9.1.2节和更新的规范RFC 7231第4.2.2节中都明确说明了这一点,即“在本规范定义的请求方法中,PUT、DELETE和安全请求方法是幂等的。” 幂等性并不仅仅意味着“每次发出相同的请求会得到相同的响应”。7231 4.2.2还指出:“即使原始请求成功,重复请求也将产生相同的预期效果,尽管响应可能会有所不同。” - Jason Hoetger
1
@JasonHoetger 我承认这一点,但我不明白它与这个回答有什么关系。该回答讨论了PUT和PATCH,甚至没有提到GET... - Dan Lowe
1
我同意@JasonHoetger的观点 - Dan的答案确实很“好”,并且有一些不错的例子。但是,从回答问题和幂等性定义的角度来看,它完全是错误的。 - alexrussell
2
啊,@JasonHoetger的评论澄清了这一点:多个幂等方法请求的结果状态只需要相同,而不必相同。 - Tom Russell
显示剩余14条评论

565

虽然 Dan Lowe 的优秀回答非常彻底地回答了关于 PUT 和 PATCH 之间的区别,但它对于为什么 PATCH 不具备幂等性的问题的回答并不完全正确。

为了说明 PATCH 为什么不具备幂等性,有助于从幂等性的定义(来自 Wikipedia)开始:

术语“幂等”更全面地用于描述执行一次或多次都会产生相同结果的操作 [...] 幂等函数是指具有 f(f(x)) = f(x) 对于任何值 x 的性质的函数。

用更通俗易懂的语言来说,可以将幂等 PATCH 定义为:使用 patch 文档对资源进行了 PATCH 后,所有后续对该资源使用相同 patch 文档的 PATCH 调用都不会更改该资源。

相反,一个非幂等的操作是其中 f(f(x)) != f(x),对于 PATCH 可以陈述为:使用 patch 文档对资源进行了 PATCH 后,后续对该资源使用相同 patch 文档的 PATCH 调用更改该资源。

为了说明一个非幂等 PATCH,假设存在一个 /users 资源,并假设调用 GET /users 返回当前用户列表:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" }]

与其像OP的例子一样PATCH /users/{id},假设服务器允许对/users进行PATCH操作。我们来发出这个PATCH请求:

PATCH /users
[{ "op": "add", "username": "newuser", "email": "newuser@example.org" }]

我们的补丁文档指示服务器将名为newuser的新用户添加到用户列表中。第一次调用后,GET /users将返回:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
 { "id": 2, "username": "newuser", "email": "newuser@example.org" }]

现在,如果我们发送与上面完全相同的PATCH请求,会发生什么?(为了本例说明,假设/users资源允许重复的用户名。)"op"是"add",所以一个新用户被添加到列表中,接下来的GET /users返回:

[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
 { "id": 2, "username": "newuser", "email": "newuser@example.org" },
 { "id": 3, "username": "newuser", "email": "newuser@example.org" }]

/users 资源已经再次更改,尽管我们针对完全相同的端点发出了完全相同的 PATCH。如果我们的 PATCH 是 f(x),那么 f(f(x)) 不等于 f(x),因此,这个特定的 PATCH 不是幂等的

虽然 PATCH 不能保证幂等性,但 PATCH 规范中没有任何东西阻止您使您服务器上的所有 PATCH 操作都成为幂等的。RFC 5789 甚至预见到从幂等 PATCH 请求中获得的优势:

可以以幂等方式发出 PATCH 请求, 这也有助于防止在类似时间范围内的两个 PATCH 请求之间发生碰撞导致不良结果。

在 Dan 的示例中,他的 PATCH 操作实际上是幂等的。在该示例中,/users/1 实体在我们的 PATCH 请求之间发生了更改,但并不是因为我们的 PATCH 请求导致的;实际上是邮局的 不同 补丁文档导致邮政编码发生更改。邮局的不同 PATCH 是不同的操作;如果我们的 PATCH 是 f(x),那么邮局的 PATCH 就是 g(x)。幂等性规定 f(f(f(x))) = f(x),但不保证 f(g(f(x)))


45
假设服务器也允许在“/users”路径上发出PUT请求,这将使PUT请求也不具备幂等性。所有这些都取决于服务器如何处理请求的设计。 - Uzair Sajid
26
那么,我们可以仅使用PATCH操作构建API。那么,在REST原则中使用HTTP动词对资源执行CRUD操作的原则呢?难道我们在这里不是过度复杂化了PATCH的边界吗? - bohr
24
如果在集合(例如/users)上实现了PUT方法,则任何PUT请求都应该替换该集合的内容。因此,对/users的PUT请求应该期望得到一组用户并删除所有其他用户。这是幂等的。你不太可能在/users端点上执行这样的操作。但是像/users/1/emails这样的东西可能是一个集合,并且允许用新集合替换整个集合是完全有效的。 - Vectorjohn
16
我永远不会考虑对一个集合(collection)发出 PATCH 请求,只会使用 POST 和 DELETE。这样做真的有人会吗?因此,从实际角度来看,PATCH 可以被认为是幂等的吗? - Tom Russell
19
为什么要使用PATCH方法将用户添加到用户集合中?实际上你是在创建一个新的资源(新用户),这不应该使用POST请求完成吗?这让我感到困惑。 - DFSFOT
显示剩余10条评论

178

简介 - 简化版

PUT => 为现有资源设置所有新属性。

PATCH => 部分更新现有资源(不需要更新全部属性)。


4
此外:PATCH => 可能是指仅更新属性而非完整的操作指令。 - Jose V
如果gal很容易更新,为什么我们要发送现有资源的所有属性?为什么检查它很重要?而不是只更新发送的字段? - jossefaz
4
PUT 不需要存在资源。虽然通常使用 POST 创建和 PUT 更新,但RFC指出:“PUT 方法请求使用请求消息内容中所包含的表示定义的状态创建或替换目标资源的状态。”因此,你可以设计一个API,使得PUT /users/1 HTTP/1.1将创建ID为1的用户(如果不存在),并替换ID为1的用户(如果存在)。 - markusk

98

我也对此很感兴趣,并找到了一些有趣的文章。虽然我可能无法完全回答你的问题,但至少提供了一些更多的信息。

http://restful-api-design.readthedocs.org/en/latest/methods.html

HTTP RFC指定PUT必须作为请求实体采用完整的新资源表示。这意味着如果仅提供某些属性,则应将其删除(即设置为null)。

因此,PUT应该发送整个对象。例如:

/users/1
PUT {id: 1, username: 'skwee357', email: 'newemail@domain.example'}

这将有效地更新电子邮件。PUT方法不太有效的原因是您只修改了一个字段,包括用户名有点无用。下一个示例显示了差异。

/users/1
PUT {id: 1, email: 'newemail@domain.example'}

现在,如果PUT请求按照规范设计,那么PUT将会将用户名设为null,你将会得到以下反馈。

{id: 1, username: null, email: 'newemail@domain.example'}

当你使用PATCH时,你只更新你指定的字段,而像你的例子一样保持其他部分不变。

下面给出的PATCH方法与我以前见过的有点不同。

http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/

PUT和PATCH请求之间的区别反映在服务器处理封装实体以修改由Request-URI标识的资源的方式上。在PUT请求中,封装实体被认为是存储在源服务器上的资源的修改版本,并且客户端请求替换存储的版本。然而,在PATCH中,封装实体包含一组说明如何修改当前驻留在源服务器上的资源以生成新版本的指令。PATCH方法会影响由Request-URI标识的资源,它还可能对其他资源产生副作用;即应用程序可以通过PATCH创建新资源或修改现有资源。

PATCH /users/123

[
    { "op": "replace", "path": "/email", "value": "new.email@example.org" }
]

你更多地将PATCH视为更新字段的一种方式。因此,您发送操作而不是部分对象。即用值替换电子邮件。

文章以此结束。

值得注意的是,对于真正的REST API,PATCH并不是真正设计用来部分修改资源的,因为Fielding的论文未定义任何部分修改资源的方式。但是,Roy Fielding本人说PATCH是由于偏向PUT不符合RESTful的原因,[他]在最初的HTTP/1.1提案中创建了它。当然,您没有传输完整的表示,但是REST也无需表示完整。

现在,我不知道我是否特别同意文章,因为许多评论员指出,传输部分表示可以轻松描述更改。

对于我来说,我对使用PATCH有所保留。在大多数情况下,我会将PUT视为PATCH,因为到目前为止我注意到的唯一区别是PUT“应该”将缺少的值设置为null。可能这不是最“正确”的方法,但祝好运编写完美的代码。


8
值得补充的是:在William Durand的文章(以及rfc 6902)中,有一些例子中"op"是"add"。显然这不是幂等的操作。 - Johannes Brodwall
3
您可以使用 RFC 7396 合并补丁来简化操作,避免构建补丁 JSON。 - Piotr Kula
1
对于 NoSQL 表格来说,patch 和 put 之间的区别非常重要,因为 NoSQL 没有列。 - stackdave

62

简短版

  • POST:用于创建一个实体

  • PUT:用于更新/替换现有的实体,其中您必须发送实体的完整表示形式,以便将其存储

  • PATCH:用于更新实体,只需发送需要更新的字段即可


为什么更新时发送所有字段很重要? - jossefaz
@jossefaz 因为你想要替换整个资源。 - NekoOs
那么你觉得我们可以将你的答案更新为“用于更新/替换现有实体”吗? - jossefaz
感谢@jossefaz,我更新了我的回答。 - Bilal
简短明了,这正是我们想要的。这应该是被接受的答案。 - Operator
那么,PUT是PATCH的一种特殊情况,唯一的区别在于PUT包含一个完整的集合,而PATCH允许表示的子集? - theking2

33
PUT和PATCH的区别是: 1. PUT需要具备幂等性,为此您必须将整个完整的资源放入请求正文中。 2. PATCH可以是非幂等的,这意味着在某些情况下它也可以是幂等的,例如您所描述的情况。
PATCH需要一些“补丁语言”来告诉服务器如何修改资源。调用方和服务器需要定义一些“操作”,例如“添加”、“替换”、“删除”。例如:
GET /contacts/1
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "skwee357@olddomain.example",
  "state": "NY",
  "zip": "10001"
}

PATCH /contacts/1
{
 [{"operation": "add", "field": "address", "value": "123 main street"},
  {"operation": "replace", "field": "email", "value": "abc@myemail.example"},
  {"operation": "delete", "field": "zip"}]
}

GET /contacts/1
{
  "id": 1,
  "name": "Sam Kwee",
  "email": "abc@myemail.example",
  "state": "NY",
  "address": "123 main street",
}

补丁语言可以通过定义约定来使操作字段隐式化,而不是使用显式的“operation”字段,例如:

在 PATCH 请求正文中:

  1. 字段的存在意味着“替换”或“添加”该字段。
  2. 如果一个字段的值为 null,则表示删除该字段。

有了上述约定,示例中的 PATCH 可以采取以下形式:

PATCH /contacts/1
{
  "address": "123 main street",
  "email": "abc@myemail.example",
  "zip":
}

哪种看起来更简洁且用户友好。但是用户需要意识到其中的潜在约定。

通过我上面提到的操作,PATCH 仍然具有幂等性。但是,如果你定义类似于“增量”或“追加”的操作,很容易看出它不再具有幂等性。


7
在我看来,幂等性的意思是:
PUT: 我发送完整的资源定义,因此 - 结果资源状态与PUT参数完全相同。每次使用相同的PUT参数更新资源时 - 结果状态都完全相同。
PATCH: 我只发送部分资源定义,因此其他用户可能在此期间更新了此资源的其他参数。因此 - 使用相同参数及其值进行连续补丁可能会导致不同的资源状态。例如:
假设一个对象定义如下:
CAR:-颜色:黑色,-类型:轿车,-座位数:5
我用以下内容进行修补:
{color:'red'}
结果对象为:
CAR:-颜色:红色,-类型:轿车,-座位数:5
然后,一些其他用户使用以下内容对这辆车进行了补丁:
{type:'hatchback'}
因此,结果对象为:
CAR:-颜色:红色,-类型:掀背车,-座位数:5
现在,如果我再次使用以下内容对此对象进行修补:
{color:'red'}
结果对象为:
CAR:-颜色:红色,-类型:掀背车,-座位数:5
这与我之前获得的有所不同!
这就是为什么PATCH不是幂等而PUT是幂等的原因。

参见https://dev59.com/SF4b5IYBdhLWcg3w-1-c#39338329,了解为什么这种情况与幂等性无关。 - enharmonic

5

虽然您关心幂等性的问题,但我想让您考虑可扩展性。

假设您有以下元素:

{
  "username": "skwee357",
  "email": "skwee357@domain.example"
}

如果使用PUT方法进行修改,您需要提供整个对象的表示:
PUT /users/1
{
  "username": "skwee357",
  "email": "skwee357@newdomain.example"
}

现在你需要更新模式,并添加一个名为phone的字段。
PUT /users/1
{
  "username": "skwee357",
  "email": "skwee357@newdomain.example",
  "phone": "123-456-7890"
}

现在同样使用PUT方式进行更新,将会把phone设置为null。为避免这个副作用,您需每次更新架构时更新修改元素的所有组件。很麻烦。
使用PATCH,则无此问题,因为PATCH只更新给定的字段。所以,在我看来,您应该使用PATCH来修改元素(无论其是否真正幂等)。那是真实的经验回报。

4

简而言之;

POST ➔ 创建资源 (非幂等 - 多次调用相同的API可能会与已存在的资源冲突)

PUT ➔ 完全更新资源 - 所有属性都应该提供 (幂等 - 可以安全地多次调用,因为资源将被完全替换)

PATCH ➔ 部分更新现有资源 - 只需要提供所需的属性 (非幂等 - 多次调用可能会更改原始资源。例如,使用新元素更新数组将始终增加数组大小,而put将用提供的内容替换它。 PATCH的另一个缺点是它需要支持新逻辑,即如何仅更新某些字段的合同。


3
其他人已经回答了PUT与PATCH的区别。我要回答原问题标题中关于“REST API真实场景”的部分。在现实世界中,我曾经遇到过一个互联网应用程序,它具有一个RESTful服务器和一个关系型数据库,其中一个客户表是“宽”(大约有40列)。我错误地使用了PUT但假定它像SQL Update命令一样,并没有填写所有列。问题:1)某些列是可选的(因此留空是有效的答案),2)许多列很少更改,3)用户不被允许更改某些列,例如最后购买日期的时间戳,4)一个列是自由格式文本“评论”列,用户勤奋地填写了半页的客户服务评论,例如配偶姓名或通常订购的订单,5)我当时正在开发一个互联网应用程序,担心数据包大小的问题。
PUT的缺点在于它强制您发送大量信息的数据包(包括整个评论列,即使只有几个内容发生了变化),而且存在2个或更多用户同时编辑同一个客户的多用户问题(因此按照最后一次更新者胜出)。PATCH的缺点在于您必须在视图/屏幕端跟踪更改并具有一些智能来仅发送更改的部分。Patch的多用户问题仅限于同时编辑同一客户的相同列。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接