jsp自定义分页标签

首先声明我也是参考了在Struts2中实现自定义分页标签全攻略(一)后才写的此文,做了点小改动,非原创也非抄袭,只是记录下学习的过程。源码在jar包中,最后有链接。

首先看看分页的效果图吧,

然后开始标签的开发。

第一步,先创建一个tld文件,这个文件的作用是定义标签,表明标签的名字,处理类,引用URI还有属性等信息。此文件放在/WEB-INF/下。

pager.tld

<?xml version="1.0" encoding="UTF-8"?>  
<taglib 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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"  
      version="2.0">
    
    <tlib-version>1.0</tlib-version>
    <short-name>pager</short-name>
    <uri>http://page.way2a.com/tag</uri>
    <tag>
        <!-- 标签名 -->
        <name>page</name>
        <!-- 对应的标签处理类 -->
        <tag-class>com.way2a.common.util.PageTag</tag-class>
        <!-- 标签主体类型 -->
        <body-content>empty</body-content>
        <!-- 标签属性描述 -->
        <attribute>
            <!-- 属性名  当前页数 -->
            <name>pageNo</name>
            <!-- 是否是必须的 -->
            <required>true</required>
            <!-- 设置属性的值是否可以在jsp编译时动态生成 -->
            <rtexprvalue>true</rtexprvalue>
            <!-- 属性的数据类型 -->
            <type>int</type>
        </attribute>
        <attribute>
            <!-- 总记录条数 -->
            <name>totalRecord</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
            <type>int</type>
        </attribute>
        <attribute>
            <!-- 每页展示的条数 -->
            <name>pageSize</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
            <type>int</type>
        </attribute>
        <attribute>
            <!-- 点击分页链接后跳转的地址 -->
            <name>url</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
            <type>String</type>
        </attribute>
    </tag>    
</taglib>

第二步,根据上面tld文件的<tag-class>标签创建标签处理类 com.way2a.common.util.PageTag.java

package com.way2a.common.util;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * 分页标签处理类
 * @author way2a
 *
 */
public class PageTag extends TagSupport{
    private static final long serialVersionUID = 6179314241821348095L;
    
    private int pageNo = 1;
    private int pageSize = 10;
    private int totalRecord ;
    private String url;
    
