我坐在来自Eric Evans(Domain Driven Design的作者)的演讲中,他指出REST混淆是假设四个REST动作自动映射到四个CRUD动作。即
POST x=> Create
GET x=> Read
PUT x=> Update
DELETE x=> Delete
我有点想念他的理由。关于建筑问题的一些不同之处。
我的问题是:为什么REST操作与CRUD操作不对应?
答案 0 :(得分:9)
POST和PUT都可以用于“创建”和“更新”操作。 POST和PUT之间的区别在于幂等性: PUT是幂等的,而POST则不是。
幂等性是某些操作的属性......,可以多次应用,而不会将结果更改为初始应用程序之外的结果。 - Wikipedia
这意味着为了符合HTTP规范,您必须使用PUT进行幂等操作,并将POST用于非幂等操作。这在RFC7231 section 4.2.2中指定。
请注意,idempotence由HTTP标准描述,与REST无直接关系。
通过一个例子来理解幂等性很容易。让我们对应该创建“客户”资源的REST API进行创建操作。幂等变体看起来如下:
PUT /customers/cust42
{ "name": "John Doe" }
这将创建名为“John Doe”且ID为“cust42”的客户。这里的重要部分是客户端指定ID 。如果客户端再次发出相同的PUT请求,则不会创建新资源 - 该操作是幂等的。
另一方面,使用POST,请求将如下所示:
POST /customers
{ "name": "John Doe" }
服务器确定ID并创建名为“John Doe”的客户资源。此操作不幂等,因为再次发出相同的POST将创建第二个用户资源。
因此在POST或PUT之间进行选择不是“创建”与“更新”的问题。上面的例子都创建了一个资源,但是一个是以幂等方式(PUT),另一个不是(POST)。
在DDD中,目标是以对域(及其专家)有意义的方式创建围绕域问题的语言。因此,在CRUD之后命名所有内容通常是个坏主意。
然而,对于DDD,上述指南仍然有用。如果您的DDD应用程序上的状态更改API操作是幂等的,则使用PUT,否则使用POST。有关DELETE的一些很好的面向域的示例,请参阅Guillaume31的答案。
答案 1 :(得分:3)
为什么REST操作与CRUD操作不对应?
因为否则意味着无法通过REST接口访问具有丰富域(即非CRUD)的应用程序。
单独使用HTTP谓词不足以描述域操作。但结合URI,内容类型并位于总体域应用协议中,您可以拥有从HTTP世界到域命令领域的映射。
DELETE因此可以在不同情况下转换为不同的东西:删除,删除,存档,拒绝,取消,结束(流程/交易)等。
答案 2 :(得分:0)
REST资源映射到域实体和HTTP方法的常见误解映射到这些域实体上的操作。在某些情况下,这可能是真的,但在这些情况下(没有业务逻辑的简单CRUD)没有人会使用DDD。
只是为了澄清我们在这里讨论的是HTTP方法而不是“REST动作”。 REST使用标准来构建客户端和服务之间的统一接口,HTTP就是这样的标准之一。如果你花点时间在这里阅读HTTP方法:http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html,那么你会发现,CRUD和PGPD之间没有1:1的映射。 theDmi已经提到了幂等性,但是例如你也可以使用POST发送搜索查询,这当然不是“创建”。
如guillaume31所写,REST不是RPC。您可以将可能的操作映射到URI,HTTP方法和其他请求元数据,而不仅仅是HTTP方法。例如,您可以将beginTransaction()
操作映射到POST /transactions/
超链接,或将wishHerHappyBirthday()
操作映射到POST /greetings/ {subject: "her", occasion: "birthday"}
超链接。基于HTTP方法和URI路由更容易,更快,但这不是强制性的,如果需要,您可以使用任何HTTP标头和正文。