3

我有以下状态机,我想要这个:

  1. 创建新订单
  2. 向其中添加项目(列表是可选的)
  3. 通过调用完成确认订单
  4. 付钱
  5. 发送

这个流程是通过 REST Web 服务控制的,我不确定哪种方法更好地遵循 REST 原则。

在此处输入图像描述

我想出了两种可能性(下面的数字与上面的数字相对应):

第一个 - 操作由路径指定

1. 
POST /create HTTP/1.1

2. 
POST /addItem HTTP/1.1
<data>
    <itemId>123</itemId>
</data>

GET /listItems HTTP/1.1

3.
POST /finish HTTP/1.1

4. 
POST /pay HTTP/1.1
<data>
    <price>123</price>
</data>

5. 
POST /send HTTP/1.1    

第二个 - 操作在正文中指定

1. 
POST / HTTP/1.1
<data>
    <operation>create.new.order</operation>
</data>
- returns resId

2. 
PUT /{resId} HTTP/1.1
<data>
    <itemId>123</itemId>
</data>

GET /items HTTP/1.1

3.
PUT /{resId} HTTP/1.1
<data>
    <operation>finish.order</operation>
</data>

4. 
PUT /{resId} HTTP/1.1
<data>
    <price>123</price>
    <operation>pay.order</operation>
</data>

5. 
PUT /{resId} HTTP/1.1    
<data>
    <operation>send.order</operation>
</data>

第二种解决方案似乎更好,但我不知道我是否可以在请求的正文中指定一个操作 - 可以吗?

另外我不确定是否应该在第二个解决方案中使用PUTor POSTat 3and 5,因为我并没有真正更新资源,我只是更改状态机的状态。

如果这些都不正确,我该怎么做?

4

1 回答 1

3

怎么样:

发布/订单

从那里你会得到一个201 Created响应,以及一个Content-Location指定刚刚创建的订单的 URL 的标头,例如/orders/2876276

好的,然后将项目添加到现有订单:

发布 /orders/2876276

该消息可以包含 url 编码的表单数据,指定您想添加到订单中的任何内容。

然后,

获取 /orders/2876276

...获得订单的一些表示。您可以进行内容类型协商以确定是否将其格式化为 json、xml 或其他格式。响应消息将提供有关您希望与请求者共享的订单的所有信息。收到日期、状态、订单项目等。

我不知道究竟FINISH是什么,但从我天真的观点来看,这只是对订单项目的一种特殊更新,所以这只是另一个带有特殊表单数据的 POST。在完成 POST 之后,对 a 的响应GET将包含一个特殊指示符,表明订单“完成”。

要处理付款,您可以在同一订单上使用另一个 POST。如果您的设计要求跟踪应收账款,那么您可能完全有另一个对象。换句话说,如果每个订单没有一次付款,但如果客户按月或按其他节奏计费,那么您将拥有另一个对象类别,例如/accounts/39839. 但在简单的情况下,您可以只使用订单对象来跟踪付款状态。

因此,POST向一个订单 URL 提供信用卡或贝宝信息以获取付款。随后,GET 将检索包含已支付订单的表示。

我认为“发送”不是 HTTP 请求。发送是您在收到付款后执行订单的操作。也许您商店中的某些系统可以发布/orders/872872872到标记它已发送。随后,GET 将检索包含已发货订单的表示,可能还带有跟踪号。


我会小心使用PUT. PUT 表示将整个对象插入到存储库中,如果对象已经存在则隐式替换。但是您的模型不需要这样做。订单管理器管理订单,并在每个订单上公开一组有限的操作(创建、添加商品等)。插入整个订单不是这些操作之一。因此 PUT 在您的场景中似乎是错误的事情。

如果您将文档插入存储库,则 PUT 是正确的。例如,想象一场拍卖,您提供待售物品。您可以使用POST来创建拍卖项目,然后/items/29829作为该项目的 URL 接收。然后,可以使用 PUT 将图像添加到正在拍卖的物品 - 您可以 PUT/items/29829/mainImage或类似的东西。PUT 意味着你知道你要 PUT 的东西的 URL。


您问:

我不知道我是否可以在请求正文中指定一个操作 - 可以吗?

HTTP 只有一组有限的动词。您的“订单”对象有多种状态。您需要将 HTTP 动词映射到状态转换。对于每个状态转换或状态更改,对订单对象使用 POST 是有意义的。您可能认为这是在请求正文中指定“一个操作”,但对我来说,这是在请求正文中指定请求的详细信息。这正是请求正文的用途。


有关更多背景信息,请查看如何喝杯咖啡。

于 2012-04-14T19:53:35.950 回答