【问题标题】:RESTful Service Design: Calling get all resource endpointRESTful 服务设计:调用获取所有资源端点
【发布时间】:2015-04-25 09:01:39
【问题描述】:

寻找一些建议来帮助我设计一个宁静的服务。

  1. 获取所有产品:当客户尝试获取所有产品/products 时会发生什么。我应该退回所有产品还是前 50 个?
  2. 如果服务会返回前50或前100,那么我应该在哪里写分页逻辑?我应该用同样的getAllProducts()方法写吗?
  3. 我计划同时拥有sortsearch 功能。这两个人会去哪里?

这是我的假设:

@RequestMapping("/products")
public String getAllProducts(@QueryParam(value="page") int page, @QueryParam(value="sort") String orderBy) {

@RequestMapping("/search/products")
public String findProducts(@QueryParam(value="q") String searchCriteria) {

【问题讨论】:

  • 投票关闭,因为它是基于 imo 的意见;无论如何/search/ 是一个动词,不适合真正宁静的服务。
  • @ᴳᵁᴵᴰᴼ 了解您的担忧。你有更清洁的方法来解决这个问题吗?
  • 投票结束,因为它完全基于意见。也就是说,我的意见是更聪明地工作,而不是更努力地工作。您是否考虑过以 json 格式返回所有产品并使用像 DataTables 这样的 jQuery 工具来处理分页、排序、搜索等。您将在后端节省大量不必要的编码(重复工作)和可以快速启动并运行。除非你有成千上万的产品,否则我会让插件为你处理它。

标签: java spring rest restful-architecture


【解决方案1】:

正如您所建议的,常规做法是使用参数。
根据您的要求,您可以使用其中一种:

  1. ?page=$pagenumber(页面大小由您定义)
  2. ?page=$pagenumber?per_page=$pagesize(页面大小由客户端定义)(这是 GitHub 的做法)
  3. ?start=$idOfFirstElement?per_page=$idOfLastElement(没有“人工”页面,更靠近数据库)

当然,您可以(或应该)限制变体 2 和 3 的输入,如果结果很大,请返回 #4XX 响应代码。


  1. 获取所有产品:当客户尝试获取所有产品/products 时会发生什么。我应该退回所有产品还是前 50 个?

常规和预期的 RESTful 行为是获取所有产品,而在实际环境中通常这是不可能的。 (想想拥有 10k 种产品的“小型”网店)。
基本上你有两种设计选择:

  1. 没有分页信息的 HTTP 请求是错误的。回复#4XX
  2. 没有分页信息的 HTTP 请求使用默认值。 (例如首页和每页 50 个产品)

我建议使用第一个,因为它看起来更干净,不会让客户感到困惑。


  1. 我计划同时拥有sortsearch 功能。这两个人会去哪里?

与页面参数相同。只需将它们添加到 URI。
例如?sortBy="price"?sort="ASC"?sort="DESC"?searchFor="lalalala"


  1. 如果服务会返回前50或前100,那么我应该在哪里写分页逻辑?我应该用同样的getAllProducts() 方法写吗?

遗憾的是,我们无法用您给定的少量代码对此发表评论。 ...而且 SO 不适合 Code Review

【讨论】:

    【解决方案2】:

    我的建议是保持查询字符串的语义简单,API 的使用者可以很容易理解的词,对于分页,这些查询参数可以是 offsetlimit,这样客户端控制它将被检索的内容,例如:

    我可能只对偏移量为 100 的前 2 个元素感兴趣,这比每次都检索固定数量的效果要好。请记住,虽然客户端可以设置限制,但您应该在服务器端设置一个最大限制值,以免最终检索所有对象并降低应用程序的速度。

    使用偏移量和限制分页的 URL 表示形式是:

    GET /products?offset=10,limit=50

    关于搜索,您还想使用该方法,您必须定义资源的哪些属性是可查询的和排序等。此外,您可能需要定义一个从所有可查询属性中查询的参数(例如q)所以对您的收藏的请求如下所示:

    GET /products?offset=10,limit=50,name=*rest*&description=*rest*

    GET /products?offset=10,limit=50,q=rest

    我还建议您查看有关 Designing REST + JSON APIs 的视频(完全披露我在 Stormpath 工作,但我确实认为它是一种宝贵的资源),Les 谈到了 1:00:00 左右的分页,以防你想快进。

    希望对你有帮助,

    何塞·路易斯

    【讨论】:

    • 我更喜欢skip=x和take=y,而不是offset=x和limit=y。这是Linq使用的术语,我觉得更直观。
    猜你喜欢
    • 2013-05-28
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多