REST资源的动态表示

时间:2013-12-10 20:18:40

标签: rest

让我们假设我有一个对象,我在我的应用程序中公开为REST资源。此对象具有许多字段,并包含许多其他对象,包括关联的集合。像这样的东西,但想想更大:

Customer
  List<Order> orders
  List<Address> shippingAddresses;
  // other fields for name, etc.

Order
  List<Product> products
  // fields for total, tax, shipping, etc.

Product
  // fields for name, UPC, description, etc.

我在我的api中将客户公开为/customer/{id}

我的一些客户会希望每个订单中的每个产品都具有所有细节。如果我关注HATEOAS,我可以提供一个链接来获取产品详细信息。这将导致对服务的n + 1次调用以填充客户订单中的产品。另一方面,如果我总是填充它,那么许多客户端会收到一堆他们不需要的信息,我会进行大量不需要的数据库查找。

如何根据客户的需求允许客户代表我的资源?

我看到了一些选择。

  1. 使用Jackson的JsonView注释预先指定使用的内容。呼叫者要求提供适合他们的视图。即/customer/{id}?view=withProducts。这将要求我在编译时指定所有可用的视图,并且不会那么灵活。

  2. 允许来电者要求在请求中填写某些字段,即/customer/{id}?fields=orders,firstName,lastName。这需要我有一些处理程序可以解析f​​ields参数,并可能使用反射来填充东西。听起来对我来说太乱了。您如何处理子资源。我可以做fields=orders.products.upc并以这种方式加入收藏吗?听起来我正试图在REST之上编写hibernate。

  3. 关注HATEOAS并要求客户端进行一百万次HTTP调用以填充他们需要的内容。这对于那些不想在大多数时间内填充项目的人来说非常有用,但对于那些试图显示订单详细信息摘要或其他类似内容的人来说,这会很昂贵。

  4. 为每个视图分配资源......

  5. 其他

2 个答案:

答案 0 :(得分:1)

我会做这样的事情: 的 /客户/ {ID} /命令/?包括=实体

这是您选项1的一种更具体的变体。

您还可以选择以下选项:

  1. 没有产品清单的特定客户的特定订单: 的 /客户/ {ID} /命令/ {ID}
  2. 只是没有产品的客户的订单: 的 /客户/ {ID} /命令/
  3. 我倾向于避免使用单一资源,因为大多数时候或者最终有人总是想要一份事情清单。

答案 1 :(得分:1)

选项2(客户端指定字段)是一种过滤方法,更像是一个查询接口,而不是一个GETable资源。如果您接受服务将填充的POST请求中的部分模板,则您的过滤器可能会更具表现力。但这很复杂。

我愿意打赌你需要的是任何复杂实体的2个简单表示。这应该处理您域中99.9%的案例。鉴于此,再制作一些URI,每个URI一个&#34; view&#34;事情。

要处理0.1%的情况(例如,当您需要完全填充Products集合时),请为允许您过滤的嵌套实体提供查询接口。您甚至可以提供超媒体链接来检索这些集合,作为上述简化表示的一部分。