继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

客户关系管理系统(2)

Java3y
关注TA
已关注
手记 297
粉丝 1.5万
获赞 6488
改善显示页面

现在问题来了,如果我们客户信息有非常非常地多,我们不可能把客户信息全部都挤在同一个页面上,如果我们这样做的话,网页的长度就会非常的长!

于是乎,我们就需要用到了分页的技术,对于分页技术基础的讲解,在我另一篇博文中有介绍: https://zhongfucheng.bitcron.com/post/jdbc/jdbcdi-si-pian-shu-ju-ku-lian-jie-chi-dbutilskuang-jia-fen-ye

看完上篇博文,我们知道,首先要做的就是:明确分页技术中需要用到的4个变量的值!

查询总记录数

查询总记录数也就是查询数据库表的记录有多少条,这是关于对数据库数据的操作,所以肯定是在dao层做!


    public Long getTotalRecord() {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM customer";

        try {
            //获取查询的结果
            Long l = (Long) queryRunner.query(sql, new ScalarHandler());
            return l;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查询总记录数失败了!");
        }

    }
查询分页的数据

获取分页的数据也是查询数据库的记录,这也是关于对数据库的操作,所以也是在Dao层做的!


    /*查询分页数据*/
    //获取分页的数据是需要start和end两个变量的【从哪条开始取,取到哪一条】
    public List<Customer> getPageData(int start, int end) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM customer LIMIT ?,?";

        try {
            List<Customer> customers = (List<Customer>) queryRunner.query(sql, new BeanListHandler(Customer.class), new Object[]{start, end});

            return customers;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("获取分页数据失败了!");
        }
    }
分析

现在我们已经可以知道总记录数了,对于其他3个变量(每页显示记录数【由程序员来指定】,当前是多少页【由用户来指定】,总页数【由总记录数和每页显示记录数来算数来的】)

现在要分析的是,这些变量应该放在哪里呢???全部放在Dao层??全部放在Dao层是可以实现功能的,但是,这样MVC结构就被破坏掉了(Dao层只用来对数据进行CRUD操作,4个变量存在Dao层,是不合理的)

最好的做法是这样的:创建一个实体Page,将分页用到的信息全部封装在Page中实现!Page就代表着分页的数据这样就非常符合面向对象的思想了!

将数据封装到Page中并在页面上显示分页的数据

①:创建Page类


    //保存着分页的数据
    private List<Customer> list;

    //总记录数
    private long totalRecord;

    //每页显示记录数,这里我规定每页显示3条
    private int linesize = 3;

    //总页数
    private int totalPageCount;

    //当前显示的页数
    private long currentPageCount;

    //...各种的setter、getter

②:BusinessService应该提供获取分页数据的服务


    //既然Page对象代表是分页数据,那么返回Page对象即可!
    //web层应该传入想要看哪一页数据的参数!
    public Page getPageData(String currentPageCount) {

        Page page = new Page();

        //获取数据库中有多少条记录,并封装到Page对象中
        Long totalRecord = customerDao.getTotalRecord();
        page.setTotalRecord(totalRecord);

        //算出总页数,并封装到Page对象中
        int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
        page.setTotalPageCount(totalPagecount);

        int start ;
        int end = page.getLinesize();

        //现在又分两种情况了,如果传递进来的参数是null的,那么说明外界是第一次查询的
        if (currentPageCount == null) {

            //第一次查询,就应该设置当前页数是第一页
            page.setCurrentPageCount(1);

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);
        } else {

            //如果不是第一次,就把外界传递进来的页数封装到Page对象中
            page.setCurrentPageCount(Long.parseLong(currentPageCount));

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);

        }
        return page;

    }

