自定义标签:

自定义标签

步骤:

  1. 编写标签处理类
  2. 编写标签描述符
  3. 导入并使用

MyTag.tld

的元素值共有4个:

元素值简介
empty表示在使用自定义标签时,不能设置标签体。
JSP表示标签体可以是任意的JSP元素。JSP必须大写。
scriptless表示标签体可以包含除scriptlet以外的任意JSP元素。
tagdependent表示JSP容器对标签体的内容不进行任何解析处理。例如,标签体中的<…>、<%…%>、${…}等,都会被当作普通的字符文本。

scriptlet: <% … %> <%! … %> <%= … %>

Tag属性

属性简介
SKIP_BODYdoStartTag()方法的返回值,表示标签体不会被执行
EVAL_BODY_INCLUDEdoStartTag()方法的返回值,表示标签体会被执行
SKIP_PAGEdoEndTag()方法的返回值,表示标签后面的JSP页面内容不被执行
EVAL_PAGEdoEndTag()方法的返回值,表示标签后面的JSP页面内容继续执行

Tag方法:

方法简介
void setPageContext(PageContext pc)JSP容器在实例化标签处理类后,会调用setPageContext()方法将JSP的内置对象PageContext对象传递给标签处理类。此后,标签处理类就可以通过pageContext对象与JSP页面进行通信
void setParent(Tag t)JSP调用完setPageContext()方法后,就会调用setParent()方法将当前标签的父标签处理类对象,传递给当前标签处理类;如果当前标签没有父标签,则参数t为null
Tag getParent()获取当前标签的父标签处理类对象
int doStartTag() throws JspException当JSP容器解析到自定义标签的开始标签时,会自动调用doStartTag()方法。该方法的返回值是EVAL_BODY_INCLUDE和SKIP_BODY两个常量。 如果使用的是Tag的子接口BodyTag,返回值还可以是BodyTag.EVAL_BODY_BUFFERED。
int doEndTag() throws JspException当JSP容器解析到自定义标签的结束标签时,会自动调用doEndTag()方法。该方法的返回值是EVAL_PAGE和SKIP_PAGE两个常量。
void release()在标签处理类对象被当作垃圾回收之前,JSP容器会调用release()方法,用于释放标签处理类对象所占用的资源。

IterationTag新增常量及方法

