我对REST比较新,我从一开始就有一个问题。
我直截了当地说,我说我有一个电子商务系统,所以我有一些“产品”,我也有这个资源:我的web api中的/api/products/1234
,我发送了一个GET HTTP请求。
应该归还什么?如果它返回包括所有属性的整个实体,那么在我只需要其中一些属性而其他属性无用的情况下它是不合适的。例如,在某些情况下我只需要“标题”和“价格”,因此,我不需要其他属性,这只是一个开销。
怎么办呢?
提前致谢。
我可以考虑两种方法来处理它。
您可以使用以下(或两种)媒体类型之一来检索产品的完整表示形式:
GET /api/products/1 HTTP/1.1
Host: example.com
Accept: application/json
GET /api/products/1 HTTP/1.1
Host: example.com
Accept: application/vnd.company.full+json
以下媒体类型仅检索产品的简短表示:
GET /api/products/1 HTTP/1.1
Host: example.com
Accept: application/vnd.company.short+json
或者,您可以支持使用查询字符串参数选择要检索的字段。
使用以下内容检索产品的完整表示形式:
GET /api/products/1 HTTP/1.1
Host: example.com
Accept: application/json
以下仅检索产品的名称和价格:
GET /api/products/1?fields=name,price HTTP/1.1
Host: example.com
Accept: application/json
为方便起见,尽管列出了字段,但您始终可以返回产品的标识符。
上述方法也可以应用于资源集合,例如/api/products
。
正如埃弗特在评论中所指出的那样,“无论如何,发送所有内容确实会对性能或带宽产生影响,这可能是值得研究的。如果没有显着的成本,那么为了清晰起见,有时会更好一些更好的模型。”
再进一步引用Donald Knuth:"premature optimization is the root of all evil"。也就是说,由于您认为您将获得性能提升,因此您不应优化测量性能问题。可以执行一些明显的优化,但是在可以测量之前应该避免任何不是非常明显优化的事情。
记住/api/products/1234
识别资源而不是实体可能有所帮助。您的API可能有许多描述同一实体的不同资源。看吉姆韦伯的谈话REST: DDD In the Large。
(另请注意,存在权衡,因为每个资源都有自己的缓存条目 - 如果客户端修改一个资源,然后看到描述同一实体的另一个资源的陈旧副本,则可能会很麻烦)。
如果您使用不同的资源方法,则可以使用您喜欢的URI中的任何拼写变体。查询字符串是常见的选择,或路径段上的文件扩展名,甚至产生单独的路径段。据我所知,选择中唯一真正的区别是relative resolution(RFC 3986)在您的用例中是否有任何价值。
应该归还什么?
一个常见的选择是使用DataTransferObject模式。福勒写道
当您使用远程接口(例如Remote Facade(388))时,每次调用都很昂贵。因此,您需要减少呼叫次数,这意味着您需要在每次呼叫时传输更多数据。一种方法是使用大量参数。但是,这通常很难编程 - 实际上,Java等语言通常不会返回单个值。
解决方案是创建一个可以保存呼叫所有数据的数据传输对象。
因为REST“被设计为对大粒度超媒体数据传输有效”(Fielding),所以这种方法非常合适。