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>

这里写图片描述

超全面的测试IT技术课程,0元立即加入学习!有需要的朋友戳:

腾讯课堂测试技术学习地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值