页面数据分页
页面数据分页
导言
在写图书管理的时候遇到了要分页的情况,一开始以为只是前端把每页的对象条数和当前页码发给后端,然后后端根据数值从数据库用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 {
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 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 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 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 books = bookDao.queryPageItemsForPrice(pageNo, pageSize,min,max);
Page 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 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
- 对总记录数和总页码显示
页码跳转
到第页
页码条的显示
- 当前页要在页码条的中间
- 页码条为奇数
// 5条
1 2 [3] 4 5
// 7
1 2 3 [4] 5 6 7
1、如果总页码数 <= 分页条长度
- 直接显示所有的分页条
1 到 总页码(末页)
[${ i }]
${ i }
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 到 分页条长度
[${ i }]
${ i }
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 到 总页数(末页)
[${ i }]
${ i }
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)
[${ i }]
${ i }
整体代码
- 在EL表达式中两个整数相除结果会自动转成小数类型
- 因为页条长度是奇数
- 所以,每次 /2 时先 -1
<%!
public static final int PAGE_NO_LENGTH = 5;
%>
<%
pageContext.setAttribute("PAGE_NO_LENGTH",PAGE_NO_LENGTH);
%>