页面数据分页
页面数据分页
导言
前端把每页的对象条数和当前页码发给后端,然后后端根据数值从数据库用SQL语句查询出来。
select * from t_table limit (pageNo - 1) * pageSize pageSize
涉及到要用三层架构的问题,所以web层并不能直接和dao交互所以在交互的过程中还要建立page分页对象
效果大致是这样
首页 上一页 1 [2] 3 4 5 下一页 末页 共9页,18条记录 到第[input]页[确定]
下面是整体思路
后端整体思路
一、建立page分页对象(bean层)
在分页对象中有五个属性,分别是
- 当前页码
- 每页的数据条数
- 总页码
- 总记录数(数据总条数)
- 当前页的对象(考虑到代码复用的关系,用泛型)
public class Page<T> {
public static final Integer PAGE_SIZE = 4;
private Integer pageNo;//当前页码
private Integer pageTotal;//总页码 pageTotalCount / pageSize (+1)
private Integer pageTotalCount;//总记录条数 select count(*) from table
private Integer pageSize = PAGE_SIZE;//每页条数
private List<T> items;//当前页的项
/**
getter
setter
constructor
toString
*/
}
- 当前页码和每页的数据条数的确定的
- 总记录数从数据库中查询
- 总页数为
- 总记录数 / 每页条数
- 如果有余数 总页数+1
- 每页 数据对象从数据库中查询,封闭成一个List集合
二、DAO层
- 查询总记录数
- 查询当前页的数据对象List集合
@Override
public Integer queryPageTotalCount() {
String sql = "select count(*) from book;";
Number number = (Number)queryForOneValue(sql);
return number.intValue();
}
@Override
public List<Book> queryPageItems(Integer pageNo, Integer pageSize) {
String sql = "select * from book limit ?,?";
Integer begin = (pageNo - 1) * pageSize;
Integer length = pageSize;
List list = queryForList(Book.class,sql, begin, length);
return list;
}
三、service层
- 调用DAO层得到总记录数、当前页的数据对象List集合
- 确定的当前的页码、每页的数据条数
- 计算出总页数
- 封闭成一个page分页bean对象
private BookDao bookDao = new BookDaoImpl();
@Override
public Page<Book> pageQueryForPrice(Integer pageNo, Integer pageSize, Integer min, Integer max) {
// 求出总记录条数
Integer pageTotalCount = bookDao.queryPageTotalCountForPrice(min,max);
// 求出总页码
Integer pageTotal = pageTotalCount / pageSize;
if(pageTotalCount % pageSize > 0) {
pageTotal++;
}
// 数据边界
if(pageNo < 1) {
pageNo = 1;
} else if(pageNo > pageTotal) {
pageNo = pageTotal;
}
List<Book> books = bookDao.queryPageItemsForPrice(pageNo, pageSize,min,max);
Page<Book> bookPage = new Page<>(pageNo,pageTotal,pageTotalCount,pageSize,books);
return bookPage;
}
四、web层
- 主要从前端接收请求
- 调用service层得到page对象
- 把当前的分页对象集合数据发给前端
- 前端做显示
private BookService bookService = new BookServiceImpl();
/**
* 分页显示图书
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String page = req.getParameter("page");
Integer pageNo = Integer.valueOf(page);
Integer pageSize = 4;
Page<Book> pageBooks = bookService.page(pageNo, pageSize);
req.setAttribute("page",pageBooks);
req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
}
前端
首页、上一页、下一页、末页
- 首页就是1
- 末页就是总页码数
- 下一页是当前页+1
- 上一页是当前页-1
- 为防止用户调皮,要对每个项做隐性处理
- 如果当前页为第一页,首页和上一页不能用
- 如果当前页是最后一页,末页和下一页不能用
- 加上不能选中复制的样式,提升体验
style="user-select: none
- 对总记录数和总页码显示
<div id="page_nav" style="user-select: none">
<c:if test="${ requestScope.page.pageNo > 1}">
<a href="bookServlet?action=page&page=1">首页</a>
<a href="bookServlet?action=page&page=${ requestScope.page.pageNo - 1 }">上一页</a>
</c:if>
<c:if test="${ requestScope.page.pageNo <= 1}">
首页
上一页
</c:if>
<%--分页条位置--%>
<c:if test="${ requestScope.page.pageNo < requestScope.page.pageTotal }">
<a href="bookServlet?action=page&page=${ requestScope.page.pageNo + 1}">下一页</a>
<a href="bookServlet?action=page&page=${ requestScope.page.pageTotal }">末页</a>
</c:if>
<c:if test="${ requestScope.page.pageNo >= requestScope.page.pageTotal}">
下一页
末页
</c:if>
共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
到第<input value="" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">
</div>
页码跳转
<script type="text/javascript">
window.onload = function () {
document.getElementById("searchPageBtn").onclick = function () {
var pageNo = document.getElementById("pn_input").value;
window.location.href = "bookServlet?action=page&page=" + pageNo;
}
}
</script>
到第<input value="" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">
页码条的显示
- 当前页要在页码条的中间
- 页码条为奇数
// 5条
1 2 [3] 4 5
// 7
1 2 3 [4] 5 6 7
1、如果总页码数 <= 分页条长度
- 直接显示所有的分页条
1 到 总页码(末页)
<c:when test="${ requestScope.page.pageTotal <= pageScope.PAGE_NO_LENGTH }">
<c:forEach begin="1" end="${ requestScope.page.pageTotal }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:when>
2、如果总页码数 > 分页条长度
2.1、如果当前页<=前几页分页条中间数
- 比如说分页条为
1 2 3 4 5
、中间是3 - 当前页为1、2、3
[1] 2 3 4 5
1 [2] 3 4 5
1 2 [3] 4 5
- 分页条的中间公式
分页条长度 / 2 + 1
- 比如
5 / 2 + 1 == 3
- 显示
1 到 分页条长度
<c:when test="${ requestScope.page.pageNo <= (pageScope.PAGE_NO_LENGTH / 2 + 1) }">
<c:forEach begin="1" end="${ pageScope.PAGE_NO_LENGTH }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:when>
2.2、如果当前页 >= 最后几页中间数
- 比如总共10页、分页条长度是5
- 最后为
6 7 [8] 9 10
、中间是8 6 7 [8] 9 10
6 7 8 [9] 10
6 7 8 9 [10]
- 最后几页中间数公式
总页码数 - (分页条长度 / 2)
10 - (5 / 2) = 8
- 显示
总页数 - 分页条长度 + 1 到 总页数(末页)
<c:when test="${ requestScope.page.pageNo >= requestScope.page.pageTotal - (pageScope.PAGE_NO_LENGTH / 2) }">
<c:forEach begin="${ requestScope.page.pageTotal - (pageScope.PAGE_NO_LENGTH - 1) }" end="${ requestScope.page.pageTotal }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:when>
2.3、其它情况
- 不满足上面两个的任一情况
- 比如总共10页、分页条长度是5
2 3 [4] 5 6
3 4 [5] 6 7
4 5 [6] 7 8
5 6 [7] 8 9
- 显示
当前页 - (分页条长度 / 2) 到 当前页 + (分页条长度 / 2)
<c:otherwise>
<c:forEach begin="${ requestScope.page.pageNo - (pageScope.PAGE_NO_LENGTH / 2) }" end="${ requestScope.page.pageNo + (pageScope.PAGE_NO_LENGTH / 2) }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:otherwise>
整体代码
- 在EL表达式中两个整数相除结果会自动转成小数类型
- 因为页条长度是奇数
- 所以,每次 /2 时先 -1
<%!
public static final int PAGE_NO_LENGTH = 5;
%>
<%
pageContext.setAttribute("PAGE_NO_LENGTH",PAGE_NO_LENGTH);
%>
<div id="page_nav" style="user-select: none">
<c:if test="${ requestScope.page.pageNo > 1}">
<a href="bookServlet?action=page&page=1">首页</a>
<a href="bookServlet?action=page&page=${ requestScope.page.pageNo - 1 }">上一页</a>
</c:if>
<c:if test="${ requestScope.page.pageNo <= 1}">
首页
上一页
</c:if>
<%-- 分页条--%>
<c:choose>
<%-- 如果总页码小于5 1,2,3,4,5 1,2,3,4 --%>
<c:when test="${ requestScope.page.pageTotal <= pageScope.PAGE_NO_LENGTH }">
<c:forEach begin="1" end="${ requestScope.page.pageTotal }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:when>
<c:when test="${ requestScope.page.pageTotal > pageScope.PAGE_NO_LENGTH }"><%-- 页码大于5 --%>
<c:choose>
<%-- pageno<=3 1,2,[3],4,5 --%>
<c:when test="${ requestScope.page.pageNo <= ((pageScope.PAGE_NO_LENGTH - 1) / 2 + 1) }">
<c:forEach begin="1" end="${ pageScope.PAGE_NO_LENGTH }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:when>
<%-- pageno>pagetotal - 3 6,7,[8],9,10 --%>
<c:when test="${ requestScope.page.pageNo >= requestScope.page.pageTotal - ((pageScope.PAGE_NO_LENGTH - 1) / 2) }">
<c:forEach begin="${ requestScope.page.pageTotal - (pageScope.PAGE_NO_LENGTH - 1) }" end="${ requestScope.page.pageTotal }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:when>
<%-- 否则 2,3,[4],5,6 --%>
<c:otherwise>
<c:forEach begin="${ requestScope.page.pageNo - ((pageScope.PAGE_NO_LENGTH - 1) / 2) }" end="${ requestScope.page.pageNo + ((pageScope.PAGE_NO_LENGTH - 1) / 2) }" var="i">
<c:if test="${ i == requestScope.page.pageNo }">
[${ i }]
</c:if>
<c:if test="${ i != requestScope.page.pageNo }">
<a href="bookServlet?action=page&page=${ i }">${ i }</a>
</c:if>
</c:forEach>
</c:otherwise>
</c:choose>
</c:when>
</c:choose>
<c:if test="${ requestScope.page.pageNo < requestScope.page.pageTotal }">
<a href="bookServlet?action=page&page=${ requestScope.page.pageNo + 1}">下一页</a>
<a href="bookServlet?action=page&page=${ requestScope.page.pageTotal }">末页</a>
</c:if>
<c:if test="${ requestScope.page.pageNo >= requestScope.page.pageTotal}">
下一页
末页
</c:if>
共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
到第<input value="" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">
</div>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!