③:web层调用BusinessService层的功能,获取得到Page对象


        //获取用户想要看的页数,如果是第一次,那肯定为null
        String currentPageCount = request.getParameter("currentPageCount");

        //调用BusinessService的方法,获取得到所有客户信息
        BusinessService businessService = new BusinessService();
        Page page  = businessService.getPageData(currentPageCount);

        //把客户信息带过去给jsp页面
        request.setAttribute("page", page);

        //跳转到显示客户界面信息的jsp
        request.getRequestDispatcher("/WEB-INF/lookCustomer.jsp").forward(request, response);

④:在JSP页面中,使用EL表达式获取到Page对象,从而输出数据


        <c:forEach items="${page.list}" var="customer">
            <tr>
                <td>${customer.name}</td>
                <td>${customer.gender}</td>
                <td>${customer.birthday}</td>
                <td>${customer.cellphone}</td>
                <td>${customer.email}</td>
                <td>${customer.preference}</td>
                <td>${customer.type}</td>
                <td>${customer.description}</td>
            </tr>
        </c:forEach>

⑤:在JSP页面中显示页码,同时把码数绑定到超链接去!


    <%--提供页数的界面--%>
    <c:forEach var="pageNum" begin="1" end="${page.totalPageCount}">
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${pageNum}">
            ${pageNum}
        </a>
    </c:forEach>
  • 效果:


让分页的功能更加完善

增加上一步和下一步

一般的分页不仅仅只有页码给你,还有上一步和下一步。我们在JSP页面上也能添加这样的功能,其实这是非常简单的!


    <%--如果当前的页码大于1,才显示上一步--%>
    <c:if test="${page.currentPageCount>1}">

        <%--把传递过去的页码-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount-1}">
            上一步
        </a>
    </c:if>

    <%--如果当前的页码小于总页数,才显示下一步--%>
    <c:if test="${page.currentPageCount<page.totalPageCount}">

        <%--把传递过去的页码-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}">
            下一步
        </a>
    </c:if>
  • 效果:


显示当前页数,总页数,总记录数


    当前页数是:[${page.currentPageCount}]&nbsp;&nbsp;&nbsp;

    总页数是:${page.totalPageCount}&nbsp;&nbsp;

    总记录数是:${page.totalRecord}
  • 效果:


跳转到某页上


    <input type="text" id="currentPageCount">
    <input type="button" value="跳转">
  • 页面效果:

我们现在要做的就是:怎么样才能输入框输入内容,然后点击跳转按钮,将输入框的数据发送到Servlet上,然后实现跳转到某页上功能

明显地,我们肯定要使用JavaScript代码!


<script type="text/javascript">

    /*既然写上了JavaScript代码了,就顺便验证输入框输入的数据是否合法吧*/
    function goPage() {

        /*获取输入框控件*/
        var input = document.getElementById("currentPageCount");

        /*获取输入框的数据*/
        var value = input.value;

        if(value==null || value==""){
            alert("请输入页码");
            return false;
        }

        if(!value.match("\\d+")){
            alert("请输入数字");
            return false;
        }

        if(value<1 || value>${page.totalPageCount}){
            alert("请输入合法数据");
            return false ;
        }

        window.location.href="${pageContext.request.contextPath}/LookCustomer?currentPageCount="+value;
    }

</script>
  • 效果:


记录JSP页面的开始页和结束页

为什么我们要记录JSP页面的开始页和结束页呢?经过上面层层地优化,我们感觉不出有什么问题了。那是因为数据量太少!

我们试着多添加点记录进数据库,再回来看看!

从上面的图我们可以发现页数有多少,JSP页面就显示多少!这明显不合理的,如果有100页也显示100页吗?

我们做一个规定,一次只能显示10页的数据。那么显示哪10页呢?这又是一个问题了,如果我们在看第11页的数据,应该显示的是第7到第16页的数据(显示11附近的页数),我们在看第2页的数据,应该显示第1到第10页的数据。用户想要看的页数是不明确的,我们显示附近的页数也是不明确的!我们应该把用户想要看的页数记录下来,然后根据逻辑判断,显示附近的页数

