本文包括:
1、分頁技術概述
2、實現分頁
3、完善分業——分頁工具條
4、幾種常見的分頁工具條
1、分頁技術概述
-
物理分頁
在SQL查詢時,從數據庫只查詢分頁需要的數據
-
通常,對于不同數據庫有不同的物理分頁語句
MySQL 使用limit;
SQLServer 使用top;
Oracle使用rowNum 對于MySQL,采用limit關鍵字
-
例如:查詢第11-20條數據,SQL語句:
select * from user limit 10,10;
-
demo:
@Test public void demo2() throws SQLException { // 物理分頁 ,根據數據庫關鍵字 limit 查詢需要數據 查詢150-200條 String sql = "select * from customer order by name limit ?,?"; int start = 150 - 1; // 開始索引 開始條數-1 int len = 200 - 150 + 1; // 結束條數-開始條數 +1 QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); List<Customer> customers = queryRunner.query(sql, new BeanListHandler<Customer>(Customer.class), start, len); System.out.println("size:" + customers.size()); for (Customer customer : customers) { System.out.println(customer.getName()); } }
-
邏輯分頁
在SQL查詢時,先從數據庫查詢出所有數據的結果集
在Java代碼中通過邏輯語句獲得分頁需要的數據
-
例如:查詢第11-20條數據:
userList.subList(10,20)
-
demo:
@Test public void demo3() throws SQLException { // 邏輯分頁 150 - 200 String sql = "select * from customer order by name"; QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); List<Customer> customers = queryRunner.query(sql, new BeanListHandler<Customer>(Customer.class)); customers = customers.subList(150 - 1, 200); System.out.println("size:" + customers.size()); for (Customer customer : customers) { System.out.println(customer.getName()); } }
性能上,物理分頁明顯好于邏輯分頁,盡量使用物理分頁。
2、實現分頁
-
分類查詢UML圖
UML繪制軟件:Jude(Java and UML Developer's Environment)
Jude教程:http://blog.csdn.net/shesunshine/article/details/5670862
-
在JSP頁面新增a鏈接,其中pageQuery為PageQueryServlet的URL:
<a href="XX/pageQuery?pNum=1">分頁查詢</a>
-
PageQueryServlet:
public class PageQueryServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 獲得客戶端提交頁碼 String pNumStr = request.getParameter("pNum"); int pNum = Integer.parseInt(pNumStr);// 如果不是數字報錯 // 將頁碼傳遞 業務層 CustomerService customerService = new CustomerService(); List<Customer> customers = customer Service.pageQuery(pNum); // 傳遞結果進行顯示 request.setAttribute("customers", customers); request.getRequestDispatcher("/list.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
-
CustomerService中設置常量、新增pageQuery(int pNum)方法:
public static final int NUMBERPAGE = 10; // 設置每頁條數為常量 public List<Customer> pageQuery(int pNum){ // 根絕頁碼和每頁條數計算開始索引 int start = (pNum - 1) * NUMBERPAGE; // 調用DAO進行分頁查詢 CustomerDAO customerDAO = new CustomerDAO(); return customerDAO.findByPage(start, NUMBERPAGE); }
-
CustomerDAO中新增findByPage(int pNum, int numberPage)方法:
public List<Customer> findByPage(int start, int numberPage){ String sql = "select * from customer limit ?,?"; QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); // 利用DBUtils開源工具進行JDBC編程 try{ return queryRunner.query(sql,new BeanListHandler<Customer>(Customer.class)); } catch(SQLException e){ e.printStackTrace(); } return null; }
3、完善分頁——分頁工具條
實現分頁中的雖然能提供分頁,但是需要手動在地址欄輸入第幾頁,這顯然對用戶極不友好,不過別急,上面只是實現了分頁的效果。
-
很多網站都提供了分頁功能,分頁頁面效果:
首頁 上一頁 1 2 3 4 5 6 7 下一頁 尾頁
-
上面的工具條只適用頁數很少的業務,google查詢的頁數有上萬頁,不可能全部顯示在頁面上,也不可能提供“尾頁”這個選項,所以以當前頁為中心,提供前后5頁的跳轉鏈接,下面是一種可借鑒的分頁工具條(假設當前頁數為10):
上一頁 5 6 7 8 9 10 11 12 13 14 15 下一頁
谷歌的分頁工具條:
-
現在一般的做法,分頁查詢都會用單獨類來封裝查詢結果
PageBean ----- 在業務層返回數據返回PageBean對象
public class PageBean { public static final int NUMPERPAGE = 10; // 每頁多少條 private int pNum; // 當前第幾頁 private int totalPageNum; // 總頁數 private int totalRecordNum; // 總記錄數 private List<Customer> customers; // 結果數據 public int getpNum() { return pNum; } public void setpNum(int pNum) { this.pNum = pNum; } public int getTotalPageNum() { return totalPageNum; } public void setTotalPageNum(int totalPageNum) { this.totalPageNum = totalPageNum; } public int getTotalRecordNum() { return totalRecordNum; } public void setTotalRecordNum(int totalRecordNum) { this.totalRecordNum = totalRecordNum; } public List<Customer> getCustomers() { return customers; } public void setCustomers(List<Customer> customers) { this.customers = customers; } }
-
于是,在CustomerService修改pageQuery(int pNum)方法:
public static final int NUMBERPAGE = 10; // 設置每頁條數為常量 public PageBean pageQuery(int pNum) { // 根據頁碼 和 每頁條數 計算開始索引 int start = (pNum - 1) * NUMPERPAGE; PageBean bean = new PageBean(); // 封裝當前頁碼 bean.setpNum(pNum); // 調用DAO進行分頁查詢 --- 結果數據 CustomerDAO customerDAO = new CustomerDAO(); List<Customer> customers = customerDAO.findByPage(start, PageBean.NUMPERPAGE); bean.setCustomers(customers); // 封裝總記錄條數,findTotalRecordNum()方法見下文 int totalRecordNum = customerDAO.findTotalRecordNum(); bean.setTotalRecordNum(totalRecordNum); // 計算總頁數,很常用!!! int totalPageNum = (totalRecordNum + PageBean.NUMPERPAGE - 1) / PageBean.NUMPERPAGE; bean.setTotalPageNum(totalPageNum); return bean; }
-
在CustomerDAO中新增findTotalRecordNum()方法:
// 查詢總記錄條數 public int findTotalRecordNum() { String sql = "select count(*) from customer"; QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource()); // ScalarHandler try { // 因為結果集只有一行一列,所以這里應該用ScalarHandler long totalRecordNum = (Long) queryRunner.query(sql, new ScalarHandler(1)); return (int) totalRecordNum; // int表示的范圍足夠了 } catch (SQLException e) { e.printStackTrace(); } return 0; }
-
于是,在PageQueryServlet中修改:
修改前:
List<Customer> customers = customer Service.pageQuery(pNum); // 傳遞結果進行顯示 request.setAttribute("customers", customers); request.getRequestDispatcher("/list.jsp").forward(request, response);
修改后:
PageBean pageBean = customerService.pageQuery(pNum); // 傳遞結果進行顯示 request.setAttribute("pageBean", pageBean); // ${pageBean} request.getRequestDispatcher("/page_list.jsp").forward(request, response);
-
接下來就是編寫JSP頁面:
-
預期效果:
-
實現首頁 上一頁
<!-- 顯示首頁 --> <c:if test="${pageBean.pNum == 1}"> 首頁 上一頁 </c:if> <c:if test="${pageBean.pNum != 1}"> <a href="/pageQuery?pNum=1">首頁</a> <a href="/pageQuery?pNum=${pageBean.pNum-1 }">上一頁</a> </c:if>
-
實現下一頁 尾頁
<!-- 顯示尾頁 --> <c:if test="${pageBean.pNum == pageBean.totalPageNum}"> 下一頁 尾頁 </c:if> <c:if test="${pageBean.pNum != pageBean.totalPageNum}"> <a href="/pageQuery?pNum=${pageBean.pNum + 1 }">下一頁</a> <a href="/pageQuery?pNum=${pageBean.totalPageNum}">尾頁</a> </c:if>
-
實現 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
<!-- 當前頁為中心前后各顯示10頁 --> <c:set var="begin" value="1" scope="page" /> <c:set var="end" value="${pageBean.totalPageNum}" scope="page" /> <!-- 判斷前面有沒有10頁 --> <c:if test="${pageBean.pNum-10>0}"> <c:set var="begin" value="${pageBean.pNum-10}" scope="page" /> </c:if> <!-- 判斷后面有沒有10頁 --> <c:if test="${pageBean.pNum+10 < pageBean.totalPageNum}"> <c:set var="end" value="${pageBean.pNum + 10}" scope="page" /> </c:if> <!-- 利用foreach循環輸出 --> <c:forEach begin="${begin}" end="${end}" var="i"> <a href="/pageQuery?pNum=${i }">${i } </a> </c:forEach>
-
至此基本功能完成,但是顯示的效果很差:
-
現在的問題是:根本不知道哪個是當前頁,所以還要改進一下foreach中的代碼:
<!-- 當前頁不顯示鏈接,即可知道哪個是當前頁 --> <!-- 利用foreach循環輸出 --> <c:forEach begin="${begin}" end="${end}" var="i"> <c:if test="${pageBean.pNum==i}"> ${i } </c:if> <c:if test="${pageBean.pNum!=i}"> <a href="/pageQuery?pNum=${i }">${i } </a> </c:if> </c:forEach>
-
現在即可清晰的顯示當前頁了(可用CSS/JavaScript進一步美化界面,功能實現到此為止)
-
實現輸入頁碼跳轉,在尾頁代碼的后面加入input:
<input type="text" id="pNum" size="2"/><input type="button" value="go" onclick="jump();"/>
對應的JavaScript代碼:
<script type="text/javascript"> function jump(){ // 獲得用戶輸入頁碼 var pNum = document.getElementById("pNum").value; location.href="/pageQuery?pNum=" + pNum; } </script>
-
4、幾種常見的分頁工具條
-
百度
強迫癥看著難受,為什么前面顯示5頁,后面顯示4頁???
-
必應
必應的分頁工具條很簡潔。
-
CSDN博客:http://blog.csdn.net/
這種分頁工具欄比較有意思,我們來分析一下:
- 利用Chrome瀏覽器的檢查功能:
它的分頁工具條只顯示5頁,最左邊的頁碼是
m*5+1 (m為非負整數)
,最右邊的頁碼是(m+1)*5
,點擊左側的...
,上述的m
變為m-1
,點擊右側的...
,上述的m
變為m+1
。-
它的重點在于計算當前頁所屬的
m
值,稍微思考一下,可以得出當前頁pNum
與當前頁所屬的m
值的關系:int m = pNum/5;
注意分頁工具條左側的
...
,當前頁為6時,它會跳轉到第1頁,所以無論是左側還是右側的...
,都將會跳轉到對應m
值的第1頁。