JSP 标签的多种实现

JSP 标签的实现方式很多,有点乱,下面简单记录一下各种方式。

标签的内容流程

0. 直接使用标签

这可能是最简单的标签使用方式,直接定义一个标签文件 *.tag,然後直接在 JSP 中使用即可,不用配置 web.xml。*.tag 可设置变量。

详细示例可参考本站的: The Simplest Way to Use JSP Tag (两个例子, 来源于 Tomcat 自带的示例).

生产环境中使用这种方式的,应该比较少。

1. 通过实现 Tag 接口

  1. 写 Tag 类,比如 org.iridium.tags.HelloWorldTag implements Tag
  2. 添加配置文件,比如 /WEB-INF/tlds/mytag.tld
  3. 在 web.xml 中引用配置文件
  4. 在 JSP 页面中使用 tag

这里是这个 HelloWorld 工程的具体实现过程。这是一个简单的例子,只是在前端页面输出一行文字,没有输入。

生产环境中使用这种方式的,应该比较少。

2. 通过继承 SimpleTagSupport 类

表达式语言的函数使用类似,用和上面的比较类似。步骤如下:

  1. 写 Tag 类,注意,它是直接 extends javax.servlet.jsp.tagext.SimpleTagSupport的
  2. 添加配置文件(tld)
  3. 在 web.xml 中引用配置文件
  4. 在 JSP 页面中使用 tag

这里是这个 HelloWorld 工程的详细内容。这是一个简单的例子,只是在前端页面输出一行文字,没有输入。

生产环境中使用这种方式的,可能比较多。

3. 通过标签使用 EL 函数

Expression Language 的最後一节:函数。这种方式使用,可以接受一些输入值,计算之後再返回。

4. 带有属性的标签

这个例子主要是演示如何结合 EL 使用标签的属性(attribute)。整个工程的创建步骤和上面的 Hello World Tag 一致,但Tag类中增添了一个属性,Tag 类是按 JavaBean 的规范书写的,这个属性要使用对应的 setter 来赋值。另外,比上面的 Hello World Tag 工程,标签描述符(TLD)的配置内容要多一些。整个工程的详细内容在这里有介绍。

生产环境中使用这种方式的,可能大量使用的都是这种方式。

5. 其他:Book Example

这个例子是标签结合 EL 使用,附件 bookexample.zip 是工程的源代码。此例的标签配置文件中,可以清楚地看到 tag 和 function 两种元素,可以作一个对比。

FindBookSimpleTag 的实现类中很前面不同的是,把 book 对象设置到标签的某个属性里(这里是 var)。

BookBean book = new BookBean(BOOK_TITLE, BOOK_AUTHOR, BOOK_ISBN);
getJspContext().setAttribute(this.var, book);

上面的代码把得到的 book 对象设置到名为 var 的域中,其实是配置文件中所指的属性。

在页面中,有如下代码:

<bk:findBook var="book" />

这相当于得到了 FindBookSimpleTag 中找到的 BookBean 对象,并命名为 book。如果这里是

<bk:findBook var="book123" />

接下来的代码就应该是这种:

${book123.title}

注意它们名称的对应关系。

这个例子还调用了 BookBean,这里比较简单,但实际的生产环境就可能很复杂了。

以上的使用方式很有趣,事实上,很多公司自建的标签库就采用这种方式:在标签里设置好几个属性,其中一个属性是为了存放对象供後面的页面代码调用的。为了区分这些属性,甚至把这个值(如本例中的 var)称为输出,让你一时找不到北。可惜这个例子的标签中,只有一个属性,无法明确区分用作输入和输出的属性。本例中的属性明显可以认为是作为输出的。

有关输出——对4,5两例的说明

通过4和5两个例子,发现输出的内容其实是 JspContext 这个 Map 中的内容。

  1. 把输出值,设置到一个 variable 中。如4中的 getJspContext().setAttribute("count", String.valueOf(i + 1));,配置标签库文件的 variable 元素,名称和 前面的 Java 代码中相同,页面通过 EL 调用时,也使用这个名称。这种使用方式有比较明显的瑕疵,就是 key 不能在页面上自定义。
  2. 通过页面中标签的属性把 key 的值传进去,然後存入值时,使用这个 key,这种方式比较灵活,可以使用自定义的变量值。如5中的 getJspContext().setAttribute(this.var, book);,这里的 this.var 就是页面传进去的 key 值。这个看起来是把输出值,设置到页面标签已存在的 attribute 中,其实不然。