深入体验JavaWeb开发内幕——进一步体味传统自定义标签的接口与实现类
我们知道要想定义自己的标签,必不可少的三个步骤是:
(1) 创建一个自定义标签处理器类;
(2) 在扩展名为“.tld”的文件中对这个标签处理器类进行描述
(3) 在JSP文件中使用taglib指令引用自定义标签
可见,要想在JSP文件中引用自定义标签,关键的一点是要有一个标签处理器类。而且不是任何Java类都可以做为标签处理器类的,只有实现了相应的标签处理接口或者继承了标签处理器接口子类的类才可以作为标签处理器类。
跟据JSP规范的不同标签处理器类所实现的接口也不同。以JSP1.2的规范为分界线,1.2之前的实现方式被称为传统标签,所要实现的主要接口有3个:Tag、IterationTag、BodyTag;1.2之后的被称为简单标签,主要实现的接口是SimpleTag。下面我们将会对传统标签接口与简单标签接口分别进行介绍。
下面我们先来看传统标签中的不同接口之间的关系以及他们相关实现类的生命周期。
一、JspTag
在javax.servlet.jsp.tagext包下,JspTag是Tag 和 SimpleTag接口的父接口。已知的子接口有BodyTag,IterationTag,SimpleTag, Tag实现类有BodyTagSupport,SimpleTagSupport,TagAdapter, TagSupport这个JspTag就类似与Java集合中的Collection一样是所有传统实现标签与简单标签的父接口,此接口定义了对于所有标签处理类都需要实现的方法
。
二、接口与实现类之间的关系图
如图所示各接口和类之间的关系可以按找Tag传统标签接口和SimpleTag简单标签接口的顺序进行分析。
从Tag接口一支:
Tag接口继承了JspTag接口并且定义了一些让Jsp解析引擎操作Jsp文件时调用的方法但这毕竟是简单的、不完全的操作,虽然可以在doStartTag()和doEndTag()中加入相应的操作代码,但是,对于标签体的一些操作仍然不能够满足要求,因此,就出现了实现了Tag接口的IterationTag接口,并且在该接口中定义了对自定义标签体进行操作的doAfterBody()方法可以决定是否循环执行标签体中的内容。并且实现改接口的BodyTag又在它们的基础上增加了对标签体初始化和设置标签体内容的方法以便于在以后更方便的获取标签体的内容。BodyTag接口中定义的方法虽然涉及到了标签体的内容,但那毕竟只是一些为需要使用标签体内容的方法提供的,它本身并没有提供对标签体进行操作,如:获取并修改标签体的方法,因此出现了可对标签体内容进行修改的实现了BodyTag接口的类BodyTagSupport类,在该类的doEndTag
()
方法中可对自定义标签体中的内容进行修改并且决定是否显示自定义标签体之后的其他Jsp页面。该类也是继承了TagSupport类的类,从而将这一切完美集于一身即真正做到了可以对自定义标签体的内外、前后进行真正的控制。TagSupport类也是我们在定义传统自定义标签时经常使用的,需要时只需使作为标签处理器的类继承改类即可。
从SimpleTag接口一支:
SimpleTag接口作为实现了JspTag的直接子接口,也定义了一些供Jsp解析引擎自行调用的方法。这些方法操作同Tag接口一样都只是一些最基本的供解析引擎调用的,不完全的操作,真正弥补了这一缺点的是它的实现类SimpleTagSupport该类中定义或从父接口中实现了一些方法,这些方法可以达到同使用传统标签一样的效果,并且简单标签之所以被称之为简单是相对于传统的开发自定义标签的TagSupport类来说的,在SimpleTagSupport中只需在doTage()方法中实现相应的业务代码即可达到与传统标签定义中调用不同的方法达到不同的功能具有异曲同工的妙处。
三、BodyTagSupport类和TagSupport类的生命周期
1、TagSupport类的生命周期
如图:
当Jsp解析引擎遇到自定义标签时根据遇到的自定义标签去寻找其对应的标签处理器类然后建立标签处理对象,如果该标签没有其他父标签再看它是否有属性如果设置了属性就将自定义标签的属性值存入标签处理对象中以方便在标签处理类中进行使用。接着调用doStartTag()方法该方法返回两个整形值一个是:
SKIP_BODY,另一个是EVAL_BODY_INCLUDE。当返回值为SKIP_BODY时,表示将忽略标签主体直接进入到doEndTag()方法中;如果返回值为EVAL_BODY_INCLUDE表示显示标签体的内容此时当执行完标签体时会运行doAfterBody()方法当该方法返回EVAL_BODY_AGAN值时将返回标签主体继续执行直到返回值为SKIP_BODY时才去执行doEndTag()方法。当执行到doEndTag()方法时,该方法同样会返回两个整形字段值。当返回SKIP_PAGE时表示忽略JSP网页的其他内容,即改结束标签之后的JSP网页的内容将被忽略。反之当返回值为EVAL_PAGE将继续运行JSP网页的其他内容。
2、BodyTagSupport类的生命周期
如图:
即当Jsp解析引擎遇到自定义标签时根据遇到的自定义标签去寻找其对应的标签处理器类然后建立标签处理对象,如果该标签没有其他父标签再看它是否有属性如果设置了属性就将自定义标签的属性值存入标签处理对象中以方便在标签处理类中进行使用。接着调用doStartTag()方法该方法返回两个整形值一个是:
SKIP_BODY,另一个是EVAL_BODY_BUFFERED此时JSP解析引擎就会自动调用setBodyContent()和doInitBody()方法将相关的JSP页面的内容传递给标签处理类对象然后返回EVAL_BODY_INCLUDE整数值此时就会显示标签体的内容。当标签体的内容执行完后解析器引擎会调用doAfterBody()方法,当返回值为SKIP_BODY时,表示将忽略标签主体直接进入到doEndTag()方法中;如果返回值为EVAL_BODY_AGAIN时表示重复显示标签体的内容直到返回值为SKIP_BODY时才去执行doEndTag()方法。当执行到doEndTag()方法时,该方法同样会返回两个整形字段值。当返回SKIP_PAGE时表示忽略JSP网页的其他内容,即改结束标签之后的JSP网页的内容将被忽略。反之当返回值为EVAL_PAGE将继续运行JSP网页的其他内容。
由上述执行流程可以看到TagSupport比BodyTagSupport类更加易于使用所以一般情况下我们还是习惯继承TagSupport类去做自定义标签处理类。
好了,上面介绍了关于传统标签的接口及其实现类的相关相关的流程以及生命周期的东西,只有深入掌握了这些才能够更加清楚的了解自定义处理类中的各方法的具体意义。才更加有助于我们对自定义标签进行深入理解!