REST web应用程序中的分页

REST web应用程序中的分页,rest,sorting,pagination,Rest,Sorting,Pagination,这是对的更通用的重新表述(删除了Rails特定部分) 我不知道如何在RESTful web应用程序中实现资源分页。 假设我有一个名为products的资源,您认为以下哪项是最好的方法,为什么: 1.仅使用查询字符串 例如,http://application/products?page=2&sort_by=date&sort_how=asc 这里的问题是我不能使用完整页面缓存,而且URL也不是很干净,不容易记住 2.使用页面作为资源和查询字符串进行排序 例如,http://application

这是对的更通用的重新表述(删除了Rails特定部分)

我不知道如何在RESTful web应用程序中实现资源分页。 假设我有一个名为
products
的资源,您认为以下哪项是最好的方法,为什么:

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\u by=price
可以产生完全不同的结果,我仍然不能使用页面缓存

3.使用页面作为资源和URL段进行排序 例如,
http://application/products/by-date/page/2

我个人认为使用这种方法没有问题,但有人警告我这不是一个好方法(他没有给出原因,所以如果你知道为什么不推荐,请告诉我)


欢迎提出任何建议、意见和批评。谢谢。

我认为第3版的问题更多的是一个“观点”问题——你是将页面视为资源还是页面上的产品

如果您将页面视为资源,那么这是一个非常好的解决方案,因为对第2页的查询将始终生成第2页

但是如果您将页面上的产品视为资源,那么您就有问题,第2页上的产品可能会更改(旧产品已删除,或者其他),在这种情况下,URI并不总是正确的 返回相同的资源


例如,客户存储指向产品列表第X页的链接,下次打开该链接时,相关产品可能不再位于第X页。

我目前在ASP.NET MVC应用程序中使用类似的方案:

e、 g.
http://application/products/by-date/page/2

特别是:
http://application/products/Date/Ascending/3

然而,我并不喜欢以这种方式在路由中包含分页和排序信息


项目列表(本例中为产品)是可变的。i、 下次有人返回包含分页和排序参数的url时,他们得到的结果可能已经改变。所以
http://application/products/Date/Ascending/3
作为指向已定义的、不变的产品集的唯一url将丢失。

我同意Fionn的观点,但我会更进一步地说,对我来说,页面不是资源,而是请求的属性。这使我只选择了选项1查询字符串。感觉很好。我真的很喜欢它的结构。不太简单,不太复杂,有很好的记录。无论是好是坏,当我在做某件事时,这都是我的“go-to”设计。

我以前使用过解决方案3(我写了很多django应用程序)。我不认为这有什么问题。它和其他两个一样可以生成(以防你需要做一些大规模的刮削或类似的工作),而且看起来更干净。另外,你的用户可以猜测url(如果它是面向公众的应用程序的话),人们喜欢直接去他们想去的地方,url猜测让人感觉很有力量。

我倾向于同意slf的观点,“页面”并不是真正的资源。另一方面,选项3更清晰、更容易阅读,用户更容易猜测,甚至在必要时打印出来。我在选项1和3之间左右为难,但我看不出有任何理由不使用选项3


此外,虽然它们看起来不错,但正如有人提到的,使用隐藏参数而不是查询字符串或URL段的一个缺点是用户无法将其添加到书签或直接链接到特定页面。这可能是一个问题,也可能不是,取决于应用程序,但需要注意的是。

我一直使用选项1的样式。缓存并不是一个问题,因为在我的例子中,数据总是频繁更改。如果允许对页面大小进行配置,则无法缓存数据


我不觉得url很难记住或不干净。对我来说,这是查询参数的一个很好的用法。资源显然是一个产品列表,查询参数只是告诉您希望列表如何显示-排序以及哪个页面。

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

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

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


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

HTTP具有非常适合分页的范围标头。你可以寄

Range: pages=1
只有第一页。这可能会迫使你重新思考什么是页面。也许客户想要不同种类的商品。范围标头还用于声明订单:

Range: products-by-date=2009_03_27-
获取比该日期或日期更新的所有产品

Range: products-by-date=0-2009_11_30
以使所有产品都早于该日期。”“0”可能不是最好的解决方案,但RFC似乎希望范围开始。可能部署了一些HTTP解析器,它们不会解析units=-range\u end

若标题不是一个(可接受的)选项,我认为第一个解决方案(全部在查询字符串中)是一种方法t
http://application/products?page=2&sort=+field1-field2
http://application/products?skip=20&limit=20&sort=+field1-field2
offset = offset + limit
Range: items=0-24
GET http://api.example.com/resources?offset=0&limit=25
Content-Range: items 0-24/66

Content-Range: items 40-65/*