页面数据分页


页面数据分页

导言

在写图书管理的时候遇到了要分页的情况,一开始以为只是前端把每页的对象条数和当前页码发给后端,然后后端根据数值从数据库用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);
%>