分页的实现方式虽有多种,但是当需分页展示大量数据的时候,将分页写在后台才是最好的选择。首先我定义了一个Pagination类,代码如下:
package com.raze.common.pagination;
import java.io.Serializable;
import java.util.List;
/**
* @author DJM
*/
public class Pagination<T> implements Serializable {
private static final long serialVersionUID = -4817814886123631684L;
/*Fields,start*/
/*记录的总条数,受数据库中的记录影响,需通过SQL查询获取*/
private Integer totalRecord;
/*记录的总页数,受参数totalRecord与pageSize影响,可通过计算获取*/
private Integer totalPages;
/*每页显示记录的条数,需自主设置*/
private Integer pageSize;
/*当前页码值,可影响参数beginLine的值,需通过参数传递获取*/
private Integer currentPage;
/*limit参数,记录起始的index,受参数currentPage与pageSize影响,通过计算获取*/
private Integer beginLine;
/*分页处理之后,得到的结果集*/
private List<T> summaryList;
/*Fields,end*/
/*Methods of getter and setter,start*/
public Integer getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(Integer totalRecord) {
this.totalRecord = totalRecord;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public Integer getBeginLine() {
return beginLine;
}
public void setBeginLine(Integer beginLine) {
this.beginLine = beginLine;
}
public List<T> getSummaryList() {
return summaryList;
}
public void setSummaryList(List<T> summaryList) {
this.summaryList = summaryList;
}
public Integer getTotalPages() {
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
/*Methods of getter and setter,end*/
/**
* Constructor.
* @param totalRecord the number of pages (required)
* @param pageSize numbers of display records(unnecessary,default 15)
* @param currentPage the current page
*/
public Pagination(Integer totalRecord, Integer pageSize, Integer currentPage) {
this.totalRecord = totalRecord==null? 0: totalRecord;
this.pageSize = (pageSize==null||pageSize<=0)? IPageable.DEFAULT_SHOW_LINE: pageSize;
this.totalPages = (this.totalRecord%this.pageSize==0||this.totalRecord==0)? this.totalRecord/this.pageSize: this.totalRecord/this.pageSize+1;
this.currentPage = currentPage==null? 1: currentPage;
this.beginLine = (this.currentPage-1)*this.pageSize;
}
/*Constructor,end*/
/*Method of toString,start*/
@Override
public String toString() {
return "Pagination [totalRecord=" + totalRecord + ", totalPages="
+ totalPages + ", pageSize=" + pageSize + ", currentPage="
+ currentPage + ", beginLine=" + beginLine + ", summaryList="
+ summaryList + "]";
}
/*Method of toString,end*/
}
为了符合设计模式的开闭原则,定义了一个接口IPageable,为Pagination提供每页默认显示记录的条数的设定。具体代码如下:
package com.raze.common.pagination;
/**
* @author DJM
*/
public interface IPageable {
/*每页默认显示记录的条数*/
public static final Integer DEFAULT_SHOW_LINE = 15;
}
一般的分页,先查询记录总数,再取出页面所需显示的相关记录。而类Pagination中的参数totalRecord表示的就是记录总数,程序使用的是MyBatis框架,映射文件中对应的语句是:
<select id="countCustomer" resultType="int">
<![CDATA[
SELECT count(*) FROM tbl_customer_info
]]>
<trim prefix="WHERE" prefixOverrides="AND">
<if test="id!=null and id!=''">
id=#{id} AND
</if>
<if test="customerName!=null and customerName!=''">
customer_name=#{customerName} AND
</if>
<if test="identityCardNumber!=null and identityCardNumber!=''">
identity_card_number=#{identityCardNumber} AND
</if>
<if test="customerPassword!=null and customerPassword!=''">
customer_password=#{customerPassword}
</if>
</trim>
</select>
类Pagination中的参数pageSize表示的是每页显示记录的条数,可以赋为null,此时,程序会默认赋值15,当然也可以自主设定,若有设定,页面将按设定值来显示记录条数。
新建映射文件pagination.xml,并加入到MyBatis配置文件中
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<mappers>
<mapper resource="mybatis/mappers/AccountInformationMapper.xml"/>
<mapper resource="mybatis/mappers/TblVipInfo.ibt.xml"/>
<mapper resource="com/raze/common/pagination/xml/pagination.xml"/>
</mappers>
</configuration>
,映射文件pagination.xml将经常被需分页的模块的映射文件中被应用,通过往SQL语句中加入limit语句来得到页面所需展示的数据,具体的pagination.xml的配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="PaginationNamespace" >
<sql id="pagination_limit">
<if test="pagination != null">
limit #{pagination.beginLine},#{pagination.pageSize}
</if>
</sql>
</mapper>
前端页面采用jQuery pagination plugin (bootstrap powered)来做前端分页,访问网址为:jQuery Pagination plugin(Optimized for bootstrap),下面是有关该插件的options and events的截图:
我的JSP页面的代码分享如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="<%=basePath%>">
<title>分页显示</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="HTML5,DJM,Bootstrap">
<meta http-equiv="description" content="DJM Page">
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="css/my-defined/my-defined.css">
<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type="text/javascript" src="FrontFramework/My97DatePicker/WdatePicker.js"></script>
<script type="text/javascript" src="FrontFramework/jquery/plugins/jquery.twbsPagination.js"></script>
</head>
<body>
<div>
<!--路径导航栏-->
<div>
<div>
<ol style="background-color:#F2DEDE;">
<li><a href="index.do">首页</a></li>
<li><a href="left.do?">可视化报表</a></li>
<li>每日订单分析报表(分页显示)</li>
</ol>
</div>
</div>
<!--检索条件栏-->
<div>
<div>
<div class="panel panel-danger">
<div>
<span class="glyphicon glyphicon-search" aria-hidden="true"></span> 检索条件
</div>
<div>
<form role="form" action="">
<div>
<label for="exampleInputAmount">确认状态</label>
<div>
<div>
<strong id="blueFont" title="确认状态">确认状态</strong>
</div>
<input type="text" id="exampleInputAmount" placeholder="确认状态">
</div>
</div>
<div>
<!--查询条件-开始时间-->
<div class="input-group ">
<div>
<strong id="blueFont" title="结束时间">开始时间</strong>
</div>
<label for="queryTimeStart">queryTimeStart</label>
<input type="text" id="queryTimeStart" name="queryTimeStart" placeholder="结束时间" onClick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss'})">
<div>
<strong id="blueFont" title="至">至</strong>
</div>
<label for="queryTimeStart">queryTimeEnd</label>
<input type="text" id="queryTimeEnd" name="queryTimeEnd" placeholder="结束时间" onClick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss'})">
</div>
</div>
<button type="submit" class="btn btn-danger">
<span class="glyphicon glyphicon-check" aria-hidden="true"></span> 查询
</button>
</form>
</div>
</div>
</div>
</div>
<!--查询结果-->
<div>
<div>
<div class="panel panel-danger">
<div>
<h3>查询结果<small>(数据库中有${numberOfRecord}条记录)</small></h3>
</div>
<div>
<!--表格-->
<table class="table table-bordered table-hover">
<thead>
<tr>
<th title="编号">编号</th>
<th title="用户姓名">用户姓名</th>
<th title="身份证编号">身份证编号</th>
<th title="用户密码">用户密码</th>
<th ttile="创建时间">创建时间</th>
<th title="更新时间">更新时间</th>
<th title="行为">行为</th>
</tr>
</thead>
<tbody>
<c:forEach items="${pagination.summaryList}" var="temp" varStatus="status">
<tr class="${status.index%4==0? 'success': status.index%4==1? 'primary': status.index%4==2? 'info': 'warning'}">
<td>${temp.id}</td>
<td>${temp.customer_name}</td>
<td>${temp.identity_card_number}</td>
<td>${temp.customer_password}</td>
<td>${temp.create_time}</td>
<td>${temp.update_time}</td>
<td>
<a href="javascript:void(0)" iconCls="icon-add" plain="true" onclick="newUser()">新增</a>
<a href="javascript:void(0)" iconCls="icon-edit" plain="true" onclick="editUser()">编辑</a>
<a href="javascript:void(0)" iconCls="icon-remove" plain="true" onclick="destroyUser()">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<nav><ul id="djm-pagination"></ul></nav>
<script type='text/javascript'>
$(document).ready(function(){
var totalPages = ${pagination.totalPages};
$("#djm-pagination").twbsPagination({
totalPages: totalPages,
startPage: 1,
visiblePages: 15,
first: '首页',
prev: '上一页',
next: '下一页',
last: '尾页',
loop: false,
href: 'eyes/addCustomer?currentPage={{number}}',
onPageClick: function (event, page) {
$('#page-content').text('Page ' + page);
}
});
});
</script>
</div>
</div>
</div>
</div>
<footer>
<p>
<span class="glyphicon glyphicon-link" aria-hidden="true"></span>
<a href="welcome.jsp">进入首页Copyright©DJM</a>
</p>
</footer>
</div>
</body>
</html>
页面的效果如下图:
控制层的代码:
package com.raze.controller;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.raze.common.pagination.Pagination;
import com.raze.domain.manager.TblCustomerInfo;
import com.raze.service.manager.ITblCustomerInfoService;
/**
* @author DJM
*/
@Controller
public class TblCustomerInfoController {
@Autowired
ITblCustomerInfoService tblCustomerInfoService;
@RequestMapping(value="/eyes/addCustomer")
public ModelAndView countCustomer(String customerName, String identityCardNumber, String customerPassword, Integer currentPage){
ModelAndView mav = new ModelAndView();
if((customerName==null||customerName=="")&&(identityCardNumber==null||identityCardNumber=="")&&(customerPassword==null||customerPassword=="")){
mav.setViewName("ShowRecordByPagination");
int recordCount = tblCustomerInfoService.countCustomer();
Pagination<TblCustomerInfo> pagination = new Pagination<TblCustomerInfo>(recordCount, 5, currentPage);
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("pagination", pagination);
pagination.setSummaryList(tblCustomerInfoService.obtainCustomerListByPagination(parameters));
mav.addObject("pagination", pagination);
}else{
TblCustomerInfo tblCustomerInfo = new TblCustomerInfo();
tblCustomerInfo.setCustomerName(customerName);
tblCustomerInfo.setIdentityCardNumber(identityCardNumber);
tblCustomerInfo.setCustomerPassword(customerPassword);
tblCustomerInfo.setCreateTime(new Date());
tblCustomerInfo.setUpdateTime(new Date());
try {
tblCustomerInfoService.addCustomer(tblCustomerInfo);
} catch (Exception e) {
e.printStackTrace();
mav.setViewName("FailurePage");
return mav;
}
mav.setViewName("SuccessPage");
mav.addObject("customerList", tblCustomerInfoService.getCustomerList(null));
}
mav.addObject("numberOfRecord", tblCustomerInfoService.countCustomer());
return mav;
}
}
持久层的对所需展示的页面的数据集的查询实现的部分代码如下:
@Override
public List<TblCustomerInfo> obtainCustomerListByPagination(Map<String, Object> conditions) {
SqlSession sqlSession = sqlSessionFactory.openSession();
TblCustomerInfoMapper mapper = sqlSession.getMapper(TblCustomerInfoMapper.class);
List<TblCustomerInfo> customerList = new ArrayList<TblCustomerInfo>();
customerList = mapper.obtainCustomerListByPagination(conditions);
sqlSession.close();
return customerList;
}
在配置文件中的配置为:
<select id="obtainCustomerListByPagination" parameterType="hashmap" resultType="hashmap">
SELECT * FROM tbl_customer_info
<trim prefix="WHERE" prefixOverrides="AND">
<if test="id!=null and id!=''">
id=#{id} AND
</if>
<if test="customerName!=null and customerName!=''">
customer_name=#{customerName} AND
</if>
<if test="identityCardNumber!=null and identityCardNumber!=''">
identity_card_number=#{identityCardNumber} AND
</if>
<if test="customerPassword!=null and customerPassword!=''">
customer_password=#{customerPassword}
</if>
</trim>
<include refid="PaginationNamespace.pagination_limit"></include>
</select>
最终的效果图如下: