分页参数处理逻辑的最佳实践
本文讲的不是如何结合数据库实现分页功能,而是对分页参数pageNum和pageSize缺省时的处理逻辑。结合工作经验,谈谈不同方案的优缺点,并推导出最佳方案。
参数:pageNum, pageSize
pageNum 指的是拉取第几页的数据(也叫记录,下同),从1开始。
pageSize 指的是每页多少条数据。特别地,当pageSize=0时,代表拉取全部数据,此时pageNum无意义。
需求:
1. pageNum和pageSize能不传就尽量不传,方便使用。
方案A:
- pageNum缺省是1
- pageSize缺省是0
当两个参数都不传时,自然就是返回全部记录。
优点:规则简单,好理解。
缺点:遇到大表时,开发人员一不小心调用就卡死了。卡死前端,也可能连后端都卡死。
开发人员刚接触一个新API时,正常的想法是什么参数都不传,调用一下看什么反应。
所以需求改为:
1. pageNum和pageSize能不传就尽量不传,方便使用。
2. 避免不小心返回表的全部记录。
方案B:
- pageNum缺省是1
- pageSize缺省是20
当两个参数都不传时,就是返回第1页记录。
若要返回全部记录,则必须传pageSize=0。
优点:不传参数时,无论表有多少记录,再也不会出现卡死的情况了。
缺点:前端不知道某些接口是有分页的,没传分页参数,某些表(比如管理员表)一开始数据量小没发现问题,使用一段时间后,超过1页了,超过的就显示不出来。这个坑不太容易发现。而且不是一两个接口有这个问题,工作量不小。生产环境修复Bug,得小心谨慎。
不传分页参数时,应该如何处理才是最佳做法(最佳实践)是个值得三思的问题。
需求再次修改为:
1. pageNum和pageSize能不传就尽量不传,方便使用。
2. 避免不小心返回表的全部记录。
3. 避免前端不知道分页机制的存在,没传分页参数,得不到第1页以外的数据。
分析:
若pageNum和pageSize都空,则不能返回全部记录,也不能返回第1页。
既然,不能返回全部,也不能返回第1页,更不能返回第n页,那就只能报错了。
什么条件下报错,报什么错?
1. 有pageNum,有pageSize,正常执行。
2. 有pageNum,有pageSize,且pageSize=0,正常执行。
3. 无pageNum,有pageSize,且pageSize=0,正常执行。
4. 有pageNum,无pageSize,pageSize取默认值,正常执行。
5. 无pageNum,有pageSize,且pageSize不是0,报错:pageNum不能空。
7. 无pageNum,无pageSize,报错:pageNum不能空。
无pageSize,则pageSize是null不是0
方案C:
- 有pageNum时,若无pageSize,则pageSize设为20。
- 无pageNum时,若pageSize不是0,则报错,错误信息:pageNum不能空。
优点:
1. 有pageNum时,pageSize可以不传;pageSize传0时,pageNum可以不传,满足需求第1点。
2. pageNum和pageSize都不传时报错,避免了返回全部记录,满足需求第2点。
3. pageNum和pageSize都不传时报错,强迫前端pageNum和pageSize至少传一个,前端也就知道这个接口有分页功能,满足需求第3点。
方案C就是最佳实践。我孜孜不倦地追求最佳方案,以不变应万变。
By the way, 关于pageSize默认20,成了业界的不成文规定,好像谁也没有要打破的意思,对此,我有看法。没有谁规定一页的默认记录数非20不可。鉴于目前互联网和通信的发达,我个人推荐一页默认50条记录。当你遇到一个软件,每次拉取20条记录,每次拉取都要等待一两秒,而你想想拉取500条记录,操作起来想死的心都有了,你就会觉得每页20条,是多么不合理。
上面的文章发表后,收到一位好朋友的反馈:如果pageSize不控制大小,那么容易造成CC攻击。他是对的!我前面考虑的都是如何防范无意之过,而忽略了防范有意攻击。而且,我觉得我可以为防范这种攻击做点什么。
pageSize限制为多少?
限制为多少这个没有一个标准。太小会造成不便,比如某些数据有两三百行,若前端想一次装载,而后端限制pageSize比较小,则前端得分成多次请求再做拼装,太不方便了。但太大也确实不行,几千几万就越来越有攻击的味道了。思前想后,最终定在了500这个数字。500是默认值的10倍,易记。一次请求500行也不至于造成攻击。仅供参考。做法也简单,如果前端传来的pageSize大于500,就直接修改为500,返回的结果中是带有pageSize的,不至于被前端不知道实际执行的pageSize是多少。
要不要禁止pageSize=0?
既然pageSize最大值是500了,还要不要支持pageSize=0?它的意义何在?假设不支持0,而前端想要每页的数据“尽可能多”,应该是传500。后来某一天后端把最大值调整为600了,前端得把500也改为600。你可能会说,不用,一开始前端就传800,甚至最大的数,比如2000,反正是一个足够大的数。这不,0就是代表这个足够大的数。是的,所以得支持0。
方案D:
- 有pageNum时,若无pageSize,则pageSize设为50。
- 无pageNum时,若pageSize不是0,则报错,错误信息:pageNum不能空。
- 有pageSize时,若pageSize大于500,则修改为500。
- 若pageSize=0,则修改为500。
嗯。方案D成为最佳实践。
博主简介:佘焕敏(shé),洋名 Billy Sir。
关注编程基础技术,并致力于研究软件的自动化生成。 对编程规范化、面向对象的极致使用也有着浓厚的兴趣。 同时非常希望能够写程序到65岁。
只有工匠精神,才能把常人觉得单调乏味的代码,当作作品雕刻成艺术品。
重点:这里几乎每一篇文章,都是我认真创作的,凝结了心血。写作从来都不是一件容易的事,对从小语文不好的我而言,是难上加难。而且,你发现没有,文中没有广告。这篇文章介绍了为什么要写这些文章。
![微信赞赏码](https://img2022.cnblogs.com/blog/33556/202211/33556-20221101085333455-1717538163.png)