这篇讲 分页算法及其通过 Java 的纯后端实现。
原理
平时在使用Google搜索时,我们可以注意到页底的分页条:
它会根据 搜索结果的总数据条数
,和 每页要显示的数据条数
,自动计算 总页数
。且 当前页码
高亮。
在MySQL数据库底层进行分页查询时,使用的是limit,那必须封装一个数据表示 当前页第一条实体数据在数据库中的位置
。
当我们向后翻页时,根据 分页条的宽度
,随着当前页面的变化,分页条会有“滚动”一样的变化:
这里需要封装 分页条起始页码
和 分页条结束页码
来进行计算。
综上所述,要实现分页功能,需要以下几个数据:
- 当前页的实体数据列表:list
- 实体数据总记录数:recordCount
- 当前页页码:currentPage
- 每页实体数据个数:pageSize
- 分页条宽度:width
- 当前页在数据库表中的起始位置:offset
- 总页数:pageCount
- 分页条起始页码:begin
- 分页条结束页码:end
其中:
- list、recordCount、currentPage 是外界传递进来的,list 和 recordCount 是数据库查询出来的,而 currentPage 是用户选择而来的;
- pageSize、width 是一开始就给定默认值的;
- offset、pageCount、begin、end 需要通过计算得出。
推演
1.计算当前页在数据库表中的起始位置(offset)
数据库标示数据记录的索引是从0开始,
所以,假设每页实体数据个数是3,那么,第1页的起始位置是0,第2页的起始位置则是3,第3页的起始位置则是6,其他的如此类推下去。
当有了 当前页页码(currentpage)
和 每页实体数据个数(pageSize)
这两个值时,就可以计算这个数据变量了。
计算公式:$offset = (currentPage - 1) * pageSize$
2.计算总页数(pageCount)
当有了实体数据总记录数(recordCount)和每页实体数据个数(pageSize)这两个数值,那就可以计算总页数(pageCount)了。
计算公式:$pageCount = recordCount / pageSize + (recordCount % pageSize == 0 ? 0 : 1)$
3.计算起始页码(begin)与结束页码(end)
首先要明确的是,起始页码和结束页码的变化与 当前页页码
、总页数
、分页条宽度
这3个数据变量有关。
分页条的变化,大体分为2种情况:
实体数据不多,总页数少于等于分页条宽度。那么分页条的起始页码就是1,而结束页码就是总页数。
总页数大于分页条宽度。这种情况里面又细分了几种情况,事情就变得复杂许多了。
下面具体分析第二种情况。
先给定总页数为15,分页条宽度为 10,作图分析:
可以看出,分页条的变化分为3种情况:
- 当前页页码小于等于分页条宽度一半;
- 当前页页码大于总页数减去分页条宽度一半;
- 当前页页码大于分页条宽度一半并且小于等于总页数减去分页条宽度一半;
再给定分页条宽度为 5,则分页条宽度为奇数时,分析如下:
实现
从底层开始开发,先把数据库以及对应的表构建起来:
|
|
然后,可以根据表来创建对应的类:
|
|
接着,则要来构建并实现封装分页数据的分页类,它是整个分页功能最核心的敌方。
|
|
在Page类的构造函数里运用了之前推导的计算公式,将每个分页要用到的数据变量都计算出来。
接下来,我们只需要往数据库表里面插入一些数据,在查询出来显示到页面上即可。
操作图书数据的Dao类:
|
|
写一个测试方法,随便插入一些图书数据:
|
|
处理图书数据的服务层:
|
|
用于显示图书分页数据的jsp页面:
|
|