**常量/**方法简介
EVAL_BODY_AGAIN 常量doAfterBody()的一个返回值,表示JSP容器会把标签体的内容重复执行一次。
int doAfterBody() 方法JSP容器在每次执行完标签体后,就会自动调用doAfterBody()方法。该方法的返回值是SKIP_BODY和EVEL_BODY_AGAIN。 SKIP_BODY:表示JSP容器会去执行代表结束标签doEndTag()方法; EVEL_BODY_AGAIN:表示JSP容器会去重复执行标签体。

BodyTag新增常量及方法

**常量/**方法简介
EVAL_BODY_TAG从JSP 1.2开始,不再推荐使用此常量。可以使用BodyTag.EVAL_BODY_BUFFERED或IterationTag.EVAL_BODY_AGAIN替代此常量。
EVAL_BODY_BUFFEREDdoStartTag()的第三个返回值,其余两个是在传统方式的上级接口Tag中定义的SKIP_BODY和EVAL_BODY_INCLUDE。 当返回EVAL_BODY_BUFFERED时,JSP容器就会创建一个javax.servlet.jsp.tagext.BodyContent对象,并调用setBodyContent()方法。
BodyContent bodyContent当前标签的标签体,被当作缓冲区使用。真正的缓冲区实际是BodyContent对象中的数组变量char[] cb。
void setBodyContent(BodyContent b)当doStartTag()返回EVAL_BODY_BUFFERED时,JSP容器就会调用此方法将标签体的内容传递给bodyContent属性。
void doInitBody() throws JspException当JSP容器执行完setBodyContent()以后,就会调用doInitBody()方法来进行一些初始化工作,为执行标签体做准备。

BodyContent类的方法

方法简介
public abstract String getString()返回BodyContent对象在缓冲变量中保存的数据
public abstract Reader getReader()返回Reader对象,用于读取缓冲变量中的数据
public abstract void writeOut(Writer out) throws IOException将BodyContent对象保存在缓冲变量中的数据,写入到指定的输出流。
public void clearBody()清空BodyContent对象在缓冲变量中保存的数据
public JspWriter getEnclosingWriter()返回JspWriter对象。当JSP容器创建BodyContent对象后,PageContext对象中的out属性就不再指向JSP隐式对象,而是指向新创建的BodyContent对象;同时,在BodyContent对象中会用一个JspWriter类型的成员变量enclosingWriter记住原来的隐式对象,getEnclosingWriter()就是返回原来的隐式对象。

​ SimpleTag接口中的方法

方法简介
public void doTag() throws JspException,IOException用于完成所有的逻辑操作:输出、迭代、修改标签体等。除了定义中的2个异常外,此方法还会抛出SkipPageException异常。 若抛出SkipPageException,就等效于传统标签doEndTag()方法返回SKIP_PAGE常量,即通知JSP容器不再执行JSP页面中位于结束标签以后的内容。
public void setParent( JspTag parent )用于将当前标签的父标签处理类对象传递给当前标签处理类。如果当前标签没有父标签,JSP容器会忽略执行此方法。
public JspTag getParent()返回当前标签的父标签处理类对象。如果没有,则返回null。
public void setJspContext( JspContext pc )用于将JSP内置对象pageContext对象传递给标签处理类。之后,标签处理类就可以通过pageContext对象与JSP页面进行交互。JspContext是PageContext的父类。
public void setJspBody( JspFragment jspBody )用于把标签体的JspFragment对象传递给标签处理类对象。

JspFragment中定义的方法

方法简介
void invoke(Writer out)用于将标签体的内容写入到输出流out对象中。如果参数out的值为null,JSP容器会将标签内容写入到JspContext.getOut()方法返回的输出流对象中。 如果doTag()方法调用一次invoke(),则会执行一次标签体;如果调用多次invoke(),就会执行多次标签体。
JspContext getJspContext()用于返回代表页面的JspContext对象

SimpleTagSupport重要的方法及属性简介

**属性/**方法简介
jspContext****属性用于保存JSP容器传入的JspContext对象
jspBody****属性用于保存JSP容器传入的JspFragment对象
**protected JspContext getJspContext()**方法用于返回代表调用页面的JspContext对象
**protected JspFragment getJspBody()**方法用于返回代表标签体JspFragment对象
  1. 编写标签处理类:

​ 传统方式:(jsp1.1),实现Tag接口 doStartTag()标签处理类的核心方法

​ 简单方式:(jsp2.0)实现SimpleTag接口 doTag()

​ 如果jsp在编译阶段,发现了自定义标签<xx:yyy >,就会交给doStartTag()或doTag()

  1. 编写标签描述符(Tld):

    ​ 编写建议 可以仿照一个其他标签语言(el,jstl) 的tld文件

  2. 导入并使用:

    ​ 位置:MyTag.tld导入WEB-INF或其子目录下(特例排除,不能是WEB-INF/lib、WEB-INF/classes)

    ​ 使用:

    1. 引入具体要使用的.tld文件 <% @taglib uri=" " prefix=“d”%>uri每个tld文件的唯一描述符,prefix:使用tld标签时的前缀

      1. 空标签(没有标签体的标签) <d:foreach></d:foreach>或<d:foreach/>

      2. 带标签体 <d:foreach>xxxxx</d:foreach>

      3. 带属性 <d:foreach 属性名=“属性值” collection="${student}" >xxxx<d:foreach>

      4. 嵌套 <d:foreach>

        ​ <d:foreach>xxxxx<d:foreach>

        ​ </d:foreach>

实际开发步骤:

  1. 编写标签处理类 确保项目有tomcat环境

  2. Tag接口:

    1. doStartTag():标签处理类的核心方法 (标签体的执行逻辑)
      1. int SKIP_BODY = 0表示标签体不会被执行
      2. int EVAL_BODY_INCLUDE = 1;表示标签体会被执行
    2. doEndTag():标签执行完毕之后的方法(例如可以让标签在执行完毕后再执行一次)
      1. int SKIP_PAGE = 5;表示标签体后面的JSP页面内容不被执行
      2. int EVAL_PAGE = 6;表示标签体后面的JSP页面的内容继续执行
  3. Tag接口中的所有方法执行顺序:

    • jsp — servlet

    • 当JSp容器(Tomcat、jetty)在将.jsp翻译成servlet(.java)的时候,如果遇到jsp中有标签,就会依次执行 setPageContent() setPsrent() doStartTag() doEndTag() realease();用于解析标签的执行逻辑

  4. IterationTag接口:(是Tag的子接口) 如果有循环使用IterationTag接口,没有循环使用Tag接口。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package javax.servlet.jsp.tagext;

import javax.servlet.jsp.JspException;

public interface IterationTag extends Tag {
    int EVAL_BODY_AGAIN = 2;

    int doAfterBody() throws JspException;
}


doAfterBody():当标签体执行完毕之后的操作,通过返回值决定。
    返回值:  (EVAL_BODY_AGAIN = 2)重复执行,SKIP_BODY=0:不再执行。
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