zoukankan      html  css  js  c++  java
  • 《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

  • 相关阅读:
    Java基础面试题附答案 81-100(五)
    css练习--抽屉作业
    css
    HTML 快速入门
    selectors 模块完成文件上传下载功能
    IO 模型
    进程 线程 协程
    socket套接字
    异常处理
    面向对象
  • 原文地址:https://www.cnblogs.com/zyuqiang/p/7235548.html
Copyright © 2011-2022 走看看