我们显示页数的代码是这样的:

很明显,我们只要控制了begin和end中的数据,就控制显示哪10页了!

①在Page类中多定义两个成员变量


    //记录JSP页面开始的页数和结束的页数
    private int startPage;
    private int endPage;

    //Setter,Getter方法

②开始页数和结束页数受用户想看的页数影响,在BusinessService的getPageData()加入下面的逻辑


            //第一次访问
            page.setStartPage(1);
            page.setEndPage(10);

            //不是第一次访问
            if (page.getCurrentPageCount() <= 10) {
                page.setStartPage(1);
                page.setEndPage(10);
            } else {
                page.setStartPage((int) (page.getCurrentPageCount() - 4));
                page.setEndPage((int) (page.getCurrentPageCount() + 5));

                //如果因为加减角标越界了,那么就设置最前10页,或者最后10页
                if (page.getStartPage() < 1) {
                    page.setStartPage(1);
                    page.setEndPage(10);
                }
                if (page.getEndPage() > page.getTotalPageCount()) {
                    page.setEndPage(page.getTotalPageCount());
                    page.setStartPage(page.getTotalPageCount() - 9);
                }
            }

③:在JSP显示页数时,获取得到开始页和结束页就行了


    <%--提供页数的界面--%>
    <c:forEach var="pageNum" begin="${page.startPage}" end="${page.endPage}">
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${pageNum}">
                [${pageNum}]&nbsp;
        </a>
    </c:forEach>
  • 效果:



重构优化
分页重构

我们再回头看看BusinessService中获取分页数据的代码:


    //既然Page对象代表是分页数据,那么返回Page对象即可!
    //web层应该传入想要看哪一页数据的参数!
    public Page getPageData(String currentPageCount) {

        Page page = new Page();

        //获取数据库中有多少条记录,并封装到Page对象中
        Long totalRecord = customerDao.getTotalRecord();
        page.setTotalRecord(totalRecord);

        //算出总页数,并封装到Page对象中
        int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
        page.setTotalPageCount(totalPagecount);

        int start ;
        int end = page.getLinesize();

        //现在又分两种情况了,如果传递进来的参数是null的,那么说明外界是第一次查询的
        if (currentPageCount == null) {

            //第一次查询,就应该设置当前页数是第一页
            page.setCurrentPageCount(1);

            page.setStartPage(1);
            page.setEndPage(10);

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);
        } else {

            //如果不是第一次,就把外界传递进来的页数封装到Page对象中
            page.setCurrentPageCount(Long.parseLong(currentPageCount));

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            if (page.getCurrentPageCount() <= 10) {
                page.setStartPage(1);
                page.setEndPage(10);
            } else {
                page.setStartPage((int) (page.getCurrentPageCount() - 4));
                page.setEndPage((int) (page.getCurrentPageCount() + 5));

                //如果因为加减角标越界了,那么就设置最前10页,或者最后10页
                if (page.getStartPage() < 1) {
                    page.setStartPage(1);
                    page.setEndPage(10);
                }
                if (page.getEndPage() > page.getTotalPageCount()) {
                    page.setEndPage(page.getTotalPageCount());
                    page.setStartPage(page.getTotalPageCount() - 9);
                }
            }

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);

        }
        return page;

    }

太太太太太tm复杂,太太太太tm长了!!!!!我们BusinessService要做的仅仅是调用Dao层的功能,为web层提供数据,但我们在方法中使用大量了逻辑判断,而且这些逻辑判断都是属于Page类的!

明确一下:只有获取数据库总记录数是在BusinessService中做的,其他的数据变量都是应该在Page类中完成!