    @Override
    public int doStartTag() throws JspException {
        if(pageSize <= 0){
            pageSize = 10;
        }
        //计算总的页数
        int pageCount = (totalRecord % pageSize == 0)?(totalRecord / pageSize):(totalRecord / pageSize + 1);
        //设置最多能显示多少个页数按钮
        int maxShowButton = 5;
        
        StringBuilder sb = new StringBuilder();
        //拼接分页样式
        sb.append("<style type=\"text/css\">");
        sb.append(".pagination {clear:both;color:#323232;padding: 10px;float:right;font-size:13px;}");  
        sb.append(".pagination a, .pagination a:link, .pagination a:visited {padding:2px 5px;margin:2px;border:1px solid #b5b5b5;text-decoration:none;color:#006699;}");  
        sb.append(".pagination a:hover, .pagination a:active {background:#fff; text-decoration:none;}");  
        sb.append(".pagination span.current {padding: 2px 5px;margin: 2px;border: 1px solid #b5b5b5;font-weight: bold;background-color: #fdfdfd;box-shadow:1px 4px 6px rgba(0,0,0,0.2) inset;}");  
        sb.append(".pagination span.disabled {padding: 2px 5px;margin: 2px;border: 1px solid #eee; color: #ddd;}");  
        sb.append("</style>\r\n"); 
        
        if(this.totalRecord == 0){
            sb.append("<div style=\"width:100%;text-align:center;display:block;font-size:15px;\" >\r\n");
            sb.append("<Strong>没有可显示的项目</Strong>\r\n");
        }else{
            sb.append("<div class=\"pagination\" >\r\n");
            //对页数进行越界处理
            if(pageNo > pageCount){
                pageNo = pageCount;
            }
            if(pageNo < 1){
                pageNo = 1;
            }
            
            sb.append("<form method=\"post\" action=\"").append(this.url)
                .append("\" name=\"paramForm\">\r\n");
            
            //获取当前页面request里的所有请求参数
            HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
            Enumeration<String> paramNames = request.getParameterNames();
            //遍历枚举里面的参数,与分页有关的直接设置到属性上,其他参数放置到type为hidden的input中
            String name = null;
            String value = null;
            while(paramNames.hasMoreElements()){
                name = paramNames.nextElement();
                value = request.getParameter(name);
                
                if("pageNo".equals(name)){
                    if(value != null && !"".equals(value)){
                        this.pageNo = Integer.parseInt(value);
                    }
                }else {
                    sb.append("<input type=\"hidden\" name=\"").append(name)
                        .append("\" value=\"").append(value).append("\" />\r\n");
                }
            }
            sb.append("<input type=\"hidden\" name=\"").append("pageNo")
                .append("\" value=\"").append(this.pageNo).append("\" />\r\n");
            
            sb.append("</form>\r\n");
            
            sb.append("<a href=\"javascript:turnOverPage(").append(1)
                .append(")\">首页</a>\r\n");
            //当前页面为第一页时不显示上一页
            if(pageNo == 1){
                sb.append("<span class=\"disabled\">上一页</span>\r\n");
            }else {
                sb.append("<a href=\"javascript:turnOverPage(").append(this.pageNo -1)
                    .append(")\" >上一页</a>\r\n");
            }
            
            //设置显示按钮的数量
            int showButton = maxShowButton;
            //当页数不够maxShowButton时
            if(pageCount < maxShowButton){
                showButton = pageCount;
            }
            
            //标识显示的按钮上的开始下标
            int startPageIndex = 1;
            //当页数为第一页或第二页时
            if(this.pageNo ==1 || this.pageNo ==2){
                startPageIndex = 1;
            }else{
                startPageIndex = this.pageNo - 2;
            }
            
            //当页数为倒数第一或第二页时    6 7 8 [9] 10   6 7 8 9 [10]  其他都是从当前页面的前2个开始,展示maxShowButton个.
            //当总页数不足maxShowButton时也适用,因为此时showButton等于pageCount,开始下标一直为1.
            if(this.pageNo == pageCount || this.pageNo == pageCount - 1 ){
                startPageIndex = pageCount - showButton + 1;  
            }
            
            //循环将按钮拼接到HTML上
            for (int i = 0; i < showButton; i++) {
                int pageIndex = startPageIndex++;
                //如果是当前页,则改变样式,不可点击。
                if(pageIndex == this.pageNo){
                    sb.append("<span class=\"current\">").append(pageIndex).append("</span>\r\n");
                }else{
                    sb.append("<a href=\"javascript:turnOverPage(").append(pageIndex).append(")\">").append(pageIndex).append("</a>\r\n");
                }
            }
            //如果到达了最后一页,则下一页按钮不可用
            if(this.pageNo == pageCount){
                sb.append("<span class=\"disabled\">下一页</span>\r\n");
            }else{
                sb.append("<a href=\"javascript:turnOverPage(").append(this.pageNo + 1)
                    .append(")\" >下一页</a>\r\n");
            }
            
            sb.append("<a href=\"javascript:turnOverPage(").append(pageCount)
                .append(")\">末页</a>\r\n");
            //拼接总记录条数和总页数
            sb.append("共<strong>").append(this.totalRecord).append("</strong>条,").append("共<strong>")
                .append(pageCount).append("</strong>页");
            
            sb.append("<script type=\"text/javascript\">\r\n");
            sb.append("function turnOverPage(no){\r\n");
            sb.append("if(no>").append(pageCount).append("){");
            sb.append("no=").append(pageCount).append(";}\r\n");
            sb.append("if(no<1){ no=1;}\r\n");
            sb.append("document.paramForm.pageNo.value=no;\r\n");
            sb.append("document.paramForm.submit();\r\n");
            sb.append("}\r\n");
            sb.append("</script>\r\n");
        }
        sb.append("</div>\r\n");
        
        try {
            this.pageContext.getOut().println(sb.toString());
        } catch (IOException e) {
            throw new JspException(e);
        }
        return 0;
    }

    public int getPageNo() {
        return pageNo;
    }

    public void setPageNo(int pageNo) {
        this.pageNo = pageNo;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalRecord() {
        return totalRecord;
    }

    public void setTotalRecord(int totalRecord) {
        this.totalRecord = totalRecord;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

 这个java类会在引用了这个标签的地方输出HTML代码替换掉标签。

第三步,在jsp页面头部引入标签

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://page.way2a.com/tag" prefix="pager" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head><title></title></head>
  
  <body>
    <h2>hello</h2>
    <pager:page pageSize="10" pageNo="1" url="/PageTag/HelloServlet" totalRecord="200"/>
  </body>
</html>

 由于只是演示,就把参数写死了,实际中用${}获取request中相应的参数值。

然后说个问题,我在ssm项目中使用时发现,url参数这里填写<%=contextPath%>/xxx/xxx时,访问页面会报错,org.apache.jasper.JasperException:attribute value for [url] is not properly terminated。

上网查了后发现好像这里不能用<%=xxx%>与/xxx混合,要么使用纯字符串路径 xxx/xxx,要么只用表达式<%=url%>。应该是不支持解析表达式值后再拼接字符串。

还有一个点就是点击页数按钮使用的是表单post提交,所以@RequestMapping()不要写method=RequestMethod.GET,否则报405。

 到这里就开发完了,但是如果每个项目要用到都去建这个类和tld文件显然是很麻烦的,因此只需要把这个class文件和tld文件放到classpath上就行了,可以打包成一个jar包。

tld文件放在META-INF文件夹,然后cmd中进入到所在文件夹下,使用以下命令进行打包:jar -cvf xxx-xxx.jar *

最后把我的jar包放上来给有需要的人参考下。

链接: https://pan.baidu.com/s/1o76RFHw 密码: 7fh8

posted @ 2017-10-26 14:44  way2a  阅读(3631)  评论(2编辑  收藏  举报