在tld文件中描述标签和属性,name代表的是属性的名字,required代表的是是否为必须,rtexprvalue代表能否使用EL表达式
<tag> <name>formatDate</name> <tag-class>tag.Demo1</tag-class> <body-content>empty</body-content> <attribute> <name>format</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag>
我们来看一下效果:
标签的继承关系
- 在深入讲解之前,我们先来看一下各种Tag接口、类之间的关系,这样学习下去才不会晕!
IterationTag说明
- 我们已经使用过了Tag接口和TagSupport类了。接下来我们看一下IterationTag是什么玩意。
public interface IterationTag extends Tag { int EVAL_BODY_AGAIN = 2; int doAfterBody() throws JspException; }
- 从关系图我们也可以看出,IterationTag接口实现了Tag接口,InterationTag接口和Tag接口最主要的区别就是多了个doAfterBody()方法和EVAL_BODY_AGAIN变量
- 理解起来也很简单:当doAfterBody()返回的是EVAL_BODY_AGAIN变量,那么标签体的内容就一直循环!当然了,TagSupport也实现了Iteration接口,也就是说TagSupport类也能完成Iteration接口的事情!
- 我们来使用一下吧:
public class Demo1 extends TagSupport { @Override public int doStartTag() throws JspException { try { pageContext.getOut().write("hello"); } catch (IOException e) { e.printStackTrace(); } //执行标签体 return EVAL_BODY_INCLUDE; } @Override public int doAfterBody() throws JspException { //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY return EVAL_BODY_AGAIN; } }
tld文件中描述,既然标签体有内容,就不能用empty了!
<tag> <name>foreverEval</name> <tag-class>tag.Demo1</tag-class> <body-content>tagdependent</body-content> </tag>
- 注意看横向的滑轮,已经死循环输出了:
doAfterBody()中只要返回的是SKPI_BODY就退出循环,执行doEndTag()方法
//定义一个变量,规定标签体循环的次数 int x = 0; @Override public int doStartTag() throws JspException { try { pageContext.getOut().write("hello"); } catch (IOException e) { e.printStackTrace(); } //执行标签体 return EVAL_BODY_INCLUDE; } @Override public int doAfterBody() throws JspException { x++; if (x >= 10) { return SKIP_BODY; } //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY return EVAL_BODY_AGAIN; }
现在我们已经能控制循环的次数了!