代码之家  ›  专栏  ›  技术社区  ›  Rich Apodaca

REST:如何创建一个依赖于三个或更多不同类型资源的资源?

  •  7
  • Rich Apodaca  · 技术社区  · 15 年前

    宁静的, hypertext-driven

    • 订单:要发货的产品组。[有一批货]
    • 目的地:发货目的地。[有许多货物]
    • 发货:将产品发送给客户的行为。[属于目的地、订单和包装商]
    • 包装工:员工实际准备订单进行装运。[有许多货物]

    订单发货时,客户端需要通过在服务器上创建新发货来记录此事件。装运需要参考目的地、订单和包装商。

    为了实现新发货的创建,我可以想到三种方法,但我不喜欢其中任何一种:

    1. 使用发货介质类型发送到/发货。发货介质类型有三个字段:“order\u uri”;“packer_uri”;和“destination_uri”。每个URI分别用作发货中涉及的订单、包装商和目的地的唯一标识符。
    2. 使用发货介质类型发送到/orders/{order\u id}/packers/{packer\u id}/destinations/{destination\u id}/ships。
    3. 向系统中添加一个名为“ShipmentBuilder”的新资源。使用ShipmentBuilder媒体类型中包含的“packer\u uri”、“destination\u uri”和“order\u uri”将邮件发送到/发货构建器。

    我不喜欢选项1,因为发货介质类型额外定义了到订单、包装器和目的地的链接。这里,“链接”是一个JSON哈希,由人类可读的名称、URI和媒体类型组成。将“order\u uri”、“packer\u uri”和“destination\u uri”添加到媒体类型似乎不是很枯燥,因为它复制了相关资源的uri。

    选项2使用深度嵌套的URI,这些URI看起来不太可维护,也无法捕获任何有意义的层次信息。

    选项3在客户端和发货创建之间放置了另一个抽象级别,这使得系统更难学习。

    如果发货只依赖于一种其他资源,那么选项2会更有意义,但在这种情况下就没有了。就目前而言,我支持选项3,但更喜欢更好的。

    在本例中,创建新发货的URI和媒体类型的最佳组合是什么?还应考虑哪些其他方法?

    {
      "shipment":{
        "created_at": "Wed Sep 09 18:38:31 -0700 2009",
        "order_uri":"http://example.com/orders/815",
        "packer_uri":"http://example.com/packers/42",
        "destination_uri":"http://example.com/destinations/666"
      },
      "order":{
        "name":"the order to which this shipment belongs",
        "uri":"http://example.com/orders/815",
        "media_type":"application/vnd.com.example.store.Order+json"
      },
      "packer":{
        "name":"the person who packed this shipment",
        "uri":"http://example.com/packers/42",
        "media_type":"application/vnd.com.example.store.Packer+json"
      },
      "destination":{
        "name":"the destination of this shipment",
        "uri":"http://example.com/destinations/666",
        "media_type":"application/vnd.com.example.store.Destination+json"
      }
    }
    

    “发货”散列的内容(减去“created\u at”字段)将被过账。使用GET时,将发送上面的完整发货表示。

    3 回复  |  直到 15 年前
        1
  •  3
  •   S.Lott    15 年前

    REST“层次结构”没有 意思是 任何东西它们便于导航,以路径的形式显示关系。不是层次结构 本身 ,但这是一条路。因此,如果您放弃“层次”概念,并认识到有许多其他路径可以到达同一最终位置,那么选项2实际上是明智的。

    您的选项2是订单->封隔器->目标路径。理论上,订单->目的地->封隔器和封隔器->订单->目的地,包装商->目的地->订单和其他几个订单都在同一个地方。是的,支持他们都很痛苦。然而,这证明了它们都是等价的

    “我不喜欢选项1,因为它看起来不太干燥。”

    所以去掉重复的东西。为什么发货还必须包含完整的订单和包装信息?URI引用足以允许查找和检索订单和包装器。为什么发送订单和包装?

    “选项3使系统更难学习。”为谁?开发者?您是围绕开发人员而不是用户及其用例来设计系统的?真丢脸。

    层次结构,但路径和对象可以存在于多个可选路径的末尾。

    /shipment . 简单、清晰的URI才是最重要的。

        2
  •  1
  •   Darrel Miller    15 年前

    好的,现在我知道你在哪里看到了复制。张贴以下内容可行吗?

    {
      "shipment":{
        "created_at": "Wed Sep 09 18:38:31 -0700 2009",
        "order":{
          "uri":"http://example.com/orders/815"
          },
        "packer":{
          "uri":"http://example.com/packers/42",
        }
        "destination":{
          "uri":"http://example.com/destinations/666",
        }
      }
    }
    

    把这个还给我

    {
      "shipment":{
        "created_at": "Wed Sep 09 18:38:31 -0700 2009",
        "order":{
          "name":"the order to which this shipment belongs",
          "uri":"http://example.com/orders/815",
          "media_type":"application/vnd.com.example.store.Order+json"
        },
        "packer":{
          "name":"the person who packed this shipment",
          "uri":"http://example.com/packers/42",
          "media_type":"application/vnd.com.example.store.Packer+json"
        },
        "destination":{
          "name":"the destination of this shipment",
          "uri":"http://example.com/destinations/666",
          "media_type":"application/vnd.com.example.store.Destination+json"
        }
      }
    } 
    

        3
  •  0
  •   inf3rno    10 年前

    我认为选项1和选项2是公平的解决方案,我会忘记选项3,因为前面的选项是更好的解决方案。

    您的客户应该始终通过检查链接的语义(例如链接关系和特定于供应商的MIME类型)而不是通过检查URL结构来决定。您不一定需要特定于供应商的MIME类型,您可以使用和RDF格式,如JSON-LD和REST以及特定于应用程序的VOCAB来描述您的链接及其输入字段,您可以使用例如Hydra。您也可以使用自定义解决方案,例如将字段添加到链接。