让我们假设我有一个对象,该对象在我的应用程序中作为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呼叫该服务,以在客户的订单内填充产品。另一方面,如果我总是填充它,那么许多客户端会收到一些他们不需要的信息,我会做大量不需要的数据库查询。
如何根据客户的需求允许我的资源的客户表示?
我看到几个选项。
使用Jackson的JsonView注释事先指定使用的内容。来电者要求适合他们的观点。即
/customer/{id}?view=withProducts
。这需要我在编译时指定所有可用的视图,并不会那么灵活。允许呼叫者请求在请求中填充某些字段,即
/customer/{id}?fields=orders,firstName,lastName
。这将需要我有一些处理程序可以解析fields参数,并可能使用反射来填充东西。听起来对我来说超级混乱。你对子资源做了什么。我能做fields=orders.products.upc
并以这种方式加入集合吗?听起来就像我试图在REST或其他东西上编写hibernate一样。按照HATEOAS,并要求客户端进行百万次HTTP调用,以填充他们需要的东西。对于那些不想在大多数情况下填充物品的人来说,这种方法非常有效,但对于试图展示订单细节总结或其他类似内容的人而言,这会很昂贵。
具有独立的资源,为每个视图...
其他?
根据我的经验,没有以下id的'/ customer'会给出这个列表,'/ customer/{id}'是你将它缩小到单个客户的方式,但这只是一种风格。这是'包含=实体'的东西,这是有趣的部分。这意味着我基本上只有2个选项,一个充分充实,另一个只包含字段。我认为这几乎不够灵活,特别是如果某些相关集合需要昂贵的操作来填充。 – digitaljoel
那么不是说你是否想包含某个实体,你可以通过说出你想包含哪个实体来解决它。/customers/{id}/orders /?products = yes&productdetails = yes和/ customers/{id}/orders/{id}只会给你一个带该id的准系统订单。 –
是啊,那基本上是我的#2。听起来像没有这个魔术弹头。 – digitaljoel