分页的实现方式虽有多种,但是当需分页展示大量数据的时候,将分页写在后台才是最好的选择。首先我定义了一个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>
最终的效果图如下: