《JavaWeb從入門到改行》分頁功能的實現


@目錄

       什么是分頁 ?

      兩個子模塊功能的問題分析 和 解決方案

      有條件查和無條件查詢的影響 和 解決方案

     項目案例: mysql + commons-dbutils+itcast-tools+BaseServlet + 分頁+JSP+JSTL+EL+MVC模式

 


 

什么是分頁?

如上所示,就是分頁  ,不用多說了

子模塊功能的問題分析 和 解決方案

 

@總功能分析  常規JDBC中,點擊查詢或輸入條件查詢,在頁面中可顯示查詢出的所有記錄,有多少記錄就顯示多少。在這種項目的基礎上增加分頁功能 。 @分頁功能的宗旨 是無論什么樣的查詢,顯示出的記錄都是當前頁的記錄 。  所以,我們必須得向系統說明我們當前是要顯示第幾頁的數據 。  自然,需要一個PageBean類

public class PageBean<T> {
        private int pageCode ;//當前頁碼
//        private int totalPage ;//總頁數,總頁數應該由計算獲取
        private int totalRecord;//總記錄數
        private int pageSize;//每頁記錄數,這是參數是定做這個軟件的甲方提出來的,在Servlet中直接定義為10了
        private List<T> beanList;//當前頁的記錄集合,方便整頁記錄的轉移
        private String url ;//Url后的條件,條件查詢設置的

這個PageBean類中封裝了當前頁、總記錄數、當前頁所有記錄的集合等,系統通過當前頁碼這個參數返回pageSize條記錄放在beanList集合中返回顯示。 

@子模塊功能1 中首頁的pageCode是1,尾頁的pageCode是totalPage,上一頁和下一頁分別是pageCode-1 和pageCode+1 。 

@子模塊功能2 先來分析一個功能 : 當前頁在頁碼列表中是第幾個位置 ?

 

從上述兩張圖片中,點擊1頁碼,當前頁處於列表的第1個位置,點擊2頁碼,當前頁處於列表的第2個位置,..........,點擊6頁碼,當前頁處於列表的第6個位置,但是當點擊7頁碼時,當前頁還是處於列表的第6個位置 。 也就是說,假如每次一行只能顯示10個頁碼,1~6頁碼的當前頁的位置還是1~6,列表從頁碼1~頁碼10。   但是7~10頁碼的當前頁的位置始終位於頁碼列表的第6個位置 ,列表從【頁碼2~頁碼11】~【頁碼X~頁碼totalPage】。其實非常好解決  ,列表頭尾的判定 還是利用pageCode , begin = pageCode - 5   ,  end = pageCode + 4  。 

@解決 

  • 如果  totalPage  <=  10(列表長度),那么  begin  =  1,end  =  totalPage ;
  • 使用公式計算;begin  =  pc-5    ,    end  =   pc   +   4;
  •  頭溢出:當  begin  <  1  時   ,   讓  begin  =  1 ;
  • 尾溢出:當   end  >  totalPage  時   ,   讓  end  =  totalPage         

 

有條件查和無條件查詢的影響 和 解決方案

 @產生一個問題  分頁使得有條件查詢產生一個嚴重問題 , 通過條件查詢出40條記錄,分4頁顯示,只有第一頁是該條件下的記錄,其余3頁都是不帶條件的記錄 。所以我們必須告訴系統我們的條件是什么,每一頁都要帶着條件去查詢和返回  。  

@解決 在pageBean中設置url參數 , 這個參數將會攜帶這條件傳遞到Servlet中 。 

項目案例(mvc+jdbc+c3p0+BaseServlet+mysql+JSP+EL+JSTL)

@使用   mysql數據庫,c3p0數據庫連接池,

