教程:了解 JSP 2.0 的新特性
讨论此教程。 可打印版本 (PDF)。
这是目录页。 无上一页。 到上一级。 转至下一页。

简单标记处理程序


在本章节中,我们将了解 JSP 2.0 的另一个有趣的新特性,简单标记处理程序。我们将特别关注以下内容:

使用简单标记扩展
简单标记接口
SimpleTag 语法
简单标记处理程序的生命周期

使用简单标记扩展

传统标记处理程序的 API 和调用协议必定略为复杂一些,因为标记主体中的 scriptlet 和 scriptlet 表达式能够依赖于使用封装页面中 scriptlet 所定义的上下文环境。随着表达式语言 (EL) 和 JSP 标准标记库 (JSTL) 的推出,JSP 页面制作人员现在可以开发不需要 scriptlet 或 scriplet 表达式的 JSP 页了。这也意味着需要考虑传统标记处理程序,其中很多处理程序在多数情况下是不相关的。这就需要定义一个更易于在多个用例中使用的标记调用协议。在 JSP 2.0 中推出的简单标记扩展提供了一种实现自定义操作的更简易方法,其生命周期也更易于处理。

简单标记扩展除了使工作更容易之外,它们还不直接依赖于任何 Servlet API,这意味着它们为进一步集成其他技术开辟了全新的领域。这一过程已经完成,因为 PageContent 现在扩展了 JspContext。JspContext 提供通用的服务,如存储 JspWriter 以及跟踪限定范围的属性,而 PageContext 具有专门为 Servlet 上下文中的 JSP 提供服务的功能。Tag 接口依赖于 PageContext,而 SimpleTag 只依赖于 JspContext。

简单标记扩展可以由以下两种方法之一来编写:

  • 在 Java 中,通过定义一个实现 javax.servlet.jsp.tagext.SimpleTag 接口的类来编写。该类用于高级页面制作人员和标记库开发人员,他们需要 Java 语言的灵活性,以便编写标记处理程序。javax.servlet.jsp.tagext.SimpleTagSupport 类为 SimpleTag 中的所有方法提供默认的实施。

  • 在 JSP 语法中,使用标记文件编写。利用在 JSP 语法中编写自定义操作的功能,页面制作人员(无 Java 的预先知识)、高级页面制作人员或者标记库开发人员(了解 Java,但是开发那些主要是基于模板的表达的标记库)已经受益。

SimpleTag 接口

简单标记处理程序是实现 SimpleTag 接口的处理程序。值得注意的是,当需要 Java 语言的灵活性来编写标记处理程序时,提供这种接口。

由 SimpleTag 使用的调用协议是由传统标记处理程序所使用的调用协议简化而成。javax.servlet.jsp.tagext.SimpleTagSupport 类为 SimpleTag 中所有方法提供了默认的实施。完整的接口定义如下所示:

public interface SimpleTag extends JspTag {
public void doTag()throws JspException, java.io.IOException;
public void setParent(JspTag parent);
public JspTag getParent();
public void setJspContext(JspContext pc);
public void setJspBody(JspFragment jspBody);
}

注意 SimpleTag 接口直接从 JspTag 扩展而成,并没有扩展 Tag,这很重要。这意味着 SimpleTag 内部没有嵌入任何固有的 JSP/Servlet 知识。另一个值得注意的不同之处在于,SimpleTag 只有一个生命周期方法 doTag(),其定义为:

public void doTag()throws JspException, java.io.IOException

对于任何给定的标记调用,只调用一次 doTag() 方法。这意味着与该标记相关的所有代码(包括标记逻辑、迭代或主体赋值)都包含在一个良好简洁的方法中。如果将它与 IterationTag 接口相比较,则会注意到用它来完成工作有多么容易。

它提供 setJspBody() 方法来支持主体内容。容器调用 setJspBody() 方法,利用 JspFragment 对象来封装标记的主体。标记处理程序实施可以在该片段上调用 invoke(),为主体赋值。方便的 SimpleTagSupport 类提供 getJspBody() 和其他有用的方法,使得此过程更加容易。

