简单标签的声明周期:
(1)当jsp在执行的过程中,每当遇到一个简单标签时都会创建一个处理类对象.
(2)调用setJspContext传入当前jsp页面的PageContext对象.
(3)如果当前标签有父标签则调用setParent方法将父标签传入,如果没有父标签则这个方法不会被调用.
(4)如果该标签具有属性,调用属性的setXXX方法将属性的值传入
(5)如果当前标签具有标签体,则会调用setJspBody将封装了标签体信息的JspFragment传入,如果没有标签体,这个方法不执行
(6)最后调用doTag方法,在这个方法里我们可以书写处理标签事件的java代码
(7)当自定义标签执行完成后,简单标签对象就销毁掉了.
1.要自定义标签,就要知道自定义标签的基本功能:
(1)控制标签体是否执行<c:if>
(2)控制标签之后的内容是否执行
(3)控制标签体重复执行<c:foreach>
(4)修改标签体后输出<c:out>
注:三个函数的功能
getJspContext()获取代表jsp页面的pageContext,
getJspBody()代表标签体内容的JspFragment对象
JspFragment:invoke(Writer out) 此方法一经调用会将标签体输出到对应的流中。
package com.itheima.simletag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class SimpleDemo1 extends SimpleTagSupport {
private int times;
public void setTimes(int times) {
this.times = times;
}
@Override
public void doTag() throws JspException, IOException {
//--控制标签体是否执行
//----控制标签体不执行,什么都不做标签体就不会执行
//----控制标签体执行,只要调用封装着标签体的JSPFragment对象的invoke方法就可以执行标签体
//JspFragment fragment = getJspBody();
//fragment.invoke(getJspContext().getOut());
//fragment.invoke(null);
//--控制标签之后的内容是否执行
//----控制标签之后的内容执行:什么都不做,标签之后的内容就会执行
//----控制标签之后的内容不执行:抛出SkipPageException这样的一个异常就可以控制标签之后的内容不执行
//throw new SkipPageException();
//--控制标签体重复执行
for(int i=0;i<times;i++)
getJspBody().invoke(null);
//--修改标签体后进行输出 注意输出流写到字符串里在想输出,就得用如下方式
//StringWriter writer = new StringWriter();
//JspFragment fragment = getJspBody();
//fragment.invoke(writer);
//String str = writer.toString();
//str = str.toUpperCase();
//getJspContext().getOut().write(str);
}
}
2.为自定义标签来增加一个属性:
(1)在标签处理类中增加一个javabean属性,这个属性就是要增加的标签的属性,并对外提供setXXX方法。
(2)在tld文件中这个标签的描述中描述一下该属性。
注1:*想要开发一个简单标签,写一个类继承SimpleTagSupport覆盖doTag方法就可以了,可以调用getJspContext/getJspBody来获取需要的内容
注2*在tld文件中对标签进行描述
<tag>
<name>simpleDemo1</name>-- 标签的名字
<tag-class>com.itheima.simletag.SimpleDemo1</tag-class>-- 标签的处理类
<body-content>scriptless</body-content>-- JSP(简单标签不能写)
<attribute>-- 声明一个属性,可以声明多个属性
<name>times</name> -- 属性的名字
<required>true</required>-- 是否为必须存在的属性
<rtexprvalue>true</rtexprvalue>-- 是否支持el表达式
<type>int</type>-- 属性的java类型
</attribute>
</tag>
3.参考:标签的继承结构:
JspTag
(1)传统标签
Tag接口-----定义了一个标签处理类应具有的最基本的方法和属性(EVAL_BODY_INCLUDE dostart方法返回表示执行标签体,SKIP_BODYdostart方法用,跳过标签体。EVAL_PAGE
用在doendtag里通知后续页面继续执行,SKIP_PAGE doendtag里通知后续页面不再执行)
|
|----IterationTag接口 (提供了doAfterBody()在标签体执行过后立即执行,并提供EVAL_BODY_AGAIN 供doafterbody方法返回表示要重新执行标签体)
|
|----TagSupport类(提供了对pageContext的引用)
|
|--BodyTag接口(EVAL_BODY_BUFFERED在doStartTag方法中返回通知标签处理器去缓存标签体bodyContent)
|
|----BodyTagSupprot类 (getBodyContent() 获取缓存对象bodyContent)
(2)简单标签(简单标签的标签体不能包含脚本内容,所以tld文件中配置body-content时不能配置为JSP)
SimpleTag接口
|
|---SimpleTagSupport实现类(getJspContext() 获取代表jsp页面的pageContext,getJspBody() 代表标签体内容的JspFragment对象)
JspFragment:invoke(Writer out) 此方法一经调用会将标签体输出到对应的流中。如果你直接给一个null默认输出到pageContext.getOut()中
如果doTag()方法抛出SkipPageException异常,标签后的jsp页面就不再执行。