在BusinessService获取了总记录数之后,我们要对其他变量进行初始化(根据总记录数,用户想要看哪一页的数据),算出其他的数据(JSP记录开始页数、结束页数、总页数等等),最好的办法就是通过Page的构造函数来实现初始化!

  • 改良后的BusinessService

    
    
    public Page getPageData2(String currentPageCount) {
    
        //获取得到总记录数
        Long totalPageCount = customerDao.getTotalRecord();
    
        if (currentPageCount == null) {
    
            //如果是第一次,那么就将用户想看的页数设置为1
            Page page = new Page(1, totalPageCount);
    
            List<Customer> customers = customerDao.getPageData(page.getStartIndex(), page.getLinesize());
    
            page.setList(customers);
            return page;
    
        } else {
    
            //如果不是第一次,就将获取得到的页数传递进去
            Page page = new Page(Integer.parseInt(currentPageCount), totalPageCount);
    
            List<Customer> customers = customerDao.getPageData(page.getStartIndex(), page.getLinesize());
    
            page.setList(customers);
            return page;
        }
    }

- **改良后的Page类(原来的Page类只有成员变量和setter、getter方法)**

```java

    public Page(int currentPageCount, long totalRecord) {

        //将传递进来的currentPageCount初始化
        this.currentPageCount = currentPageCount;

        //总页数
        totalPageCount = (int) (totalRecord % linesize == 0 ? totalRecord / linesize : totalRecord / linesize + 1);

        //总记录数
        this.totalRecord = totalRecord;

        //开始取数据的位置
        startIndex = (currentPageCount - 1) * linesize;

        //如果当前页小于10,那么开始页为1,结束页为10就行了
        if (this.currentPageCount <= 10) {
            this.startPage = 1;
            this.endPage = 10;
        } else {
            startPage = this.currentPageCount - 4;
            endPage = this.currentPageCount + 5;

            //加减后页数越界的情况
            if (startPage < 1) {
                this.startPage = 1;
                this.endPage = 10;
            }
            if (endPage > totalPageCount) {
                this.startPage = this.currentPageCount - 9;
                this.endPage = this.totalPageCount;
            }
        }

    }
分页显示页面重构

分页的显示页面都是永恒不变的,我们可以把代码重构成一个jsp,需要用到分页显示页面的地方,就包含进去就行了!

  • page.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--显示当前页数--%>
    当前页数是:[${page.currentPageCount}]&nbsp;&nbsp;&nbsp;

    <%--如果当前的页码大于1,才显示上一步--%>
    <c:if test="${page.currentPageCount>1}">

        <%--把传递过去的页码-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount-1}">
            上一步
        </a>
    </c:if>

    <%--提供页数的界面--%>
    <c:forEach var="page" begin="${page.startPage}" end="${page.endPage}">
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page}">
            [${page}]&nbsp;
        </a>
    </c:forEach>

    <%--如果当前的页码小于总页数,才显示下一步--%>
    <c:if test="${page.currentPageCount<page.totalPageCount}">

        <%--把传递过去的页码-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}">
            下一步
        </a>&nbsp;&nbsp;
    </c:if>

    <input type="text" id="currentPageCount">
    <input type="button" value="跳转" onclick="goPage()">

    总页数是:${page.totalPageCount}&nbsp;&nbsp;

    总记录数是:${page.totalRecord}

    <script type="text/javascript">

        /*既然写上了JavaScript代码了,就顺便验证输入框输入的数据是否合法吧*/
        function goPage() {

            /*获取输入框控件*/
            var input = document.getElementById("currentPageCount");

            /*获取输入框的数据*/
            var value = input.value;

            if(value==null || value==""){
                alert("请输入页码");
                return false;
            }

            if(!value.match("\\d+")){
                alert("请输入数字");
                return false;
            }

            if(value<1 || value>${page.totalPageCount}){
                alert("请输入合法数据");
                return false ;
            }

            window.location.href="${pageContext.request.contextPath}/LookCustomer?currentPageCount="+value;
        }

    </script>

用需要用到的地方,导入即可!


    <jsp:include page="page.jsp"></jsp:include>

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP