在查询列表时我们常常会用到分页,分页的好处就是减少数据交换,每次查询一定数量减少数据库压力等等。
按实现形式分前台分页和服务器分页:
前台分页就是一次查询出所有记录,在页面中用js进行虚拟分页,这种形式在数据量较小时优势比较明显,一次加载就不必再访问服务器了,但当数据量较大时会对页面造成压力,传输速度也会大幅下降。
服务器分页就是每次请求相同数量记录,按一定规则排序,每次取一定序号直接的数据。例如,我想查询班级学生列表,这个列表按学号排序,当查看第一页时查询1-10号学生,第二页时11-21号学生以此类推。这样分页的好处就是每次查询的返回时间是固定的,但每次都需要访问服务器与数据库,这种分页常用于大数据量查询。
下面我们主要说说服务器分页。
jsp分页代码:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
<tfoot>
<tr>
<td colspan="7" align="center">
<div class="page">
<span style="padding:0; margin:0;width:290px; line-height:27px;text-align:right; float:left;">共<font color="#FF6600">${COUNT }</font>条记录</span>
<span style="padding:0; margin:0;width:290px; text-align:left;line-height:27px;float:right;padding-left:10px;">第<span id="current">${CURRENT_PAGE}</span><span id="pageSize">${PAGE_SIZE}</span>页</span>
<span style="padding:0; margin:0;line-height:27px;float:right;">到<input name="CURRENT_PAGE" type="text" size="3" id="currentPage" style="margin-left:5px;margin-right:5px;"/>页</span>
<c:choose>
<c:when test="${CURRENT_PAGE >1}">
<a href="${REQUEST_PATH}?CURRENT_PAGE=1" class="first" title="第一页"></a>
</c:when>
<c:otherwise>
<a href="javascript:;" class="first" title="第一页"></a>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${CURRENT_PAGE >1}">
<a href="${REQUEST_PATH}?CURRENT_PAGE=${CURRENT_PAGE -1}" class="pre" title="上一页"></a>
</c:when>
<c:otherwise>
<a href="javascript:;" class="pre" title="上一页"></a>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${CURRENT_PAGE < PAGE_SIZE}">
<a href="${REQUEST_PATH}?CURRENT_PAGE=${CURRENT_PAGE +1}" class="next" title="下一页"></a>
</c:when>
<c:otherwise>
<a href="javascript:;" class="next" title="下一页"></a>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${CURRENT_PAGE<PAGE_SIZE}">
<a href="${REQUEST_PATH}?CURRENT_PAGE=${PAGE_SIZE}" class="last" title="末页"></a>
</c:when>
<c:otherwise>
<a href="javascript:;" class="last" title="末页"></a>
</c:otherwise>
</c:choose>
</div>
</td>
</tr>
</tfoot>
<script type="text/javascript">
$(function(){
var curIpt = $('#currentPage'),curVal = $('#current').text(),totalVal = $('#pageSize').text(),
curPage = function(){
var curIptVal = Number($.trim(curIpt.val())),reg = /^[1-9]\d*$/;
if(!reg.test(curIptVal)){
window.location.href = path + "/queryContactInPages?CURRENT_PAGE=" + curVal ;
return false;
}
if(curIptVal > totalVal){
window.location.href = path + "/queryContactInPages?CURRENT_PAGE=" + totalVal ;
return false;
}
window.location.href = path + "/queryContactInPages?CURRENT_PAGE=" + curIptVal ;
};
curIpt.keydown(function(e){
if(e.which == 13){
curPage();
}
});
});
</script>
我们看到这个页面有上一页下一页等按钮,点击请求${REQUEST_PATH}这个地址,这个路径就是一个公共的请求路径,因为这个分页是会复用的,所以这个path可以根据不同页面设置不同的请求。请求默认只有一个参数CURRENT_PAGE(当前页码),这个当前页面传几就跳转到第几页,注意这里是从1开始的,而不是0.后面也可以增加其他参数,如查询条件等。
当请求传递到action或servlet后,对分页数据进行一定的处理:
Page page = new Page();
int currPage = 0;
// 当前页数
String currentPage = request.getParameter(Constants.CURRENT_PAGE);
// 部门代码
if (StringUtils.hasText(currentPage))
currPage = Integer.parseInt(currentPage) - 1;
List results = 查询学生列表(Page.getStartOfPage(currPage + 1), Page.DEFAULT_PAGE_SIZE);
int resultsCount = 查询学生列表总记录数();
// 设置总记录
page.setTotalCount(resultsCount);
request.setAttribute(Constants.RESULT_LIST, results);
// 分页数据项
request.setAttribute(Constants.CURRENT_PAGE, currPage + 1);
request.setAttribute(Constants.PAGE_SIZE, page.getTotalPageCount());
request.setAttribute(Constants.COUNT, page.getTotalCount());
request.setAttribute(Constants.REQUEST_PATH, request.getRequestURI());
处理流程是,先取出当前页,如果有值并且大于0,就说明不是初始查询,注意这里的当前页是从0开始的,后面会对页面传过来的值进行加减1的处理。
然后根据条件查询相应列表和总记录数并放置在request中传回页面.
下面是Page.java的代码:
public static int DEFAULT_PAGE_SIZE = 10;// 默认每页显示数
public static int MAX_PAGE_SIZE=Integer.MAX_VALUE;//最大记录数
private int pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数
private int start; // 起始记录
private int totalCount; // 总记录数
private int currentPage; // 当前页
/**
* 取总记录数.
*/
public int getTotalCount() {
return this.totalCount;
}
/**
* 取总页数.
*/
public int getTotalPageCount() {
if (totalCount % pageSize == 0) {
if (totalCount == 0)
return 1;
else
return totalCount / pageSize;
} else
return totalCount / pageSize + 1;
}
/**
* 取每页数据容量.
*/
public int getPageSize() {
return pageSize;
}
/**
* 取该页当前页码,页码从1开始.
*/
public int getCurrentPageNo() {
return start / pageSize + 1;
}
/**
* 该页是否有下一页.
*/
public boolean hasNextPage() {
return this.getCurrentPageNo() < this.getTotalPageCount() - 1;
}
/**
* 该页是否有上一页.
*/
public boolean hasPreviousPage() {
return this.getCurrentPageNo() > 1;
}
/**
* 获取任一页第一条数据在数据集的位置,每页条数使用默认值.
*
* @see #getStartOfPage(int,int)
*/
public static int getStartOfPage(int pageNo) {
return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
}
/**
* 获取任一页第一条数据在数据集的位置.
*
* @param pageNo
* 从1开始的页号
* @param pageSize
* 每页记录条数
* @return 该页第一条数据
*/
public static int getStartOfPage(int pageNo, int pageSize) {
return (pageNo - 1) * pageSize;
}
public int getNextPageNo() {
return getCurrentPageNo() + 1;
}
public int getPreviousPageNo() {
return getCurrentPageNo() - 1;
}
public boolean getHasNextPage() {
return this.getCurrentPageNo() < this.getTotalPageCount();
}
public boolean getHasPreviousPage() {
return this.getCurrentPageNo() > 1;
}
/**
* @return the start
*/
public int getStart() {
return start;
}
/**
* @param start
* the start to set
*/
public void setStart(int start) {
this.start = start;
}
/**
* @return the currentPage
*/
public int getCurrentPage() {
return currentPage;
}
/**
* @param currentPage
* the currentPage to set
*/
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
/**
* @param pageSize
* the pageSize to set
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
/**
* @param totalCount
* the totalCount to set
*/
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
里面含有计算总数和当前页码等。