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>
    

    参考资料:

  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/linkworld/p/7633089.html
Copyright © 2011-2022 走看看