当前位置:  开发笔记 > 前端 > 正文

REST Web应用程序中的分页

如何解决《RESTWeb应用程序中的分页》经验,为你挑选了7个好方法。

这是对这个问题的更通用的重构(消除了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_by=price可以产生完全不同的结果,我仍然不能使用页面缓存.

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

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

任何建议,意见和批评都非常受欢迎.谢谢.



1> slf..:

我同意Fionn,但我会更进一步说,对我而言,Page 不是资源,它是请求的属性.这使我只选择了选项1查询字符串.感觉很对.我真的很喜欢Twitter API的结构.不是太简单,也不是太复杂,记录良好.无论好坏,这都是我的"走向"设计,当我在做某种方式而不是另一种方式时.


+1:查询字符串不是第一类资源标识符; 他们只是澄清资源的排序和分组.

2> Fionn..:

我认为版本3的问题更多是"观点"问题 - 您是否将页面视为资源或页面上的产品.

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

但是,如果您看到页面上的产品作为资源,则您遇到第2页上的产品可能会更改的问题(旧产品已删除或其他),在这种情况下,URI并不总是返回相同的资源.

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


您的答案顺利地转到"正确的解决方案是1",但没有说出来.
好吧,但是如果你删除了某些东西,那么同一个URI上应该没有别的东西.如果删除页面X的所有产品 - 页面X可能仍然有效,但现在包含第X + 1页的产品.因此,如果您在"产品资源视图"中看到页面X的URI已成为页面X + 1的URI ".
将页面视为资源可能应该引入POST/foo/page来创建新页面,对吧?
在我看来,页面是一个浮动概念,与底层域无关.因此不应被视为资源.我的意思是浮动,因为它是流动的,页面的概念随着上下文而变化; 您的API的一个用户可能是一个移动应用程序,每页只能消耗2个产品,而另一个是可以使用整个该死的列表的机器应用程序.简而言之,页面是底层域实体(产品)的"表示",不应作为URL的一部分包含在内; 仅作为查询参数.

3> temoto..:

HTTP具有很好的Range标头,也适用于分页.你可以发送

Range: pages=1

只有第一页.这可能会迫使你重新思考什么是页面.也许客户想要一系列不同的商品.Range标头也可用于声明订单:

Range: products-by-date=2009_03_27-

获得比该日期更新的所有产品或

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

获得比该日期更早的所有产品.'0'可能不是最佳解决方案,但RFC似乎想要一些范围启动.部署的HTTP解析器可能无法解析单位= -range_end.

如果header不是(可接受的)选项,我认为第一个解决方案(查询字符串中的所有内容)是一种处理页面的方法.但请,请按字母顺序规范化查询字符串(sort(key = value)对).这解决了"?a = 1&b = x"和"?b = x&a = 1"的区分问题.


标题看起来可能看起来不错,但它们不允许共享页面(例如通过复制URL).所以对于ajax请求,它们可能是一个很好的解决方案(因为ajax修改的页面无论如何都不能在当前状态下共享),但我不会将它们用于常规分页.
@ChrisWestin http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.12 HTTP/1.1使用范围(第14.35节)和内容范围(第14.16节)标题字段中的范围单位.`range-unit = bytes-unit | other-range-unit`也许你指的是`HTTP/1.1定义的唯一范围单位是"bytes".HTTP/1.1实现可以忽略使用其他单元指定的范围.这与您的语句不同.
Range标头仅用于字节范围.请参阅[HTTP标头规范](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html),第14.35节.

4> Rich Apodaca..:

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

话虽如此,URL方案相对无关紧要.如果您将应用程序设计为超文本驱动(因为所有REST应用程序必须按照定义),那么您的客户端将不会自己构建任何URI.相反,您的应用程序将提供指向客户端的链接,客户端将遵循它们.

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

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


很好的提醒在REST Web服务中使用超媒体链接.

5> 小智..:

我总是使用选项1的样式.缓存并不是一个问题,因为在我的情况下数据经常变化.如果允许页面大小可配置,则无法再次缓存数据.

我没有发现网址难以记住或不清洁.对我来说,这是一个很好的查询参数使用.资源显然是一个产品列表,查询参数只是告诉你如何显示列表 - 排序和哪个页面.



6> 小智..:

奇怪的是,没有人指出选项3具有特定顺序的参数. http // application/products/Date/Descending/Name/Ascending/page/2http // application/products/Name/Ascending/Date/Descending/page/2

指向相同的资源,但具有完全不同的URL.

对我来说,选项1似乎是最可接受的,因为它清楚地区分了"我想要什么""我多么想要"它(它们之间甚至有问号大声笑).可以使用完整URL实现整页缓存(无论如何,所有选项都会遇到同样的问题).

使用Parameters-in-URL方法,唯一的好处是干净的URL.虽然你必须想出一些方法来编码参数并无损地解码它们.当然你可以使用URLencode/decode,但它会让网址再次丑陋:)



7> Sorter..:

我更喜欢使用查询参数offset和limit.

offset:表示集合中项目的索引.

限制:项目数.

客户端可以简单地按如下方式更新偏移量

offset = offset + limit

为下一页.

该路径被视为资源标识符.页面不是资源,而是资源集合的子集.由于分页通常是GET请求,因此查询参数最适合分页而不是标题.

我用metamug.他们有这个可配置的. 选择查询metamug上的分页

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有