博客管理系统项目中使用的是PageHelper的分页插件,这里回忆一下手写实现分页的方法:
1.分页Bean
public class PageBean<T> {
private int pc;// 当前页码page code
//总页数tp:由tr/ps计算可得
private int tr;// 总记录数total record
private int ps;// 每页记录数page size
private List<T> beanList;// 当前页的记录
……
}
2.分页在各层中的处理
(1)DAO
public PageBean<Customer> findAll(int pc, int ps) throws SQLException {
String sql = "select count(*) from t_customer";
int tr = ((Number)qr.query(sql, new ScalarHandler())).intValue();
sql = "select * from t_customer limit ?,?";//使用limit来限制查询记录数
List<Customer> customerList = qr.query(sql,
new BeanListHandler<Customer>(Customer.class), (pc-1)*ps, ps);
//将查询的结果放到特定的bean中
PageBean<Customer> pb = new PageBean<Customer>();
pb.setPc(pc);
pb.setPs(ps);
pb.setTr(tr);
pb.setDatas(customerList);
//返回bean
return pb;
}
(2)serlvet(controller)
public String query(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//把条件截取出来,保存到pb.url中,避免点击分页时丢失查询条件
String url = req.getQueryString();
//url中有可能存在pc,这需要把pc截取下去,另外获取
int index = url.lastIndexOf("&pc=");
if(index != -1) {
url = url.substring(0, index);
}
//获取pc
String pc = req.getParameter("pc");
if(pc != null && !pc.trim().isEmpty()) {
int pc = Integer.parseInt(pc);
}else{
int pc = 1;
}
//设置每页记录数
int ps = 10;
// 获取页面传递的查询条件
Customer c = CommonUtils.toBean(req.getParameterMap(), Customer.class);
// 使用查询条件来完成查询
PageBean<Customer> pb = customerService.query(c, pc, ps);
pb.setUrl(url);
req.setAttribute("pb", pb);
return "f:/list.jsp";
}
3.页面显示
(1)分页页码列表计算公式:
如果总页数<=10(列表长度),那么begin=1,end=总页数
使用公式计算;begin=pc-5, end=pc + 4;
头溢出:当begin<1时,让begin=1
尾溢出:当end>tp时,让end=tp
(2)list.jsp:
<p style="text-align: center;">
第${pb.pc }页/共${pb.tp }页
<a href="<c:url value='/CustomerServlet?${pb.url }&pc=1'/>">首页</a>
<c:if test="${pb.pc > 1 }">
<a href="<c:url value='/CustomerServlet?${pb.url }&pc=${pb.pc-1 }'/>">上一页</a>
</c:if>
<%------------------------------------ --%>
<%-- 页码列表的长度自己定,10个长 --%>
<c:choose>
<%-- 第一条:如果总页数<=10,那么页码列表为1 ~ tp --%>
<c:when test="${pb.tp <= 10 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="${pb.tp }"/>
</c:when>
<c:otherwise>
<%-- 第二条:按公式计算,让列表的头为当前页-4;列表的尾为当前页+5 --%>
<c:set var="begin" value="${pb.pc-4 }"/>
<c:set var="end" value="${pb.pc+5 }"/>
<%-- 第三条:第二条只适合在中间,而两端会出问题。这里处理begin出界! --%>
<%-- 如果begin<1,那么让begin=1,相应end=10 --%>
<c:if test="${begin<1 }">
<c:set var="begin" value="1"/>
<c:set var="end" value="10"/>
</c:if>
<%-- 第四条:处理end出界。如果end>tp,那么让end=tp,相应begin=tp-9 --%>
<c:if test="${end>pb.tp }">
<c:set var="begin" value="${pb.tp-9 }"/>
<c:set var="end" value="${pb.tp }"/>
</c:if>
</c:otherwise>
</c:choose>
<%-- 循环显示页码列表 --%>
<c:forEach begin="${begin }" end="${end }" var="i">
<c:choose>
<c:when test="${i eq pb.pc }">${i }</c:when>
<c:otherwise>
<a href="<c:url value='/CustomerServlet?${pb.url }&pc=${i}'/>">[${i }]</a>
</c:otherwise>
</c:choose>
</c:forEach>
<%------------------------------------ --%>
<c:if test="${pb.pc < pb.tp }">
<a href="<c:url value='/CustomerServlet?${pb.url }&pc=${pb.pc+1 }'/>">下一页</a>
</c:if>
<a href="<c:url value='/CustomerServlet?${pb.url }&pc=${pb.tp }'/>">尾页</a>
<select name="pc" onchange="_change()" id="select">
<c:forEach begin="1" end="${pb.tp }" var="i">
<option value="${i }" <c:if test="${i eq pb.pc }">selected="selected"</c:if> >${i }</option>
</c:forEach>
</select>
</p>