在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截取掉了。
查詢性別爲男的人員:
至此,簡單的分頁功能已經實現了。