             采用commons-dbutils組件,封裝好的JdbcUtils工具類和TxQueryRunner工具類輔助JDBC ,  (學習地址 : http://www.cnblogs.com/zyuqiang/p/7218083.html

             BaseServlet輔助類 

            JSP+EL+JSTL

@數據庫

1 CREATE TABLE t_customer (
2    username VARCHAR(50) DEFAULT NULL,
3    age INT(11) DEFAULT NULL,
4    balance DOUBLE(20,5) DEFAULT NULL
5 );
t_customer

 

 @源碼

 1 package cn.kmust.pagination.customer.domain;
 2 /**
 3  * 實體類
 4  *    變量名字與數據庫中對應字段名一樣,便於封裝操作
 5  * @author ZHAOYUQIANG
 6  *
 7  */
 8 public class Customer {
 9     private String username ; //用戶
10     private int age ;  //年齡
11     private double balance ; //資金
12     public String getUsername() {
13         return username;
14     }
15     public void setUsername(String username) {
16         this.username = username;
17     }
18     public int getAge() {
19         return age;
20     }
21     public void setAge(int age) {
22         this.age = age;
23     }
24     public double getBalance() {
25         return balance;
26     }
27     public void setBalance(double balance) {
28         this.balance = balance;
29     }
30     @Override
31     public String toString() {
32         return "Customer [username=" + username + ", age=" + age + ", balance="
33                 + balance + "]";
34     }
35     public Customer(String username, int age, double balance) {
36         super();
37         this.username = username;
38         this.age = age;
39         this.balance = balance;
40     }
41     public Customer() {
42         super();
43         // TODO Auto-generated constructor stub
44     }
45     
46     
47     
48 
49 }
Customer
 1 package cn.kmust.pagination.pageBean.domain;
 2 import java.util.List;
 3 import java.util.List;
 4 /**
 5      * 分頁Bean
 6      *    把每一頁中的當前頁碼、總頁數、總記錄數、每頁記錄數、當前頁的記錄集合等參數
 7      *       封裝到該類的一個對象中,形成PageBean對象
 8      * @author ZHAOYUQIANG
 9      *
10      */
11     public class PageBean<T> {
12         private int pageCode ;//當前頁碼
13 //        private int totalPage ;//總頁數,總頁數應該由計算獲取
14         private int totalRecord;//總記錄數
15         private int pageSize;//每頁記錄數,這是參數是定做這個軟件的甲方提出來的,在Servlet中直接定義為10了
16         private List<T> beanList;//當前頁的記錄集合,方便整頁記錄的轉移
17         private String url ;//Url后的條件,條件查詢設置的
18         
19         public String getUrl() {
20             return url;
21         }
22         public void setUrl(String url) {
23             this.url = url;
24         }
25         public int getPageCode() {
26             return pageCode;
27         }
28         public void setPageCode(int pageCode) {
29             this.pageCode = pageCode;
30         }
31         /*
32          * 計算總頁數,這個頁數是由總記錄和每頁記錄數決定的
33          */
34         public int getTotalPage() {
35             int totalPage = totalRecord/pageSize ;            
36             return totalRecord%pageSize==0 ? totalPage : totalPage+1;
37         }
38         public int getTotalRecord() {
39             return totalRecord;
40         }
41         public void setTotalRecord(int totalRecord) {
42             this.totalRecord = totalRecord;
43         }
44         public int getPageSize() {
45             return pageSize;
46         }
47         public void setPageSize(int pageSize) {
48             this.pageSize = pageSize;
49         }
50         public List<T> getBeanList() {
51             return beanList;
52         }
53         public void setBeanList(List<T> beanList) {
54             this.beanList = beanList;
55         }
56 
57 }
PageBean
  1 package cn.kmust.pagination.customer.servlet;
  2 
  3 import java.io.IOException;
  4 import java.io.UnsupportedEncodingException;
  5 
  6 import javax.servlet.ServletException;
  7 import javax.servlet.http.HttpServletRequest;
  8 import javax.servlet.http.HttpServletResponse;
  9 
 10 import cn.itcast.commons.CommonUtils;
 11 import cn.itcast.servlet.BaseServlet;
 12 import cn.kmust.pagination.customer.domain.Customer;
 13 import cn.kmust.pagination.customer.service.CustomerService;
 14 import cn.kmust.pagination.pageBean.domain.PageBean;
 15 /**
 16   * Web層
 17   *   繼承了我們自己寫的BaseServlet類
 18   *   要求寫的方法得與service()相同,
 19   *     並且.jsp頁面必須傳遞過來一個method參數,如(add、deleter等)
 20   *   
 21   * @author ZHAOYUQIANG
 22   *
 23 */
 24 public class CustomerServlet extends BaseServlet {
 25     /*
 26      * 依賴CustomerService
 27      */
 28     private CustomerService cstmService = new CustomerService();
 29     /**
 30      * 客戶查詢所有
 31      *    加入了分頁功能 : 向頁面返回當前頁的所有記錄, 返回的是一個對象,對象中封裝了一個beanList集合
 32      *         該集合中存放這當前頁所有記錄
 33      * @param request
 34      * @param response
 35      * @return
 36      * @throws ServletException
 37      * @throws IOException
 38      */
 39     public String queryAll(HttpServletRequest request, HttpServletResponse response)
 40             throws ServletException, IOException {
 41         /*
 42          * 1. 獲取list.jsp頁面傳遞的pc
 43          * 2. 給定每頁記錄數ps = 10 。開發者根據客戶的需求,認為規定的
 44          * 3. 使用pc和ps調用sevice方法,得到當前頁的PageBean對象(該對象中封裝了
 45          *         當前頁的所有記錄的集合等)
 46          * 4. 把PageBean保存到request域中
 47          * 5. 轉發到list.jsp
 48          * 
 49          */
 50         int pageCode = getCurrentPage(request);
 51         int pageSize = 10 ; //每頁10記錄        
 52         PageBean<Customer> pageBean = cstmService.queryAll(pageCode,pageSize);
 53         /*
 54          * 因為與條件查詢共用一個list.jsp,所以也需要加url
 55          */
 56         pageBean.setUrl(getUrl(request));
 57         request.setAttribute("pageBean", pageBean);
 58         return "f:/list.jsp";
 59        
 60     }
 61     
 62 
 63     /**
 64      * 條件查詢
 65      *    具有分頁功能,按照條件查詢,條件也會被帶入分頁中
 66      * @param request
 67      * @param response
 68      * @return
 69      * @throws ServletException
 70      * @throws IOException
 71      */
 72     public String query(HttpServletRequest request, HttpServletResponse response)
 73             throws ServletException, IOException {
 74         /*
 75          * 1. 封裝表單數據到Customer對象中
 76          *       只有一個屬性username,是查詢的條件critaria
 77          * 2. 得到當前頁碼 pageCode
 78          * 3. 給定pageSize 10 
 79          * 4. 使用pageCode和pageSize以及條件對象,調用service方法得到query,
 80          *            返回當前頁的PageBean對象,內封裝了當前頁的所有記錄集合
 81          * 5. 把PageBean保存到request域中
 82          * 6. 轉發到list.jsp顯示成功信息
 83          */
 84         Customer criteria = CommonUtils.toBean(request.getParameterMap(), Customer.class);    
 85         /*
 86          * 處理GET請求方式編碼問題
 87          *    因為query.jsp表單使用的是get提交方法
 88          */
 89         criteria = encoding(criteria);
 90         
 91         int pageCode = getCurrentPage(request);
 92         int pageSize = 10 ; //每頁10記錄
 93         PageBean<Customer> pageBean = cstmService.query(criteria,pageCode,pageSize);
 94         /*
 95          * 得到url,保存到pageBean對象中
 96          */
 97         pageBean.setUrl(getUrl(request));
 98         request.setAttribute("pageBean", pageBean);
 99         return "f:/list.jsp";
100     }
101     
102     
103     /**
104      * 處理GET請求亂碼
105      *    因為BaseSevlet類中只有處理POST請求的亂碼,沒有GET請求的亂碼處理
106      * @param criteria
107      * @return
108      * @throws UnsupportedEncodingException 
109      */
110     private Customer encoding(Customer criteria) throws UnsupportedEncodingException {
111         String username = criteria.getUsername();
112        
113         if(username != null && !username.trim().isEmpty()){
114             username = new String(username.getBytes("ISO-8859-1"),"utf-8");
115             criteria.setUsername(username);
116         }    
117         return criteria;
118     }
119     
120     
121     
122     
123     /**
124      * 獲取pageCode(當前頁碼)
125      *     傳遞到Servlet中的參數都是String類型的,所以需要轉換
126      *     pageCode參數如果不存在,說明是第一次調用,當前頁碼默認為第一頁
127      * @param request
128      * @return
129      */
130     private int getCurrentPage(HttpServletRequest request){
131         String value = request.getParameter("pageCode");
132         if(value == null || value.trim().isEmpty()){
133             return 1 ;
134         }
135         return Integer.parseInt(value);    
136     }
137     
138     
139     /**
140      * 截取url
141      *   條件查詢中需要使用
142      *    /項目名/Servlet路徑?參數字符串
143      * @param request
144      * @return
145      */
146     private String getUrl(HttpServletRequest request){
147         /*
148          * 1. 獲取項目名
149          * 2. 獲取Servlet路徑
150          * 3. 獲取參數列表
151          *       這個參數是條件
152          */
153         String contextPath = request.getContextPath();
154         String servletPath = request.getServletPath();
155         String queryString = request.getQueryString();
156         /*
157          * 4. 判斷是否包含pageCode參數 
158          *      如果包含需要剪掉,不要這個參數
159          */
160         if(queryString.contains("&pageCode")){
161             int index = queryString.lastIndexOf("&pageCode");
162             queryString = queryString.substring(0,index);
163         }
164         return contextPath+servletPath+"?"+queryString ;
165     }
166 
167 }
CustomerServlet
 1 package cn.kmust.pagination.customer.service;
 2 
 3 import java.sql.SQLException;
 4 import java.util.List;
 5 
 6 import cn.itcast.jdbc.JdbcUtils;
 7 import cn.kmust.pagination.customer.dao.CustomerDao;
 8 import cn.kmust.pagination.customer.domain.Customer;
 9 import cn.kmust.pagination.pageBean.domain.PageBean;
10 
11 
12 
13 /**
14  * service 層   處理業務
15  * @功能  
16  *       1. 條件查詢
17  *       2. 查詢 所有用戶
18  *       3. 查詢 所有記錄行數
19  * @author ZHAOYUQIANG
20  *
21  */
22 public class CustomerService {
23     /*
24      * 依賴CustomerDao
25      */
26     CustomerDao cstmDao = new CustomerDao();
27     /**
28      * 條件查詢
29      *   
30      * @param criteria
31      * @param pageCode
32      * @param pageSize
33      * @return
34      */
35     public PageBean<Customer> query(Customer criteria,int pc,int ps) {
36            return  cstmDao.query(criteria,pc,ps);            
37         }
38     /**
39      * 查詢所有客戶業務
40      *  具有分頁功能 : 返回PageBean對象 ,對象中封裝了 當前頁所有記錄的集合
41      * @param pc
42      * @param ps
43      * @return
44      */
45     public PageBean<Customer> queryAll(int pc,int ps){
46         return cstmDao.queryAll(pc,ps);
47     }
48     
49     
50     
51 }
CustomerService
  1 package cn.kmust.pagination.customer.dao;
  2 
  3 import java.sql.ResultSet;
  4 import java.sql.SQLException;
  5 import java.util.ArrayList;
  6 import java.util.List;
  7 import java.util.Map;
  8 
  9 import javax.sql.DataSource;
 10 
 11 import org.apache.commons.dbutils.QueryRunner;
 12 import org.apache.commons.dbutils.ResultSetHandler;
 13 import org.apache.commons.dbutils.handlers.BeanHandler;
 14 import org.apache.commons.dbutils.handlers.BeanListHandler;
 15 import org.apache.commons.dbutils.handlers.MapHandler;
 16 import org.apache.commons.dbutils.handlers.MapListHandler;
 17 import org.apache.commons.dbutils.handlers.ScalarHandler;
 18 
 19 import cn.itcast.jdbc.JdbcUtils;
 20 import cn.itcast.jdbc.TxQueryRunner;
 21 import cn.kmust.pagination.customer.domain.Customer;
 22 import cn.kmust.pagination.pageBean.domain.PageBean;
 23 
 24 
 25 
 26 
 27 /**
 28  *dao層  
 29  *    對數據庫的操作 
 30  * @author ZHAOYUQIANG
 31  *
 32  */
 33 public class CustomerDao {
 34     private QueryRunner qr = new TxQueryRunner();     
 35     /**
 36      * 對數據庫進行查詢所有客戶操作
 37      *   具有分頁功能  : 返回PageBean對象,該對象封裝了當前頁的所有記錄的集合
 38      *      當前頁的所有記錄都放到beanList集合中,然后隨當前頁碼等參數封裝到pageBean中返回  
 39      * @return
 40      */
 41     public PageBean<Customer> queryAll(int pc,int ps){
 42         try {
 43             /*
 44              * 有關數據庫的操作:
 45              *     准備sql模版
 46              *     調用QueryRunner的query方法
 47              */
 48             /*該方法的任務:
 49              *  1. 創建PageBean對象
 50              */
 51             PageBean<Customer> pageBean = new PageBean<Customer>();
 52             /*
 53              * 2. 設置pc和ps,封裝到我pageBean對象
 54              */
 55             pageBean.setPageCode(pc);
 56             pageBean.setPageSize(ps);
 57             /*
 58              *  3. 查詢數據庫得到totalRecord(數據庫所有記錄),封裝到我pageBean對象
 59              */
 60             String sql = "select count(*) from t_customer";
 61             Number num = (Number)qr.query(sql,new ScalarHandler() );
 62             int totalRecord  = num.intValue();
 63             pageBean.setTotalRecord(totalRecord);
 64             /*
 65              * 4. 查詢數據庫得到BeanList(當前頁記錄的集合),封裝到我pageBean對象
 66              *      當前頁到底是第幾頁,當前頁有多少條記錄呢?
 67              *        利用mysql的limit子句, (limit 4,10的意思是從第五行記錄開始(包含第五行),查詢10行記錄)
 68              *          很明顯當前頁的是從第(pc-1)*ps行開始,查詢ps行記錄。
 69              *          根據limit子句的特點,巧妙的設計查詢當前頁的數據
 70              *      用order by 通過客戶姓名來排序顯示
 71              */
 72             sql = "select * from t_customer order by username limit ?,?";
 73             List<Customer> beanList = qr.query(sql, 
 74                     new BeanListHandler<Customer>(Customer.class),(pc-1)*ps,ps);        
 75             pageBean.setBeanList(beanList);
 76             /*
 77              * 5. 返回PageBean對象
 78              */
 79             return pageBean ;
 80         } catch (SQLException e) {
 81             throw new RuntimeException(e);
 82         }        
 83     }
 84     /**
 85      * 條件查詢
 86      *   具有分頁功能
 87      * @param criteria
 88      * @param pc
 89      * @param ps
 90      * @return
 91      */
 92     public PageBean<Customer> query(Customer criteria,int pc,int ps) {
 93         try {
 94             /*
 95              * 1. 創建PageBean對象
 96              * 2. 設置已有屬性,pc和ps(pageCode和pageSize)
 97              * 3. 通過條件查詢數據庫得到totalRecord
 98              * 4. 查詢數據庫,返回beanList(當前頁記錄的集合)
 99              */
100             PageBean<Customer> pageBean = new PageBean<Customer>();
101             pageBean.setPageCode(pc);
102             pageBean.setPageSize(ps);
103             /*
104              * 3. 通過條件查詢數據庫得到totalRecord 
105              */
106             String sql1 = null;
107             String username = criteria.getUsername();
108             if(username != null && !username.trim().isEmpty()){                
109                 sql1 = "select count(*) from t_customer where username like ?" ;
110             }
111             Object[] params1 = {"%"+username+"%"};
112             /*
113              * 3.3. 得到totalRecord
114              */
115             Number num = (Number)qr.query(sql1,
116                     new ScalarHandler(),params1);
117             int totalRecord = num.intValue();
118             pageBean.setTotalRecord(totalRecord);
119             /*
120              * 4. 查詢數據庫,返回beanList(當前頁記錄的集合)
121              *    還是需要拼湊sql語句,並且需要limit子句
122              *      params中需要給出limit后兩個問號對應的值
123              *    
124              */
125             
126             String sql2 = "select * from t_customer where username like ? limit ?,?";
127             
128             Object[] params = {"%"+username+"%",(pc-1)*ps,ps};
129             List<Customer> beanList = qr.query(sql2,
130                     new BeanListHandler<Customer>(Customer.class),
131                     params);
132             pageBean.setBeanList(beanList);
133             return pageBean ;
134         } catch (SQLException e) {
135             throw new RuntimeException(e);
136         }
137         
138     }
139 }
CustomerDao

 

 @項目download   http://files.cnblogs.com/files/zyuqiang/jdbcStudy_Demo5_pagination.rar

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM