java EE开发之Servlet第十三课:复杂自定标签

上一节我们讲了,简单自定义标签的使用,如果没有了解的看官,可以自行 简单自定义标签,事实上,在实际开发过程中简单自定义标签不能满足我们的需求,比如,我们要对标签体进行迭代,根据条件对标签体进行相应的处理,这个时候我们就要学习复杂自定义标签的使用。这编我们按下面的思路讲复杂自定标签

  1. 怎么样实现复杂自定标签。
  2. 自定义标签实战一:循环打印时间
  3. 自定义标签实战二:if-else标签

1,怎么样实现复杂自定义标签
继承BodyTagSupport类或实现BodyTag接口

public class MyTag extends BodyTagSupport {

    @Override
    public int doAfterBody() throws JspException {
        // TODO Auto-generated method stub
        return super.doAfterBody();
    }

    @Override
    public int doEndTag() throws JspException {
        // TODO Auto-generated method stub
        return super.doEndTag();
    }

    @Override
    public void doInitBody() throws JspException {
        // TODO Auto-generated method stub
        super.doInitBody();
    }

    @Override
    public int doStartTag() throws JspException {
        // TODO Auto-generated method stub
        return super.doStartTag();
    }

    @Override
    public BodyContent getBodyContent() {
        // TODO Auto-generated method stub
        return super.getBodyContent();
    }

    @Override
    public JspWriter getPreviousOut() {
        // TODO Auto-generated method stub
        return super.getPreviousOut();
    }

    @Override
    public void release() {
        // TODO Auto-generated method stub
        super.release();
    }

    @Override
    public void setBodyContent(BodyContent b) {
        // TODO Auto-generated method stub
        super.setBodyContent(b);
    }

}

setPageContext() 将所在jsp页面的pageContext注入进来,目的是为了在后面的 方法中可以访问到jsp页面对象的pageContext属性。
setParent() 设置此标签的父标签。
doStartTag() 在开始标签属性设置后调用,如果返回SKIP_BODY则忽略标签之中的内容,如果返回EVAL_BODY_INCLUDE则将标签体的内
容进行输出。
setBodyContent() 设置当前的BodyContent。
doInitBody() 在计算BodyContent时需要进行一些初始化,就在这个方法中进行。
doAfterBody() 如果返回EVAL_BODY_AGEIN,表示继续计算一次BodyTag;
返回EVAL_BODY_INCLUDE则将标签体的内容进行输出;
返回EVAL_BODY_BUFFERED,它将对主体进行计算,并输出到缓冲区(注:此处是缓冲区并非直接输出到客户端,需要我
们手动(this.bodyContent.getEnclosingWriter().write(this.bodyContent.getString());)进行输出客户端的调用,否则主内
直到返回SKIP_BODY才继续执行doEndTag()。
doEndTag() 在结束标签之前调用,返回SKIP_PAGE跳过整个jsp页面后面的输出,返回EVAL_PAGE执行页面余下部分。
release() 生命周期结束时调用,释放标签程序占用的任何资源.。
为了方便各位看官,下面给出更为直观的流程图:

这里写图片描述
2. 自定义标签实战一:循环打印时间

标签类定义

public class KateLoopTag extends BodyTagSupport
{
    int counts;//counts为迭代的次数。
    public KateLoopTag ()
    {
        super();
    }

    /**
     *设置counts属性。这个方法由容器自动调用。
     */
    public void setCounts(int c)
    {
        this.counts=c;
    }

    /**
     *覆盖doStartTag方法
     */
     public int doStartTag() throws JspTagException  
     {   
         System.out.println("doStartTag");
         if(counts>0) 
         { 
             return EVAL_BODY_TAG;
         } 
         else 
         { 
              return SKIP_BODY;
         } 
    }

    /**
     *覆盖doAfterBody方法
     */
    public int doAfterBody() throws JspTagException 
    { 
        System.out.println("doAfterBody"+counts);
        if(counts>1)
        {
            counts--;
            return EVAL_BODY_AGAIN; 
         }  
         else
         { 
            return SKIP_BODY; 
         } 
    }

   /**
     *覆盖doEndTag方法
     */
    public int doEndTag() throws JspTagException 
    {
         System.out.println("doEndTag");
        try 
        {  
             if(bodyContent != null)  
             {
                 bodyContent.writeOut(bodyContent.getEnclosingWriter()); 
             }
        } 
        catch(java.io.IOException e)
        {
            throw new JspTagException("IO Error: " + e.getMessage());  
        }   
        return EVAL_PAGE;  
    }

     public void doInitBody() throws JspTagException{
      System.out.println("doInitBody");
     }
     public void setBodyContent(BodyContent bodyContent) 
     {   
          System.out.println("setBodyContent");
          this.bodyContent=bodyContent;     
     }      
}

TLD文件定义
在WEB-INF/tag下面创建kzTag.tld文件

<tag>    
   <name>loop</name>
   <tag-class>com.kz.KateLoopTag</tag-class>
   <!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP  -->
   <body-content>JSP</body-content>
   <attribute>
           <!-- 这个是我们资源源文件中的属性,同时源文件中必须要有setCounts(int counts)方法 -->
         <name>counts</name>
         <!-- 必需要给定 -->
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
     </attribute>
</tag>

测试
**

<%@ taglib uri="/WEB-INF/tag/kzTag.tld" prefix="bodytag" %>
<html>
<head>
<title>body tag</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
 <HR>
 <bodytag:loop counts="5"> 
   现在的时间是: <%=new java.util.Date()%><BR>
</bodytag:loop> 
 <HR>  
 </BODY>  
</HTML>

这里写图片描述
3. 自定义标签实战二:if-else标签
在jsp中是没有类似java中,if-else if- else这样的逻辑判断,今天我们就用自定义标签的形式来实现
if标签类的实现

/**
 * 自定义if  elseif else 标签
 * @author 凯舟.陈超
 * @date 2013-6-22 下午9:38:45
 * @modifyNote
 * @version 1.0
 */
public class TmIfTag extends BodyTagSupport {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    private String body = null; // 用于存放成功条件后的内容
    private boolean subtagSucceeded;
    private boolean test;

    public TmIfTag() {
        super();
        init();
    }

    @Override
    public void release() {
        super.release();
        init();
    }

    @Override
    public int doStartTag() throws JspException {
        if (test) {
            this.succeeded();
        }
        /*return EVAL_BODY_INCLUDE;计算标签体内容直接输出到客户端
         * 计算标签体内容并输出到缓冲区,必须通过 body = bodyContent.getString().trim();获取缓存区内容
         * 然后通过pageContext.getOut().write(内容) 输出到页面。
         */
        return EVAL_BODY_BUFFERED;

    }
    @Override
    public int doEndTag() throws JspException {
        try {
            if (subtagSucceeded){
                String body2 = getBody();
                pageContext.getOut().write(body2);
            }
        } catch (IOException e) {
            throw new JspException("IOError while writing the body: "
                    + e.getMessage(), e);
        }
        init();
        return super.doEndTag();
    }
    public void setBody() {
        if (body == null) {
            body = bodyContent.getString().trim();
        }
    }
    private String getBody() {
        if (body == null)
            return bodyContent.getString().trim();
        else
            return body;
    }
    /**
     * 子条件判断成功
     */
    public void succeeded() {
        subtagSucceeded = true;
    }
    /**
     * 是否已经执行完毕
     * 
     * @return
     */
    public boolean isSucceeded() {
        return subtagSucceeded;
    }
    private void init() {
        test = false;
        subtagSucceeded = false;
        body = null;
    }
    public void setTest(boolean test) {
        this.test = test;
    }
}

else-if标签类的实现

public class TmElseIfTag extends BodyTagSupport{
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    private boolean test;  
    public TmElseIfTag() {
        super();
        init();
    }

    @Override
    public int doStartTag() throws JspException {
        Tag parent = getParent();

        if(parent==null || !(parent instanceof TmIfTag)){
            throw new JspTagException("else tag must inside if tag");
        }

        TmIfTag ifTag = (TmIfTag)parent;
        if(ifTag.isSucceeded()){
            // 已经有执行成功的条件,保存之前的html
            ifTag.setBody();
        }else if(test){        // 当前条件为true,之前无条件为true
            ifTag.succeeded();
            // 则清除之前的输出
            String body3 = ifTag.getBodyContent().getString();
            ifTag.getBodyContent().clearBody();
        }

        return EVAL_BODY_BUFFERED;
    }

    @Override
    public void release() {
        super.release();
        init();
    }

    private void init() {
        test = false;
    }

    public void setTest(boolean test) {
        this.test = test;
    }
}

else标签类的实现

public class TmElseTag extends BodyTagSupport{
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;

    public void release() {
        super.release();
    }

    public int doStartTag() throws JspException {
        Tag parent = getParent();

        if(parent==null || !(parent instanceof TmIfTag)){
            throw new JspTagException("else tag must inside if tag");
        }

        TmIfTag ifTag = (TmIfTag)parent;
        if(ifTag.isSucceeded()){
            // 已经有执行成功的条件,保存之前的html
            ifTag.setBody();
        }else{
            // 之前没有的判断没有成功条件,则清除之前的输出
            ifTag.getBodyContent().clearBody();
            ifTag.succeeded();
        }

        return EVAL_BODY_BUFFERED;
    }

}

TLD文件
在WEB-INF/tag下面创建kz.tld文件

<tag>
        <description>if标签</description>
        <name>if</name>
        <tag-class>com.kz.tag.TmIfTag</tag-class>
        <!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
        <body-content>JSP</body-content>
        <attribute>
            <name>test</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

    <tag>
        <description>elseif标签</description>
        <name>elseif</name>
        <tag-class>com.kz.tag.TmElseIfTag</tag-class>
        <!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
        <body-content>empty</body-content>
        <attribute>
            <name>test</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

    <tag>
        <description>else标签</description>
        <name>else</name>
        <tag-class>com.kz.tag.TmElseTag</tag-class>
        <!-- 如果没有标签体,设置empty , 如果有标签休必须设置JSP -->
        <body-content>empty</body-content>
    </tag>

jsp测试使用

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/WEB-INF/tag/kz.tld" prefix="kz"%>
    <kz:if test="${1==2}">
        我是if
      <kz:elseif test="${1==1}"/>
        我是else if
    </kz:if>

这里写图片描述

发布了26 篇原创文章 · 获赞 13 · 访问量 7020

猜你喜欢

转载自blog.csdn.net/womeia331416/article/details/78064974