zoukankan      html  css  js  c++  java
  • 分页

    1. 分页的优点
      • 只查询一页,不用查询所有页!有利于提高效率.

    2. 分页数据

    1. 页面的数据都是由 Servlet 传递过来的. Servlet 需要给页面提供
    2. 当前页: pageCode, 简写 pc
      • 如果页面没有传递当前页码, 那么 Servlet 默认是第一页, 否则,以页面传递的为准!
    3. 总页数: totalPages, 简写 tp
      • tp = 总记录数/每页记录数;
      • 总记录数: totalRecord, tr. 由 DAO 来获取, SELECT COUNT(*) FROM t_customer;
      • 每页记录数: 也称为业务数据或系统数据, 由我们自己来定义, 此处为 10 行;
    4. 当前页数据: beanList
    5. url : 用于保存查询条件

    3. 数据传递

    • 我们需要把这些分页数据封装到一个 javaBean 中, 它就叫 PageBean.
    public class PageBean<T>{
        private int pc;  // 当前页码,page Code
        //private int tp;  总页数, total page, 通过计算得到
        private int tr;  // 总记录数, total record
        private int ps;  // 每页记录数, page size
        private List<T> beanList;  //当前页的记录, T 是为了方便将来复用
        private String url; // 表示 url 后面的条件!
    
        public int getPc(){
            return pc;
        }
        public void setPc(int pc){
            this.pc = pc;
        }
    
        // tp 是计算出来的
        public void getTp(){
            int tp = tr/ps;
            // 如果有余数, 总页数+1
            return tr/ps==0 ? tp : tp+1;
        }
    
        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> getBeanList(){
            return beanList;
        }
        public void setBeanList(List<T> beanList){
            this.beanList = beanList;
        }
    
        public String getUrl(){
            return url;
        }
        public void setTr(String url){
            this.url = url;
        }
    
    }
    

    4. 分页数据在各层的处理

    1. 页面: 显示分页相关的链接们!
      • 页面需要给 Servlet 传递当前页码
    2. Servlet: 创建 PageBean 对象, 给 PageBean 所有的属性赋值, 然后传递给页面.
      • Servlet 需要给 DAO 传递当前页码,以及每页记录数.
    3. Service: 中转站
    4. DAO
      • 获取总记录数 tr: SELECT COUNT(*) t_customer;
      • 获取当前页数据 BeanList: SELECT * FROM t_customer LIMIT x,y; limit 方言
        其中, x 表示从第几行开始查询, y 表示查询多少行.
    // CustomerServlet
        // 查询所有
        public String findAll(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException{
    
                // 使用 getPc 方法, 得到 pc
                int pc = getPc(request);
    
                // 给定 ps 的值, 每页10行
                int ps = 10;
    
                // 传递 pc, ps 给 service, 得到 PageBean
                PageBean<Customer> pb = customerService.findAll(pc,ps);
    
                // 保存到 request 域
                request.setAttribute("pb",pb);
    
                // 转发到 list.jsp
                return "f:/list.jsp";
        }
    
        // 从 request 域得到的 pc 为字符串, 需要转换成 int 类型
        private int getPc(HttpServletRequest request){
            String value = request.getParameter("pc");
    
            // 如果 pc 参数不存在, 说明 pc=1;
            // 如果 pc 参数存在, 转换成 int 类型
            if(value == null || value.trim().isEmpty()){
                return 1;
            }
    
            return Interger.parseInt(value);
        }
    
    // CustomerService
        public PageBean<Customer> findAll(int pc, int ps){
            return customerDao.findAll(pc,ps);
        }
    
    // CustomerDao
        public PageBean<Customer> findAll(int pc, int ps){
            try{
    
                PageBean<Customer> pb = new PageBean<Customer>();
    
                // 设置 pb 的 pc 和 ps的值
                pb.setPc(pc);
                pb.setPs(ps);
    
                // 得到 tr
                String sql = "SELECT COUNT(*) FROM t_customer";
    
                Number num = (Number)qr.query(sql, new ScalarHandler());
    
                int tr = num.intValue();
                pb.setTr(tr);
    
                // 得到 BeanList
                sql = "SELECT * FROM t_customer order by cname LIMIT ?,?";
    
                List<Customer> beanList = qr.query(sql,
                                new BeanListHandler<Customer>(Customer.class),
                                (pc-1)*ps,ps);
    
                pb.setBeanList(beanList);
                return pb;
            }catch(SQLException e){
                throw new RuntimeException(e);
            }
        }
    
    // list.jsp
        <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="${pb.beanList }" 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:froEach>
            </table>
            <br/>
    
            <%--给出分页相关的链接 --%>
            <center>
                第${pb.pc}页/共${pb.tp}页
                <a href="<c:url value='/CustomerSevlet?method=findAll&pc=1'/>">首页</a>
                <c:if test="${pb.pc > 1}">
                <a href="<c:url value='/CustomerServlet?method=findAll?pc=${pb.pc-1}'/>">上一页</a>
                </c:if>
                <c:if test="${pb.pc < pb.tp}">
                <a href="<c:url value='/CustomerServlet?method=findAll?pc=${pb.pc+1}'/>">下一页</a>
                </c:if>
                <a href="<c:url value='/CustomerServlet?method=findAll?pc=${pb.tp}'/>">尾页</a>
            </center>
        </body>
    

    5. 分页的页码列表

    5.1 需要关注的参数
    • 最多显示多少个页码, 定为 10 页;
    • 当前页, 在页码列表中的位置, 即居中显示, 定位 6;
    5.2 如何来确定页码列表
    • 需要当前页码, begin, end 三样数据.
    5.3 计算公式
    • 如果总页数 <= 10(列表长度), 那么 begin = 1, end = 总页数;
    • 使用公式计算: begin = pc -5, end = pc + 4;
    • 头溢出: 当 begin < 1 时, 让 begin = 1;
    • 尾溢出: 当 end > ${tp} 时, 让 end = ${tp};
    // list.jsp
        <body>
    
            <br/>
            <center>
                第${pb.pc}页/共${pb.tp}页
                <a href="<c:url value='/CustomerSevlet?method=findAll&pc=1'/>">首页</a>
                <c:if test="${pb.pc > 1}">
                <a href="<c:url value='/CustomerServlet?method=findAll?pc=${pb.pc-1}'/>">上一页</a>
                </c:if>
    
                <%-- 计算 begin 和 end --%>
                <c:choose>
                    <%-- 如果总页数不足 10 页, 那么把所有的页数都显示出来! --%>
                    <c:when test="${pb.tp <= 10}">
                        <c:set var="begin" value="1"/>
                        <c:set var="end" value="${pb.tp}"/>
                    </c:when>
                    <c:otherwise>
                        <%-- 当总页数 > 10 时, 通过公式计算出 begin 和 end --%>
                        <c:set var = "begin" value="${pb.pc - 5}"/>
                        <c:set var = "end" value="{pb.pc + 4}"/>
    
                        <%-- 头溢出 --%>
                        <c:if test="${begin < 1}">
                            <c:set var = "begin" value = "1"/>
                            <c:set var = "end" value="10"/>
                        </c:if>
    
                        <%-- 尾溢出 --%>
                        <c:if test="${end > pb.tp}">
                            <c:set var="begin" value="${pb.tp-9}"/>
                            <c:set var="end" value="${pb.tp }"/>
                        </c:if>
                    </c:otherwise>
                </c:choose>
    
                <%-- 循环遍历页码列表 --%>
                <c:forEach var="i" begin="${begin}" end="${end}">
                    <c:choose>
                        <c:when test="${i eq pb.pc}">
                            [${i }]
                        </c:when>
                        <c:otherwise>
                            <a href="<c:url value='/CustomerServlet?method=findAll&pc=${i}'/>">[${i}]</a>
                        </c:otherwise>
                    </c:choose>
                </c:forEach>
    
                <c:if test="${pb.pc < pb.tp}">
                <a href="<c:url value='/CustomerServlet?method=findAll?pc=${pb.pc+1}'/>">下一页</a>
                </c:if>
                <a href="<c:url value='/CustomerServlet?method=findAll?pc=${pb.tp}'/>">尾页</a>            
            </center>
        </body>
    

    6. 在超链接中保留参数

    • 当使用多条件查询时, 在点击第 2 页时, 这个第 2 页超链接没有条件了, 所以会丢失条件,
      我们需要在页码上的所有链接都要保留条件!!
    • 要保留的条件以一个字符串的形式保存到 PageBean 的 url 中, 这个操作交给 Servlet 处理.
    // CutomerServlet
        public String query(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException{
    
            // 把条件封装到 Customer 对象中
            Customer criteria = CommonUtils.toBean(request.getParameterMap(),Customer.class);
    
            // 得到 pc
            int pc = getPc(request);
    
            int ps = 10;
    
            // 使用 pc, ps 以及条件对象, 调用 service 方法得到 PageBean
            PageBean<Customer> pb = customerService.query(criteria, pc, ps);
    
            // 保存 url 到 pb
            pb.setUrl(gerUrl(request));
    
            // 保存到 request 域
            request.setAttribute("pb",pb);
    
            // 转发到 list.jsp
            return "f:/list.jsp";
        }
    
        // 截取 url
        //  request 域中的 url :  /项目名/Servlet 路径?参数字符串
        // 请求方式更改为 get 请求
        private String getUrl(HttpServletRequest request){
                String contextPath = request.getContextPath();
                String servletPath = request.getServletPath();
                String queryString = request.getQueryString();
    
                // 判断是否存在 pc, 存在的话, 需要去掉
                if(queryString.contains("&pc=")){
                    int index = queryString.lastIndexOf("&pc=");
                    queryString = queryString.substring(0,index);
                }
    
                return contextPath + servletPath +"?"+ queryString;
        }
    
    
    // CustomerService
        public PageBean<Customer> query(Customer criteria, int pc, int ps){
            return customerDao.query(criteria, pc, ps);
        }
    
    // customerDao
        public PageBean<Customer> query(Customer criteria, int pc, int ps){
    
            // 创建 pageBean 对象
            PageBean<Customer> pb = new PageBean<Customer>();
    
            // 设置 pc 和 ps
            pb.setPc(pc);
            pb.setPs(ps);
    
            // 得到 tr
    
            // 查询 tr 的 sql 语句前缀
            StringBuilder cntSql = new StringBuilder("SELECT COUNT(*) FROM t_customer");
            StringBuilder whereSql = new StringBuilder(" WHERE 1=1");
    
            // 创建一个 ArrayList, 用来装载参数
            List<Object> params = new ArrayList<Object>();
    
            String cname = criteria.getCanem();
            if(cname != null && !cname.trim().isEmpty()){
                whereSql.append(" AND cname like ?");
                params.add("%" + cname + "%");
            }
    
            String gender = criteria.getGender();
            if(gender != null && !gender.trim().isEmpty()){
                whereSql.append(" AND gender=?");
                params.add(gender);
            }
    
            String cellphone = criteria.getCellphone();
            if(cellphone != null && !cellphone.trim().isEmpty()){
                whereSql.append(" AND cellphone like ?");
                params.add("%" + cellphone + "%");
            }
    
            String email = criteria.getEmail();
            if(email != null && !email.trim().isEmpty()){
                whereSql.append(" AND email like ?");
                params.add("%"+ email + "%");
            }
    
            Number num = (Number)qr.query(cntSql.append(whereSql).toString(),
                                    new ScalarHandler(),params.toArray());
            int tr = num.intValue();
            pb.setTr(tr);
    
            // 得到 beanList
            StringBuilder sql = new StringBuilder("SELECT * FROM t_customer");
            StringBuilder limitSql = new StringBuilder(" LIMIT ?,?");
            params.add((pc-1)*ps);
            params.add(ps);
    
            List<Customer> beanList =
                                 qr.query(sql.append(whereSql).append(limitSql).toString(),
                                new BeanListHandler<Customer>(Customer.class), 
                                params.toArray());
    
            pb.setBeanList(beanList);
    
            return pb;
        }
    
    // list.jsp
        <body>
            <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: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>
            </center>        
        </body>
    

    参考资料:

  • 相关阅读:
    异常 中断 陷阱
    关于delete字符串 需不需要加 [ ]
    关于联合体输出的问题(是否小端模式)
    String reorder
    数据库 ---5 索引 创建用户及授权 数据备份
    数据库 --- 4 多表查询 ,Navicat工具 , pymysql模块
    数据库 --- 3 行(记录)操作 单表查询
    数据库 --- 2 库 ,表
    数据库 --- 1 初始 数据库
    并发 --- 5 线程的其他方法 线程队列 线程池 协程
  • 原文地址:https://www.cnblogs.com/linkworld/p/7633089.html
Copyright © 2011-2022 走看看