Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 245|回复: 0

[jsp学习]构建自己的通用分页组件(2)

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-2 13:36:41 | 显示全部楼层 |阅读模式
    1. 需求:    在前一篇文章中,我们通过分析常见的分页需求,构建了一个通用的分页类Page和页面范围类PageScope,在此基础上完成了分页查询的前后台交互。但是取得当前页面的数据及其他分页页码信息后,最终还是要展示到页面上。

        一种常用的方法就是将分页查询后返回的page对象传递给页面,页面通过一些判断逻辑来进行相应的展示。但是这种方式不方便复用,即使将其单独独立出来,并在需要分页的页面分别导入,也不是很好的做法,因为在页面中写判断逻辑总是不太合适的。
        本文将以Jsp为例,使用Jsp的自定义标签,来实现一个页面分页标签处理程序,最终使得在需要分页的页面中能够简单、容易的复用。
    2. 设计:
        首先我们来预览一下我们需要实现的功能,如下图:
      
       
       
         
       

         
       
      
           为使设计更加灵活,从上述图片中,我们可以将这新展示内容抽象为:首页、末页、上一页、下一页、当前页、当前页之前的页数、当前页之后的页数、页码的链接地址、展示样式、分页信息等。而且,我们希望这些参数可由调用者自由设置,并根据调用者提供的参数不同,进行不同的展示,譬如:

        根据这种实际需求,我们在PageTag类中定义如下属性: public class PageTag extends TagSupport {
        private static final long serialVersionUID = 3441235160861303080L;
        // 首页
        private String homePage;
        // 末页
        private String lastPage;
        // 上一页
        private String previousPage;
        // 当前页之前的页数,默认为4。
        private int beforeNum = 4;
        // 当前页之后的页数,默认为5。
        private int afterNum = 5;
        // 分页对象
        private Page page;
        // 链接地址
        private String url;
        // 下一页
        private String nextPage;
        // 当前页码
        private String pageIndex;
        // 页面大小
        private String pageSize;
        // 外层div样式
        private String divClass;
        // 是否进行动态补足,默认为true。
        private boolean supplement = true;
    }[/code]    从上面的代码中可以看出,除了我们之前描述的需求外,我还定义了当前页码和页面大小的Url参数,这样做是为了可以在用户给定的Url后面动态加上当前页面页码及页面大小的参数。比如:用户设定的url链接为http://www.javaeye.com/,那么添加参数后的动态url为http://www.javaeye.com/admin/blogs/677469/?pageIndex=6&pageSize=15。另外,细心的读者还会发现,我们还定义了一个名为supplement的boolean型属性,用以标识是否对设定的当前页面之前和之后的页数进行动态补足。比如说:总页数为15页,当前为第2页,设定当前页之前显示4个页码,当前页之后显示5个页码,供10个页码。若不进行动态补足,将显示:1 2 3 4 5 6 7这些页码,但若进行动态补足,由于前面页码不足,将从后面进行补充,反之亦然,那么补足后显示的页码将为:1 2 3 4 5 6 7 8 9 10。 3. 实现:
        通过上面的分析和设计,下面我们继承Jsp提供的自定义标签TagSupport来实现自定义我们的分页标签PageTag。通过重写父类TagSupport的doStartTag()和doEndTag()方法,并在此方法中实现分页处理逻辑。 /**
    * 标签处理开始,构造一个存放分页信息的字符串缓冲区。
    * @return SKIP_BODY,忽略标签之间的内容。
    * @throws javax.Servlet.jsp.JspException Jsp异常。
    */
    @Override
    public int doStartTag() throws JspException {
        buff = new StringBuilder();
        return SKIP_BODY;
    }
    /**
    * 标签实际分页处理逻辑。
    * @return EVAL_PAGE,按正常的流程继续执行Jsp页面。
    * @throws javax.servlet.jsp.JspException Jsp异常。
    */
    @Override
    public int doEndTag() throws JspException {
        if (page == null) {
            log.info("page is null.");
            return EVAL_PAGE;
        }
        // 写入开始DIV
        writeBeginDiv();
        // 写入分页信息
        writePageInfo();
        // 写入结束DIV
        writeEndDiv();
        // 记录日志
        writeDebugLog();
        // 输出到页面
        printToPage();
        return EVAL_PAGE;
    }[/code]     然后我们在分别完成各个子方法的实现即可。下面略举一二,最后将所有代码一并奉上。 /**
    * 写入实际的分页信息。
    * 调用者可自行设定是否显示首页、末页、上一页、下一页
    * 以及当前页面之前和之后的页数、是否进行动态补足等。
    */
    private void writePageInfo() {
        int beforeCount = countBefore();
        int afterCount = countAfter();
        // 如果定义了动态补足,则对当前页之前和之后的页数进行动态补足。
        if (supplement) {
            beforeCount = fixBeforeCount(beforeCount, afterCount);
            afterCount = fixAfterCount(beforeCount, afterCount);
        }
        int index = page.getPageIndex();
        // 首页
        writeHomePage(index);
        // 上一页
        writePreviousPage(index);
        // 当前页之前的页码
        writeBeforePageIndex(index, beforeCount);
        // 当前页
        writeCurrentPageIndex(index);
        // 当前页之后的页码
        writeAfterPageIndex(index, afterCount);
        // 下一页
        writeNextPage(index);
        // 末页
        writeLastPage(index);
    }[/code] /**
    * 计算当前页之前的页数。
    * @return 当前页之前的页数。
    */
    private int countBefore() {
        int beforeCount = 0;
        if (page.getPageIndex() - 1 > beforeNum) {
            beforeCount = beforeNum;
        } else {
            beforeCount = page.getPageIndex() - 1;
        }
        return beforeCount;
    }[/code] /**
    * 动态补足当前页之前的页数。
    * @param beforeCount 当前页之前的页数。
    * @param afterCount 当前页之后的页数。
    * @return 修正后的当前页之前的页数。
    */
    private int fixBeforeCount(int beforeCount, int afterCount) {
        int totalNum = beforeNum + afterNum + 1;
        int useNum = beforeCount + afterCount + 1;
        if (useNum < totalNum) {
            int befores = page.getPageIndex() - 1;
            int margin = befores - beforeCount;
            if (margin > 0) {
                int needNum = totalNum - useNum;
                beforeCount += margin > needNum ? needNum : margin;
            }
        }
        return beforeCount;
    }[/code] /**
    * 写入首页信息,如果设定了显示首页。
    * @param index 当前页码。
    */
    private void writeHomePage(int index) {
        if (homePage == null || homePage.isEmpty()) {
            return;
        }
        buff.append(LABEL_START);
        int homeIndex = 1;
        if (index > homeIndex) {
            writeUrlPageIndex(homeIndex, page.getPageSize(), homePage);
        } else {
            buff.append(homePage);
        }
        buff.append(LABEL_END);
    }[/code] /**
    * 写入当前页之前的页码。
    * @param index 当前页码。
    * @param beforeCount 前页之前的页数。
    */
    private void writeBeforePageIndex(int index, int beforeCount) {
        int beginIndex = index - beforeCount < 0 ? 1 : index - beforeCount;
        for (int i = beginIndex; i < index; i++) {
            buff.append(LABEL_START);
            writeUrlPageIndex(i, page.getPageSize(), String.valueOf(i));
            buff.append(LABEL_END);
        }
    }[/code] /**
    * 将分页信息输入到页面上。
    */
    private void printToPage() {
        try {
            pageContext.getOut().write(buff.toString());
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
        }
    }[/code] 4. 测试:
        针对此分页标签的实现,写了一个简单的测试代码来测试其正确性,如下: public class PageTagTest {
        @Test
        public void writePage() throws JspException {
            PageTag instance = new PageTag();
            Page page = new Page(7, 10);
            page.setTotalData(75);
            instance.setPage(page);
            instance.setDivClass("divClass");
            instance.setHomePage("首页");
            instance.setLastPage("末页");
            instance.setPreviousPage("上一页");
            instance.setNextPage("下一页");
            instance.setPageIndex("page");
            instance.setBeforeNum(4);
            instance.setAfterNum(5);
            instance.setSupplement(false);
            instance.setUrl("http://zhangshixi.javaeye.com");
            instance.doStartTag();
            instance.doEndTag();
        }
    }[/code]    最终写入到Jsp页面的内容如下: <div class="divClass">
        <label><a href="http://zhangshixi.javaeye.com?page=1">首页</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=6">上一页</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=3">3</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=4">4</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=5">5</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=6">6</a></label>
        <span>7</span>
        <label><a href="http://zhangshixi.javaeye.com?page=8">8</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=9">9</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=10">10</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=11">11</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=12">12</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=8">下一页</a></label>
        <label><a href="http://zhangshixi.javaeye.com?page=12">末页</a></label>
    </div>[/code]    限于篇幅,这里仅略举一例,当然,你也可写通过修改测试代码,来测试更多参数组合。至于在页面的最终展示样式,您可通过在外部css中,提供一个外层div的样式divClass来自行设定。在上传的代码中我会上传一个css的样式定义,来实现像本文开始时提供的效果,仅供参考,读者可在自己实际的项目中自行实现。
    5. 如何使用?
        好了,通过上面的说明,我们已经详细介绍了分页标签的设计及实现,那么我们究竟如何将其使用在页面中呢?下面我讲意义说明:
    首先,我们需要对自定义标签处理程序提供一个page-tag.tld配置文件,它定义了该标签的使用规则,参数规范等。如: <?xml version="1.0" encoding="UTF-8"?>
    <taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
        <tlib-version>1.0</tlib-version>
        <short-name>util</short-name>
        <uri>http://www.codingfarmer.com/tags</uri>
        <tag>
            <description>分页标签</description>
            <name>page</name>
            <tag-class>com.codingfarmer.util.page.PageTag</tag-class>
            <body-content>empty</body-content>
            <attribute>
                <description>首页</description>
                <name>homePage</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
                <type>java.lang.String</type>
            </attribute>
            <attribute>
                <description>分页对象</description>
                <name>page</name>
                <required>true</required>
                <rtexprvalue>true</rtexprvalue>
                <type>com.codingfarmer.util.page.Page</type>
            </attribute>
            ........
        </tag>
    </taglib>  [/code]    限于篇幅,上面只略举了两个属性的定义,其余原理同上。在上传的源码中会有详细的配置,请下载参考。
        其次,在定义好自定义标签的配置文件后,我们还需要在web.xml中引入,如将去放到WEB-INF下,并在web.xml中配置如下: <jsp-config>
        <taglib>
            <taglib-uri>pageTag</taglib-uri>
            <taglib-location>/WEB-INF/page-tag.tld</taglib-location>
        </taglib>
    </jsp-config>[/code]     最后,在需要分页的页面中我们可以插入以下代码,并根据实际需要设置相应的属性即可,如: // 引入page-tag.tld文件的定义
    <%@ taglib uri=" http://www.codingfarmer.com/tags" prefix="util" %>
    // 分页显示
    <util:page url="http://zhangshixi.javaeye.com" page="$ {page}"
               pageIndex=”pageIndex” homePage=”首页” lastPage=”末页”
               previousPage="Previous" nextPage="Next" className="pageNav" />[/code]    最终在页面上生成的分页效果为:  
    6. 相关说明:
        至此,我们已经完成了一个通用的分页组件的设计与实现,这样,我们就可以将其收录到自己的工具箱中,使用时在项目中引入即可,从而大大简化了分页的处理及展示,也达到了良好的复用,简化了维护。
        下面上传的压缩包中,包含了自定义分页标签处理程序,测试类,还提供了一个仅供参考的css分页样式定义。还望大家哪呢个提出更好的建议和意见,以便改进,不胜感激。

      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/10/2/133641141.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-6-16 02:55 , Processed in 0.380043 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表