JavaWeb笔记-20-客户管理案例之分页进阶、分页组合

1、分页:


原理:利用sql语句中的方言:limit x , y   从x行开始查,查y行   

优点:每次只查询部分,不用查询所有

2、数据的传递:


分页数据们需要在各层之间来回的传递!

为了提升效率,将所有分页数据装进JavaBean中,起名为分页bean。
构成一个JavaBean对象,数据传递时传输该对象即可。
    PageBean: 
    public class PageBean<T> {
        private int pc; // 当前页码
        private int tp; // 总页数  //不允许设置,需要通过计算获得  在get方法中计算.
        private int tr; // 总记录数
        private int ps; // 每页记录数
        private List<T> beanList; // 当前页的记录

        private String url; //用来表示url后的参数条件
    }

3、页面数据:


页面数据都是由Servlet传递过来的。

Servlet需要的数据:
    当前面:pageCode,pc;
        pc:1)如果页面没有传递当前页码,那么Servlet默认是第一页,
            2)按页面传递的页码为准!
    总页数:totalPages,tp
        tp:总记录数(tr)/每页记录数(ps)

        总记录数:totalRecored,tr
            tr:dao来获取,select count(*) from t_customer;
        每页记录数:业务数据或叫系统数据!10行! (ps)

    当前页数据:beanList

    url  //用来代表超链接后参数条件

4、分页在各层中的处理


页面:给出分页相关的所有链接
Servlet:创建PageBean对象,给PageBean所有属性赋值,传递给页面。
    servlet需要给DAO传递 pc 、ps

service:略
Dao: 
    tr: select count(*)...
    beanList:select * from t_customer limit x.y; (从x行开查询,查y行)

这里写图片描述

5、显示页码列表


1)需要计算出页码列表的起始位begin和终止位end,
2)动态显示出从begin到end范围内的页码数字
3)对页码加上超链接

 1 2 3 4 5 (6) 7 8 9 10    括号内为当前页

需要设置:
1)最多显示多少个页码! 现定为10;
2)当前页,在页码列表中的位置,定为6;


页码列表计算:
    思路:使用当前页码来推算出前后页

需要两样数据:
    begin
    end

    10 11 12 13 14 (15) 16 17 18 19
    需要使用pc来推算出begin和end
    begin = pc – 5
    end = pc + 4

计算公式:
    1)总页数 <= 10(列表长度),那么begin=1,end=总页数

2)总页数 > 10 
使用公式计算;begin=pc-5, end=pc + 4;
头溢出:当begin<1时,让begin=1
尾溢出:当end>${tp}时,让end=${tp}

6、分页之查询条件丢失问题


问题介绍:当使用多条件查询后,再点击第 2 页时,第 2 页超链接条件会发生丢失。

为了正常使用,在超链接中要保留参数

解决:1)把条件以字符串的形式保存到PageBean的url中。
      2)在servlet中截取字符串。


问题:post请求不能传递参数,导致参数不能直接获取
解决:将post改为get

    问题:改为get后需要手动处理get请求编码问题。post方式在BaseServlet中已被自动处理过。
    解决:手动挨个设置get方法携带的参数。

url中截去pc的目的: pc是个变量,不能被固定。

servlet

1)//分页查询所有客户
    public String findAll(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /*
         * 1.获取页面传递的pc
         *      pc不存在,默认为首页  pc=1
         *      存在,将字符串参数转为int型
         * 2.给定ps的值  
         * 3.使用pc和ps调用service方法,得到PageBean,保存到request中
         * 4.转发到list.jsp中.
         */

        //1.得到pc  使用下面方法.
        int pc = getPc(request);

        //2.给定ps的值
        int ps = 10;  //每页十条记录

        //3.使用pc和ps调用service方法,得到PageBean,
        PageBean<Customer> pb = customerService.findAll(pc,ps);

        //设置URL
        pb.setUrl(getUrl(request));

        //保存到request中
        request.setAttribute("pb", pb);

        return "f:/list.jsp";   
    }

    //得到pc方法
    private int getPc(HttpServletRequest request){
        String value = request.getParameter("pc");
        if(value == null || value.trim().isEmpty()){
            return 1;
        }
        return Integer.parseInt(value);
    }
2)//分页组合查询
        public String query(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 获取查询条件,把条件封装到Custome对象中.
            Customer criteria = CommonUtils.toBean(request.getParameterMap(), Customer.class);

            //处理GET请求编码
             criteria = encoding(criteria);

            //得到pc
            int pc = getPc(request);

            //给定ps.
            int ps = 10; //表示每页10行记录  

            //使用pc和ps,条件对象,调用service方法得到PageBean
            PageBean<Customer> pb = customerService.query(criteria,pc,ps);

            //设置URL
            pb.setUrl(getUrl(request));
            //把PageBean保存到request中,以便输出
            request.setAttribute("pb", pb);

            //转发
            return "f:/list.jsp";
        }

        //处理GET请求编码方法
        private Customer encoding(Customer criteria) throws UnsupportedEncodingException {
            String cname = criteria.getCname();
            String gender = criteria.getGender();
            String cellphone = criteria.getCellphone();
            String email = criteria.getEmail();
            if(cname != null && !cname.trim().isEmpty()){
                cname = new String (cname.getBytes("ISO-8859-1"),"utf-8");
                criteria.setCname(cname);
            }
            if(gender != null && !gender.trim().isEmpty()){
                gender = new String (gender.getBytes("ISO-8859-1"),"utf-8");
                criteria.setGender(gender);
            }
            if(cellphone != null && !cellphone.trim().isEmpty()){
                cellphone = new String (cellphone.getBytes("ISO-8859-1"),"utf-8");
                criteria.setCellphone(cellphone);
            }
            if(email != null && !email.trim().isEmpty()){
                email = new String (email.getBytes("ISO-8859-1"),"utf-8");
                criteria.setEmail(email);
            }   
            return criteria;
        }


        /**
         * 截取url
         *      /项目名/Servlet路径?参数字符串
         * @param request
         * @return
         */
        private String getUrl(HttpServletRequest request){


            //得到项目名
            String contextPath = request.getContextPath();
            //得到Servlet路径
            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;
        }

CustomerDao

1)  //分页查詢所有客戶
    public PageBean<Customer> findAll(int pc, int ps){  //返回值为
        try{
            /*  
             * 创建PageBean对象pb      用来装载数据,方便页面间传送
             * 设置pb的pc和ps         给pb设置当前页码和当前页的记录数
             * 得到tr,设置给pb      得到总记录数,用来计算共用有多少页
             * 通过查询得到beanList    设置给pb
             * 返回pb
             */
            PageBean<Customer> pb = new PageBean<Customer>();
            pb.setPc(pc); //设置pb的pc和ps
            pb.setPs(ps);

            //得到tr(总记录数)
            String sql = "select count(*) from t_customer"; 
            //查询返回结果为Object  需要用Number接收,然后转为int 
            Number num = (Number)qr.query(sql, new ScalarHandler());
            int tr = num.intValue();
            pb.setTr(tr);

            //得到beanList   beanList是用来存储多个JavaBean的集合 
            //使用方言查询  ,  得到每页数据的集合
            sql = "select * from t_customer limit ?,?";
            List<Customer> beanList = qr.query(sql, 
                    new BeanListHandler<Customer>(Customer.class),
                    (pc-1)*ps,ps);
            pb.setBeanList(beanList);  //将当前页记录设置给pb
            return pb;
        }catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
2)//分页组合查询
        public PageBean<Customer> query(Customer criteria, int pc, int ps) {
            try{
                //创建PageBean对象
                PageBean<Customer> pb = new PageBean<Customer>();

                //设置已有属性pc,ps
                pb.setPc(pc);
                pb.setPs(ps);

        //得到tr   此时的tr为条件删选后的tr(先查询,将查询结果通过Number返回为int类型)
                //做法:
                    //给出sql模板   
                    //先给出sql前缀  (拆分给出,方便下面得到BeanList时复用)
                StringBuilder cntSql = new StringBuilder("select count(*) from t_customer");
                StringBuilder whereSql = new StringBuilder(" where 1=1");   
                    //判断条件,向sql中追加where子句.
                //给出参数,无法统一确定有几个参数,所以需要在添加条件时,直接赋值
                //有几个问号就有几个参数,
                //创建一个ArrayList对象集合,用来装载参数值.(有几个装几个)s
                List<Object> params = new ArrayList<Object>();
                String cname = criteria.getCname();
                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
            int tr = num.intValue();
            pb.setTr(tr);

        //得到beanList
            //先给出前缀
        StringBuilder sql = new StringBuilder("select * from t_customer");
            //给出limit子句.
        StringBuilder limitSql = new StringBuilder(" limit ?,?");
            //params中需要给出limit中两个问号的参数
        params.add((pc-1)*ps);
        params.add(ps);
            //执行查询得到beanList
        List<Customer> beanList = qr.query(sql.append(whereSql).append(limitSql).toString(), 
                new BeanListHandler<Customer>(Customer.class),
                params.toArray());

        //设置BeanList
        pb.setBeanList(beanList);

        return pb;  //pb携带pc ps tr beanList返回
            }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=loadForEdit&cid=${cstm.cid }'/>">编辑</a>
            <a href="<c:url value='/CustomerServlet?method=delete&cid=${cstm.cid }'/>">删除</a>
        </td>
    </tr>
</c:forEach>
</table>
<br/>

<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:choose>
    <%-- 1)总页数 <= 10(列表长度),那么begin=1end=总页数 --%>
    <c:when test="${pb.tp <= 10 }">
        <c:set var="begin" value="1" />
        <c:set var="end" value="${pb.tp }" />
    </c:when>

    <%-- 2)总页数 > 10 ,通过公式计算出begin, end --%>
    <c:otherwise>
        <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="${pb.url }&pc=${i } "> ${i }</a>
        </c:otherwise>
    </c:choose> 
</c:forEach>




<c:if test="${pb.pc < pb.tp }">
    <a href="${pb.url }&pc=${pb.pc+1}">下一页</a>
</c:if>
    <a href="&pc=${pb.tp } ">尾页</a>

</center>
 </body>

猜你喜欢

转载自blog.csdn.net/qq_41307491/article/details/81591185