这是这个问题的一个更通用的重新表述(消除了Rails特定的部分)

我不确定如何在RESTful web应用程序中实现资源分页。 假设我有一个叫做产品的资源,你认为以下哪一个是最好的方法,为什么:

1. 只使用查询字符串

如。http://application/products?page=2&sort_by=date&sort_how=asc 这里的问题是,我不能使用全页缓存,而且URL不是很干净,容易记住。

2. 使用页面作为资源和查询字符串进行排序

如。http://application/products/page/2?sort_by=date&sort_how=asc 在这种情况下,我们看到的问题是http://application/products/pages/1不是唯一的资源,因为使用sort_by=price可以产生完全不同的结果,我仍然不能使用页面缓存。

3.使用页面作为资源,并使用URL段进行排序

如。http://application/products/by-date/page/2 我个人认为使用这种方法没有问题,但有人警告我这不是一个好的方法(他没有给出理由,所以如果你知道为什么不推荐,请告诉我)

任何建议,意见,批评都是非常欢迎的。谢谢。


当前回答

奇怪的是,没有人指出选项3的参数是按特定顺序排列的。 http / /应用程序/产品/日期/降/名称/升/页面/ 2 而且 http / /应用程序/产品/名称/升/日期/降/页面/ 2

指向相同的资源,但有完全不同的url。

对我来说,选项1似乎是最可接受的,因为它清楚地区分了“我想要什么”和“我想要什么”(它甚至在它们之间有问号,哈哈)。全页面缓存可以使用完整的URL实现(所有选项都会遇到相同的问题)。

使用参数在URL方法的唯一好处是干净的URL。尽管你必须想出一些方法来编码参数并无损地解码它们。当然,你可以使用URLencode/decode,但这将使url再次丑陋:)

其他回答

奇怪的是,没有人指出选项3的参数是按特定顺序排列的。 http / /应用程序/产品/日期/降/名称/升/页面/ 2 而且 http / /应用程序/产品/名称/升/日期/降/页面/ 2

指向相同的资源,但有完全不同的url。

对我来说,选项1似乎是最可接受的,因为它清楚地区分了“我想要什么”和“我想要什么”(它甚至在它们之间有问号,哈哈)。全页面缓存可以使用完整的URL实现(所有选项都会遇到相同的问题)。

使用参数在URL方法的唯一好处是干净的URL。尽管你必须想出一些方法来编码参数并无损地解码它们。当然,你可以使用URLencode/decode,但这将使url再次丑陋:)

我目前正在我的ASP中使用类似于此的方案。NET MVC应用程序:

例如,http://application/products/by-date/page/2

具体来说是:http://application/products/Date/Ascending/3

但是,我并不喜欢以这种方式在路由中包括分页和排序信息。

项目列表(在本例中为产品)是可变的。也就是说,下次有人返回包含分页和排序参数的url时,他们得到的结果可能已经改变了。因此,将http://application/products/Date/Ascending/3作为指向一组确定的、不变的产品的唯一url的想法就消失了。

选项1似乎是最好的,因为您的应用程序将分页视为一种为同一资源生成不同视图的技术。

尽管如此,URL方案相对来说并不重要。如果将应用程序设计为超文本驱动的(根据定义,所有REST应用程序都必须是超文本驱动的),那么客户端将不会自行构造任何uri。相反,您的应用程序将向客户端提供链接,客户端将遵循这些链接。

客户端可以提供的一种链接是分页链接。

所有这些令人愉快的副作用是,即使您改变了对分页URI结构的想法,并在下周实现了完全不同的东西,您的客户机也可以继续工作,而无需进行任何修改。

我使用in下面的模式来获得下一页记录。 http://application/products?lastRecordKey=?&pageSize=20&sort=ASC

RecordKey是数据库中保存顺序值的表的列。这用于一次只从DB中获取一个页面数据。 pageSize用于确定获取多少条记录。Sort用于按升序或降序对记录进行排序。

HTTP有很好的范围头,也适合分页。你可以发送

Range: pages=1

只有第一页。这可能会迫使您重新考虑什么是页面。也许客户想要不同范围的产品。Range头也可以用于声明订单:

Range: products-by-date=2009_03_27-

让所有的产品更新日期或

Range: products-by-date=0-2009_11_30

让所有的产品都比这个日期更老。'0'可能不是最好的解决方案,但RFC似乎想要一些范围开始。可能部署的HTTP解析器不会解析units=-range_end。

如果标题不是一个(可接受的)选项,我认为第一个解决方案(所有在查询字符串)是一种处理页面的方式。但是,请规范化查询字符串(按字母顺序排序(键=值)对)。这就解决了?A =1&b=x" and "?B =x&a=1"的微分问题。