在web应用中展现查询结果通常都须要使用分页功能,使用分页咱们能够每次只查出当前页的数据,从而减少每次请求的数据量。mysql可使用limit方言,oracle可使用rownum来实现与limit相同的效果。若是数据总量不是特别大的话也能够将全部结果所有查出来,而后对结果进行截取,这种状况下通常使用ArrayList来接受结果集,保证取出的顺序和存入的数据一致。javascript
分页的时候有几个关键的属性须要在servlet、service、dao层中进行传输,其中须要从前端页面传入的属性包括当前页码、每页记录条数以及查询条件参数,须要从dao层返回的属性有总记录条数、当前页的数据(总页数可计算得出)。因此通常讲这些关键属性都封装在javaBean中,用javaBean来接收和传递分页的关键参数。css
一、查询所有结果进行分页html
public class PageBean<T> { private int pc;//当前页码 //private int tp;//总页数 private int tr;//总条数 private int ps;//每页条数 private List<T> pageList;//当前页的数据 private String url;//请求的url和参数 public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getTp(){ //获取总页数,总页数不设置属性的缘由是只能从查询的结果中进行计算获取总页数 int tp = tr /ps; return tr%ps==0 ? tp : tp+1; } public int getPc() { return pc; } public void setPc(int pc) { this.pc = pc; } public int getTr() { return tr; } public void setTr(int tr) { this.tr = tr; } public int getPs() { return ps; } public void setPs(int ps) { this.ps = ps; } public List<T> getPageList() { return pageList; } public void setPageList(List<T> pageList) { this.pageList = pageList; } }
这里也封装了一个url属性,这个属性是在复用显示分页结果的页面时会用到。由于咱们的结果展现页面可能会被多个查询发放使用,因此在结果页面的请求url必须是动态的,url中还必须带上查询的条件,由于第一次分页查询的时候可能会有一些过滤条件,在咱们经过点击“下一页”之类的超连接时也须要将初始查询参数带上。前端
首页:java
<html> <head> </head> <body style="text-align: center;"> <h1>分页示例</h1> <a href="<c:url value='/CustomerServlet?method=findAll'/>" >查询人员</a> <a href="<c:url value='/query.jsp'/>">带条件的分页</a> </body> </html>
servlet:mysql
public String findAll(HttpServletRequest request,HttpServletResponse response) throws Exception { int pc = getPc(request); int ps = ConfigUtil.getPc(); String url = getUrl(request); PageBean<Customer> page = customerService.findAll(pc,ps); page.setUrl(url); System.out.println(url); request.setAttribute("pb", page); return "/list.jsp"; } public int getPc(HttpServletRequest request){ String pc = request.getParameter("pc"); return pc==null|| pc.trim().isEmpty()?1:Integer.parseInt(pc); } public String getUrl(HttpServletRequest request){ String url = request.getRequestURI(); String params = request.getQueryString(); if(params.indexOf("&pc")!=-1){//url中全部初始参数保留,除了须要跳转的页码数,每次请求时都不一样,这里由于咱们的应用pc老是最后一个参数,因此能够直接截取掉pc参数 params = params.substring(0, params.indexOf("&pc")); } return url+"?"+params; }
这里ConfigUtil.getPc()是从配置文件中获取每页的条数。也有许多web应用在前端页面上能够改变每页的记录条数,那么就要将这里ps改为从request中获取。web
public class ConfigUtil { private static Properties prop = null; static { /* * 加载配置文件 * 只在JdbcUtils类被加载时执行一次 */ InputStream in = ConfigUtil.class.getClassLoader().getResourceAsStream("com//leo//customer//config//config.properties"); prop = new Properties(); try { prop.load(in); } catch (IOException e) { throw new RuntimeException(); } } public static int getPs(){ return Integer.parseInt(prop.getProperty("pagesize")) ; } }
service:sql
package com.leo.customer.service; import java.sql.SQLException; import java.util.List; import com.leo.customer.dao.CustomerDao; import com.leo.customer.domain.Customer; import com.leo.customer.domain.PageBean; import com.leo.customer.jdbc.JdbcUtils; public class CustomerService { private CustomerDao dao = new CustomerDao(); //分页查询所有 public PageBean<Customer> findAll(int pc ,int ps) throws SQLException{ return dao.findAll(pc,ps); } }
dao:apache
package com.leo.customer.dao; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.dbutils.handlers.ScalarHandler; import com.leo.customer.domain.Customer; import com.leo.customer.domain.PageBean; import com.leo.customer.jdbc.TxQueryRunner; import com.leo.customer.util.BeanHandler; import com.leo.customer.util.BeanListHandler; public class CustomerDao { private TxQueryRunner qr = new TxQueryRunner(); //分页查询所有 public PageBean<Customer> findAll(int pc,int ps) throws SQLException{ PageBean<Customer> pb = new PageBean<Customer>(); pb.setPc(pc); pb.setPs(ps); String sql = "select count(1) from t_customer"; Number n = (Number) qr.query(sql, new ScalarHandler()); pb.setTr(n.intValue()); sql = "select * from t_customer order by cid limit ?,?"; Object[] params = {(pc-1)*ps,ps}; List<Customer> list = qr.query(sql, new BeanListHandler<Customer>(Customer.class), params); pb.setPageList(list); return pb; } }
这里TxQueryRunner是QueryRunner的扩展类,结合JdbcUtil类作的事务处理,这里由于是查询操做,因此能够不用关注事务。dao层中调用TxQueryRunner的方法代码为oracle
public <T> T query(String sql, ResultSetHandler<T> rsh) throws SQLException { Connection con = JdbcUtils.getConnection(); T result = super.query(con, sql, rsh); JdbcUtils.releaseConnection(con); return result; } public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { Connection con = JdbcUtils.getConnection(); T result = super.query(con, sql, rsh, params); JdbcUtils.releaseConnection(con); return result; }
若是不须要进行事务处理,这里彻底可使用QueryRunner来进行查询。
查询显示页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <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="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h3 align="center">客户列表</h3> <table border="1" width="70%" align="center"> <tr> <th>客户姓名</th> <th>性别</th> <th>生日</th> <th>手机</th> <th>邮箱</th> <th>描述</th> <th>操做</th> </tr> <c:forEach items="${requestScope.pb.pageList}" var="cstm"> <tr> <td>${cstm.cname }</td> <td>${cstm.gender }</td> <td>${cstm.birthday }</td> <td>${cstm.cellphone }</td> <td>${cstm.email }</td> <td>${cstm.description }</td> <td> <a href="<c:url value='/CustomerServlet?method=preEdit&cid=${cstm.cid }'/>" >编辑</a> <a href="<c:url value='/CustomerServlet?method=delete&cid=${cstm.cid }'/>">删除</a> </td> </tr> </c:forEach> </table> <br/> <c:choose> <c:when test="${pb.tp<=10 }"> <c:set var="begin" value="1"></c:set> <c:set var="end" value="${pb.tp }"></c:set> </c:when> <c:otherwise> <c:set var="begin" value="${pb.pc-5}"></c:set> <c:set var="end" value="${pb.pc+4}"></c:set> <c:if test="${begin <1 }"> <c:set var ="begin" value="1"></c:set> <c:set var = "end" value="10"></c:set> </c:if> <c:if test="${end >pb.pc }"> <c:set var ="begin" value="${ pb.tp-9}"></c:set> <c:set var = "end" value="${pb.tp }"></c:set> </c:if> <c:if test=""></c:if> </c:otherwise> </c:choose> <center> 第${pb.pc }页/共${pb.tp }页 <a href="${pb.url}&pc=1">首页</a> <c:if test="${pb.pc > 1 }"> <a href="${pb.url}&pc=${pb.pc-1}">上一页</a> </c:if> <c:forEach var="i" begin="${begin }" end="${end }"> <c:choose> <c:when test="${i eq pb.pc }"> <span style="color:red">[${ i}]</span> </c:when> <c:otherwise> <a href="${pb.url}&pc=${ i}">[${ i}]</a> </c:otherwise> </c:choose> </c:forEach> <c:if test="${pb.pc < pb.tp }"> <a href="${pb.url}&pc=${pb.pc+1}">下一页</a> </c:if> <a href="${pb.url}&pc=${pb.tp}">尾页</a> <span>第</span> <input type="text" id="topc" name="topc" style="width:30px" onblur="toPage()"> <input type="hidden" id="tp" value="${pb.tp }" > <input type="hidden" id="url" value="${pb.url }" > <span>页</span> <a onclick="fnToPage()" href="#">跳转</a> </center> </body> <script type="text/javascript"> function toPage(){ var topage = document.getElementById("topc").value; var tp = document.getElementById("tp").value; if(topage>tp || topage < 1){ alert("页码有误,请输入1到"+tp+"之间的整数"); } } function fnToPage(){ var topage = document.getElementById("topc").value; var url = document.getElementById("url").value; if(topage==""||topage==null){ alert("请输入要跳转的页面"); return; } href = url+"&pc="+topage; window.location = href; } </script> </html>
最终效果:
二、根据条件查询进行分页
从首页进入到query.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <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="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h3 align="center">高级搜索</h3> <form action="<c:url value='/CustomerServlet'/>" method="get"> <input type="hidden" name="method" value="query"/> <table border="0" align="center" width="40%" style="margin-left: 100px;"> <tr> <td width="100px">客户名称</td> <td width="40%"> <input type="text" name="cname"/> </td> </tr> <tr> <td>客户性别</td> <td> <select name="gender"> <option value="">==请选择性别==</option> <option value="男">男</option> <option value="女">女</option> </select> </td> </tr> <tr> <td>手机</td> <td> <input type="text" name="cellphone" /> </td> <td> <label id="cellphoneError" class="error" > ${ cellphoneError}</label> </td> </tr> <tr> <td>邮箱</td> <td> <input type="text" name="email" value="${email}"/> </td> <td> <label id="emailError" class="error"> ${ emailError}</label> </td> </tr> <tr> <td> </td> <td> <input type="submit" value="搜索"/> <input type="reset" value="重置"/> </td> <td> </td> </tr> </table> </form> </body> </html>
输入条件进行过滤查询。这里为了简单起见使用了get方法进行提交,由于咱们要将查询的url(包含参数)保存到request中,使用get方法咱们在servlet中能够直接使用getQueryString来获取查询参数字符串,若是使用post须要手动拼接。
在servlet中编写query方法:
public String query(HttpServletRequest request,HttpServletResponse response) throws SQLException{ String cname = request.getParameter("cname"); String gender = request.getParameter("gender"); String cellphone = request.getParameter("cellphone"); String email = request.getParameter("email"); if(cellphone!=null &&cellphone.length()>15){ request.setAttribute("cellphoneError", "手机号过长"); return "/query.jsp"; } if(email!=null && email!=""){ if(email.length()>40||email.indexOf("@")<0){ request.setAttribute("emailError", "邮箱格式错误"); request.setAttribute("email", email); return "/query.jsp"; } } int pc = getPc(request); int ps = ConfigUtil.getPs(); String url = getUrl(request); System.out.println(url); PageBean<Customer> page = customerService.query(cname,gender,cellphone,email,pc,ps); page.setUrl(url); request.setAttribute("pb", page); return "/list.jsp"; }
service:
public PageBean<Customer> query(String cname,String gender,String cellphone,String email,int pc,int ps) throws SQLException{ return dao.query(cname,gender,cellphone,email,pc,ps); }
dao:
public PageBean<Customer> query(String cname,String gender,String cellphone,String email,int pc,int ps) throws SQLException{ String sql = "select * from t_customer where 1=1 "; List params = new ArrayList(); if(cname.length()>0){ sql += "and cname = ? "; params.add(cname); } if(gender.length()>0){ sql += "and gender = ? "; params.add(gender); } if(cellphone.length()>0){ sql += "and cellphone = ? "; params.add(cellphone); } if(email.length()>0){ sql += "and email = ? "; params.add(email); } PageBean<Customer> page = new PageBean<Customer>(); page.setPc(pc); page.setPs(ps); List<Customer> list = qr.query(sql, new BeanListHandler<Customer>(Customer.class),params.toArray()); if(list==null) list = new ArrayList<Customer>(); page.setTr(list.size()); int toindex = pc*ps; if(toindex>list.size()){ toindex = list.size(); } page.setPageList(list.subList((pc-1)*ps, toindex)); return page; }
这里没有使用mysql的limit方言,而是直接根据页码和每页记录数对结果集进行截取处理。
getUrl方法确保了即便咱们在页面上点击下一页或者跳转某一页,咱们的请求url中的参数始终不变,初始化查询性别为男,在页面上不论如何点击页码跳转,url中都会有性别参数为男。惟一变化的参数是请求跳转的页码,因此在getUrl方法中将参数pc截取掉了。
查询性别为男的人员:
至此,简单的分页功能已经实现了。