大部分 SimpleTag 处理程序应该扩展 javax.servlet.jsp.tagext.SimpleTagSupport。这是很方便的类,与 TagSupport 或 BodyTagSupport 类似。该类中还包括一些有用的方法,包括:

  • public JspFragment getJspBody() 方法,它返回由容器通过 setJspBody 所传递的主体。JspFragment 封装标记的主体。如果 JspFragment 为空,则表示标记的主体内容类型为空。

  • public static final JspTag findAncestorWithClass(JspTag from, java.lang.Class klass),它找出给定类的类型实例(最接近给定的实例)。该方法从 Tag 和/或 Simple Tag 接口使用 getParent() 方法。该方法用于协作标记间的对等操作。当遍历祖先时,对于遇到的每个 TagAdapter 实例(用于允许在传统标记处理程序与 SimpleTag 处理程序之间进行协作),将 TagAdapter.getAdaptee() 所返回的标记处理程序与 klass 相比较。在标记处理程序与该类匹配而不是与其 TagAdapter 匹配时,返回该标记处理程序。

SimpleTag 语法

SimpleTag 的基本语法是:

public interface SimpleTag extends JspTag

以上语法为简单标记处理程序定义了接口。简单标记处理程序与传统标记处理程序的不同之处在于,SimpleTag 接口不支持 doStartTag() 和 doEndTag(),而是提供一个简单的 doTag() 方法,该方法对任何给定的标记调用进行一次调用,且仅一次。在此单个方法中执行所有的标记逻辑、迭代、主体赋值等。因此,简单标记处理程序具有与 BodyTag 相同的功能,但却具有更加简单的生命周期和接口。

为支持主体内容,它提供了 setJspBody() 方法。容器调用 setJspBody() 方法,利用 JspFragment 对象来封装标记的主体。标记处理程序实施可以在该片段上调用 invoke(),根据需要任意多次为主体赋值。

值得注意的是,SimpleTag 处理程序必须具有一个公共的无参数结构符。多数 SimpleTag 处理程序应该扩展 SimpleTagSupport。

简单标记处理程序的生命周期

当 JSP 中需要简单标记处理程序时,由容器对其进行实例化,从而执行然后放弃该程序。在使用该接口时,没有复杂的高速缓存语义,因为不对任何内容进行高速缓存或重用。专家组发现,使用高速缓存机制获得的性能增益显著地增加了编写轻便标记处理程序的难度,并且使处理程序易于出现错误。

如果性能因素非常关键,我建议首先将标记处理程序作为简单标记进行实施,然后在进行更加复杂和耗费时间的传统处理程序编写之前,采用某些性能量度来查看您的标准是否得到满足。

简单标记处理程序发生以下的生命周期事件(以相同顺序):

1. 每次容器遇到标记时,创建新的标记处理程序实例。通过在相应的实施类上调用零参数构造符,完成此过程。注意必须为每个标记调用创建新实例,这很重要。

2. 在标记处理程序中调用 setJspContext() 和 setParent() 方法。如果传递的值是“null”,则不需要调用 setParent() 方法。在使用标记文件的情况下,创建一个 JspContext 包装,以便标记文件看上去具有其本身的页面范围。调用 getJspContext() 必须返回所包装的 JspContext。

3. 容器为每个为该标记所定义的属性而调用设置器,其顺序是它们出现在 JSP 页或标记文件中的顺序。如果属性值是表达式语言的表达式或运行时表达式,则它首先被赋值,然后被传递到设置器。另一方面,如果属性为动态属性,则调用 setDynamicAttribute()。

4. 由容器调用 setJspBody() 方法,将该标记的主体设置为 JspFragment。如果标记被声明为具有空的 ,则将 null 值传递到 setJspBody()。

5. 由容器调用 doTag() 方法。所有的标记逻辑、迭代、主体赋值等都在该方法中发生。

6. 在 doTag() 方法返回后,所有的变量被同步。


讨论此教程。 可打印版本 (PDF)。
这是目录页。 无上一页。 到上一级。 转至下一页。
寄送此页面
Printer View 打印机视图