哪种方法可以创建REST Web服务?

时间:2012-04-14 19:33:08

标签: web-services http rest

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

  1. 创建新订单
  2. 将项目添加到其中(列表是可选的)
  3. 通过致电
  4. 确认订单
  5. 付钱
  6. 发送
  7. 此流程通过REST Web服务进行控制,我不确定哪种方法更符合REST原则。

    enter image description here

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

    第一个 - 操作由路径

    指定
    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>
    

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

    此外,我不确定是否应在第二个解决方案中使用PUTPOST 35,因为我并未真正更新资源,我只是改变状态机的状态。

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

1 个答案:

答案 0 :(得分:3)

怎么样:

  

POST / orders

从那里你得到一个201 Created回复,以及一个Content-Location标题,用于指定刚刚创建的订单的网址,例如/orders/2876276

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

  

POST / orders / 2876276

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

然后,

  

GET / orders / 2876276

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

我不知道FINISH究竟是什么,但从我天真的看来,它只是对订单商品的一种特殊更新,因此这只是另一个带有特殊表单数据的POST。在完成POST后,对GET的响应将包含一个特殊指示符,表明订单是“完整的”。

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

所以,POST到订单网址,提供信用卡或PayPal信息以获得付款。随后,GET将检索包含已支付订单的表示。

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


我会谨慎使用PUT。 PUT表示将整个对象插入存储库,如果该对象已存在则隐式替换。但是你的模型并没有要求它。订单管理器管理订单,并在每个订单上公开一组有限的操作(创建,添加项目等)。插入整个订单不是这些操作之一。因此,PUT在你的场景中似乎是错误的。

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


你问:

  

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

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


有关更多背景信息,请查看How to get a cup of coffee.