Java标签之自定义分页标签

in Java with 0 comment

做过Java Web项目的开发工程师都知道,如果单纯的使用jsp脚本开发,糅合内容和行为逻辑与一体是一个非常不好的体验,更不易于维护。所以采用了JSTL标签库,用于分离数据显示和业务逻辑,简易开发,带来优雅编程体验。JSTL 即:JSP Standard Tag Library,一个JSP标签集合,它封装了JSP应用的通用核心功能。他依赖于standard.jar和jstl.jar两个jar包。

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。尽量只是用核心标签,包括<c:if>、<c:choose>、<c:when>、<c:otherwise>、<c:forEach>等,主要用于构造循环和分支结构以控制显示逻辑。标签引用:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

格式化标签一般用于日期相关的数据处理。函数标签一般用于字符串相关的数据处理。当然,这次要记录的是如何自定义标签,增强自己的数据处理需要。这里以自定义分页标签为例。

1、实现Tag接口或者继承缺省适配的Tag相关类。

开发中通常不直接实现这些接口而是继承TagSupport/BodyTagSupport/SimpleTagSupport类,重写doStartTag()、doEndTag()等方法,定义标签要完成的功能。

现在已自定义分页标签为例,继承BodyTagSupport类,重写doStartTag方法。定义了一些属性。

PageData pageData; // 分页类
String funcName; // js 回调函数名
String formId; // 表单的ID名
String formUrl; // 表单提交的URL

重写doStartTag方法:

@Override
public int doStartTag() throws JspException {
    JspWriter out = this.pageContext.getOut();
    try {
        if (pageData == null) {
            return Tag.SKIP_BODY;
        }
        out.println(getPageHtml());
    } catch (IOException e) {
        throw new JspException(e);
    }
    return Tag.EVAL_BODY_INCLUDE;
}

在getPageHtml方法里根据逻辑拼接html分页列表,如一个简单的例子:

private String getPageHtml() {
        if (pageData == null) {
            return “”;
        }
        StringBuilder sBuilder = new StringBuilder();
        if (pageData.hasNext()) {
            sBuilder.append(“<li><a href=\”javascript:void(0)\” onclick=\””).append(this.funcName)
            .append(“(“).append(pageData.getPageNo()+1).append(“,”).append(pageData.getPageSize()).append(“,'”).append(formId).append(“‘,'”).append((formUrl == null || “”.equals(formUrl)?“”:formUrl))
            .append(“‘);\”>下一页</a></li>”);
        } else {
            sBuilder.append(“<li class=\”disabled\”>下一页</li>”);
        }
        if (pageData.hasPrevious()) {
            sBuilder.append(“<li><a href=\”javascript:void(0)\” onclick=\””).append(this.funcName)
            .append(“(“).append(pageData.getPageNo()-1).append(“,”).append(pageData.getPageSize()).append(“,'”).append(formId).append(“‘,'”).append((formUrl == null || “”.equals(formUrl)?“”:formUrl))
            .append(“‘);\”>上一页</a></li>”);
        } else {
            sBuilder.append(“<li class=\”disabled\”>上一页</li>”);
        }
        return sBuilder.toString();
    }

2、编写扩展名为tld的标签描述文件对自定义标签进行定义。

pages.tld自定义标签描述了标签名,标签处理类、和相关属性定义描述:

<tag>
    <name>page</name>
    <tag-class>com.common.test.PageTag</tag-class>
    <description>分页标签–power by wenqy.com</description>
    <attribute>
      <name>pageData</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <description>封装分页数据类</description>
    </attribute>
    <attribute>
      <name>funcName</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      <description>选择页签触发的js函数名</description>
    </attribute>
    <attribute>
      <name>formId</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <description>选择页签后要提交表单的ID</description>
    </attribute>
    <attribute>
      <name>formUrl</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      <description>选择页签后要跳转的页面URL</description>
    </attribute>
  </tag>

3、在JSP页面中使用taglib指令引用该标签库

Jsp头部引用tld标签描述文件。

<%@ taglib prefix="fns" uri="/WEB-INF/tlds/pages.tld" %>

调用自定义标签,formUrl属性非必须。

<fns:page pageData="${requestScope.pageData }" funcName="page" formId="myForm" />

4、js方法

表单里定义pageNo、pageSize两个隐藏域,并重写页签调用方法,使用jquery方法。

<script type=“text/javascript”>
        // 参数: 页数、页大小、form ID、submit URL
        function page(no, size,form,url) {
            var re = /^[0-9]*$/;
            if(!re.test(size)){
                alert(‘页大小为数字’);
                return;
            }
            if(!re.test(no)){
                alert(‘页数为数字’);
                return;
            }
            if (no) {
                $(“#pageNo”).val(no);
            }
            if (size) {
                $(“#pageSize”).val(size);
            }
            if (url) {
                $(“#” + form).attr(“action”,url);
            }
            $(“#” + form).submit();
            return false;
        }
</script>

5、pageData分页类

/**
 * 
 * @author wenqy
 *
 */
public class PageData implements Serializable {
    private static final long serialVersionUID = 8040968899344110256L;
    protected static final int DEFAULT_PAGE_NO = 0;
    protected static final int DEFAULT_PAGE_SISE = 0;
    protected static final int DEFAULT_INDEX_BEGIN = 0;
    protected static final int DEFAULT_INDEX_END = 0;
    protected List<?> items; // 页数据
    protected Object[][] results;
    protected int pageNo; // 当前页
    protected int pageSize; // 页大小
    protected int pageCount; // 页数
    protected int totalCount;
    protected int handleCount;
    protected int lastPageSize;
    protected int columnCount;
    protected int beginIndex;
    protected int endIndex;
    protected int[] indexes; // 记录每页的起始下标
    protected String orderField; // 排序字段
    protected boolean isOrderAsc; // 升降排序
    protected String resInfo;
    protected String pageCode;
    public boolean hasNext() {
        return (this.pageNo < this.pageCount);
    }
    public boolean hasPrevious() {
        return (this.pageNo > 0);
    }
    public static int convertFromPageToStartIndex(int paramInt1, int paramInt2) {
        return ((paramInt1 – 1) * paramInt2);
    }
    public int currentPageNo() {
        return getPageNo();
    }
    public int getNextIndex() {
        int i = getBeginIndex() + this.pageSize;
        if (i >= this.totalCount)
            return getBeginIndex();
        return i;
    }
    public int getPreviousIndex() {
        int i = getBeginIndex() – this.pageSize;
        if (i < 0)
            return 0;
        return i;
    }
    public List<?> getItems() {
        return this.items;
    }
    public void setItems(List<?> paramList) {
        this.items = paramList;
    }
    public int getPageNo() {
        return this.pageNo;
    }
    public void setPageNo(int paramInt) {
        this.pageNo = paramInt;
    }
    public int getPageSize() {
        return this.pageSize;
    }
    public void setPageSize(int paramInt) {
        this.pageSize = paramInt;
    }
    public int getPageCount() {
        if (this.totalCount < 0)
            return –1;
        if (this.totalCount == 0)
            return 0;
        if (this.pageSize > 0) {
            int i = this.totalCount / this.pageSize;
            if (this.totalCount % this.pageSize > 0)
                ;
            this.pageCount = (++i);
        } else {
            this.pageCount = 1;
            this.pageSize = this.totalCount;
        }
        return this.pageCount;
    }
    public void setPageCount(int paramInt) {
        this.pageCount = paramInt;
    }
    public int getTotalCount() {
        return this.totalCount;
    }
    public void setTotalCount(int paramInt) {
        if (paramInt > 0) {
            this.totalCount = paramInt;
            if (this.pageSize <= 0)
                return;
            int i = this.totalCount / this.pageSize;
            if (paramInt % this.pageSize > 0)
                ;
            this.indexes = new int[++i];
            for (int j = 0; j < i; ++j)
                this.indexes[j] = (this.pageSize * j);
        } else {
            this.totalCount = 0;
        }
    }
    public int getBeginIndex() {
        return this.beginIndex;
    }
    public void setBeginIndex(int paramInt) {
        if (this.totalCount <= 0)
            this.beginIndex = 0;
        else if (paramInt >= this.totalCount)
            this.beginIndex = this.indexes[(this.indexes.length – 1)];
        else if (paramInt < 0)
            this.beginIndex = 0;
        else if (this.pageSize > 0)
            this.beginIndex = this.indexes[(paramInt / this.pageSize)];
        else
            this.beginIndex = paramInt;
    }
    public int getEndIndex() {
        return this.endIndex;
    }
    public void setEndIndex(int paramInt) {
        this.endIndex = paramInt;
    }
    public int getLastPageSize() {
        if (this.totalCount < 0)
            return –1;
        if (this.totalCount == 0)
            return 0;
        int i = this.totalCount % this.pageSize;
        if (i > 0)
            return i;
        return this.pageSize;
    }
    public void setLastPageSize(int paramInt) {
        this.lastPageSize = paramInt;
    }
    public int getColumnCount() {
        return this.columnCount;
    }
    public void setColumnCount(int paramInt) {
        this.columnCount = paramInt;
    }
    public int getHandleCount() {
        return this.handleCount;
    }
    public void setHandleCount(int paramInt) {
        this.handleCount = paramInt;
    }
    public int[] getIndexes() {
        return this.indexes;
    }
    public void setIndexes(int[] paramArrayOfInt) {
        this.indexes = paramArrayOfInt;
    }
    public String getOrderField() {
        return this.orderField;
    }
    public void setOrderField(String paramString) {
        this.orderField = paramString;
    }
    public boolean isOrderAsc() {
        return this.isOrderAsc;
    }
    public void setOrderAsc(boolean paramBoolean) {
        this.isOrderAsc = paramBoolean;
    }
    public Object[][] getResults() {
        return this.results;
    }
    public void setResults(Object[][] paramArrayOfObject) {
        this.results = paramArrayOfObject;
    }
    public String getResInfo() {
        return this.resInfo;
    }
    public void setResInfo(String paramString) {
        this.resInfo = paramString;
    }
}

封装Dao层的分页方法,传入pageData。Jsp会被Java容器,如:Tomcat翻译成Servlet,获取pageContext对象,调用doStartTag方法。

pageData

使用标签库可以对内容显示和业务逻辑的解耦有很大帮助,如果觉得现有标签库不能满足需要还可以自定义标签。当然也是可以选择其他模板引擎,如freemarker、velocity等等。

参考:

http://tomcat.apache.org/taglibs/standard/ Standard Taglib