本教程将概述如何创建 Jakarta-Taglibs 库中的一些基本标记。标记库允许您创建自定义操作并封装功能。自定义标记可以明确地将表示层与业务逻辑分开。它们是易于维护的可重用组件,可以访问 JSP 页面可用的所有对象。有关更多详细信息,请参阅JavaServer Pages 规范,版本 1.2。
实现 JSP v1.1+ 的服务器支持标记库。您可以在JavaServer Pages 行业发展势头页面上找到各种服务器及其当前支持的描述。Sun 网站上还提供了非常好的Java Web 服务教程,其中包括自定义标记和JSP 标准标记库 (JSTL)部分。
标记处理程序负责 JSP 页面与其他服务器端对象之间的交互。在执行 JSP 页面时,当遇到自定义标记时会调用处理程序。doStartTag() 和 doEndTag() 方法分别在遇到自定义标记的开始和结束标记时调用。 release() 方法释放标记处理程序分配的资源。
有两个描述标记处理程序的接口
标记 | 用于对不感兴趣于操作其主体内容的简单标记处理程序 |
主体标记 | 标记的扩展,允许处理程序访问其主体 |
标记处理程序有两个主要操作方法
doStartTag() |
处理此操作的开始标记。 |
doEndTag() | 处理此操作的结束标记。在从 doStartTag 返回后调用。 |
release() | 释放资源 |
doStartTag() 返回以下内容
- EVAL_BODY_INCLUDE
- 处理操作的主体,但不要创建新的 BodyContent。原样传递主体,不进行操作。仅在不实现 BodyTag 接口时有效。
- EVAL_BODY_TAG
- 处理操作的主体并创建新的 BodyContent。仅在实现 BodyTag 接口时有效。
- SKIP_BODY
- 不评估标记的主体
doEndTag() 返回以下内容
- EVAL_PAGE
- 将评估 JSP 页面的其余部分
- SKIP_PAGE
- 将不评估 JSP 页面的其余部分
返回值指示 JSP 容器如何评估 JSP 页面的其余部分。release() 方法释放标记处理程序分配的资源。
TagSupport 和 BodyTagSupport 是 Tag 的子类,可以在创建新标记处理程序时用作基类。
TagSupport 类是一个实用程序类,它实现了 Tag 接口并添加了其他便利方法,包括
如果标记处理程序操作操作的主体,则它必须实现 BodyTag 接口。doStartTag() 必须返回 EVAL_BODY_TAG 才能评估标记的主体。如果返回 SKIP_BODY,则主体将被忽略。与主体内容交互的方法包括
doInitBody() | 在标记主体评估之前调用,但在设置主体内容之后 |
doAfterBody() | 在主体内容评估之后调用 |
BodyTagSupport 类实现了 BodyTag 接口并添加了其他便捷方法。其中一些方法包括
在 Web 应用程序中,处理程序必须位于以下标准位置之一,用于 Java 类
标记处理程序可以访问一些由 JSP 容器使用 setter 方法设置的属性。这包括 pageContext 和 parent 对象。标记处理程序还可以访问服务器端对象和封闭操作。如果标记是嵌套的,则可以通过使用以下任一方法访问封闭标记的父处理程序
检索父对象后,可以获取父处理程序的静态和动态创建的对象。
标记库描述符 (TLD) 由 JSP 容器用于解释包含引用该标记库的 taglib 指令的页面。它是一个 XML 文档,将操作标记映射到标记处理程序类。您可以通过两种方式找到 TLD
您可以在 Servlet 2.2 和 JSP 1.1 规范中找到有关 web.xml taglib 元素的更多信息。
由于最近更改为调用验证解析器,您需要明确引用外部 DOCTYPE
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
TLD taglib 元素是文档根。它具有以下子元素
tlibversion | 标记库实现的版本 |
jspversion | 标记库所需的 JSP 规范版本 |
shortname | 可用于从 JSP 页面引用标记库的名称 |
uri | 唯一标识标记库的 uri - 描述标记库“用途”的信息字符串 |
info | 描述标记库“用途”的字符串 |
标签元素定义标签库中的一个操作。它可能具有多个子元素,这些子元素定义操作
name | 唯一操作名称 |
tagclass | 实现 javax.servlet.jsp.tagext.Tag 的标签处理程序类 |
teiclass | javax.servlet.jsp.tagext.TagExtraInfo 的可选子类 |
bodycontent |
三种正文内容类型之一 |
info |
可选的标签特定信息 |
attribute |
操作的所有属性 |
如果标签具有正文,则包含 bodycontent。它由页面组合工具使用,因此不会影响正文的组合。它可以是以下三种类型之一
- JSP(默认)
- JSP 容器应该计算标签的任何正文,但它也可以为空
- tagdependent
- 标签的任何正文都将由标签本身处理,但它也可以为空
- empty
- 正文必须为空
teiclass 定义脚本变量并包括以下信息
- name
- type
- 是否需要创建变量
- scope
attributes 可以具有以下字段
- name(必需)
- 属性名称
- required
- 如果属性是必需的还是可选的
- rtexprvalue
- 如果属性值可以在运行时由脚本动态计算。注意:默认值为“false”,表示属性具有静态值。如果属性值在请求时确定,请务必将其设置为“true”。
对于每个属性,您必须在标签处理程序中具有 JavaBeans 样式的 get 和 set 方法。如果您的属性名为 id,则 TagSupport 类为您定义 setId() 和 getId() 方法。
JavaServer Pages 可以处理封装在标签库操作中的 XML 内容。
<%@ taglib uri="identifier" prefix="prefix" %>
要使用标签库,您需要使用 taglib 指令告诉 JSP 容器它位于何处。该指令必须在任何操作之前。
要安装标记库,您需要执行以下步骤
<taglib> <taglib-uri>http://jakarta.apache.org/taglibs/{library}</taglib-uri> <taglib-location>/WEB-INF/{library}.tld</taglib-location> </taglib>
<%@ taglib uri="http://jakarta.apache.org/taglibs/{library}" prefix="x" %>
要向 Jakarta-Taglibs 添加标记库子项目,您需要执行以下操作
使用 jakarta-taglibs 项目中的构建脚本创建 war 文件。构建 war 文件后,您可以简单地将该文件放置在 $TOMCAT_HOME/webapps 目录中。Tomcat 将加载您的类并创建新上下文。
war 文件应具有以下结构
META-INF/ META-INF/MANIFEST.MF WEB-INF/ WEB-INF/classes/ WEB-INF/lib/ WEB-INF/lib/{tagLibrary}.jar WEB-INF/web.xml WEB-INF/{tagLibrary}.tld
如果您不想使用 jar 文件,则可以将所有类文件放置在 /WEB-INF/classes 目录中。
有关 war 文件的更多信息,请参阅 Java Servlet 规范,v2.2。
此基本标记是“Hello World”示例。每当遇到该标记时,都会打印文本“Hello World”。
您可以在 /WEB-INF/classes/basic 目录中找到 Hello World 标记的标记处理程序,因为它属于 basic 包
package basic;
导入 jsp 和标记类
import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*;
Hello World 标记处理程序实现了 doStartTag() 方法,该方法在遇到开始标记时调用。
public int doStartTag() throws JspException { try { pageContext.getOut().print("Hello World"); } catch (Exception ex) { throw new JspException("IO problems"); } return SKIP_BODY; }
JSP 容器设置 pageContext,并且标签处理程序可以使用它。 SKIP_BODY 值确保不评估标签主体。
<?xml version="1.0" encoding="ISO-8859-1" ?>
描述部署描述符 DOCTYPE 的 XML 头。部署描述符包括 Web 应用程序的元素和配置信息。
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
初始标签库描述
<taglib> <!-- The version number of this tag library --> <tlibversion>1.0</tlibversion> <!-- The JSP specification version required to function --> <jspversion>1.1</jspversion> <!-- The short name of this tag library --> <shortname>utility</shortname> <!-- Public URI that uniquely identifies this version of the tag library --> <uri>http://jakarta.apache.org/taglibs/utilitytags</uri> <!-- General information about this tag library --> <info> A simple tag library for the examples </info>
Hello World 标签描述。
<!-- Hello tag --> <tag> <name>Hello</name> <tagclass>basic.Hello</tagclass> <bodycontent>empty</bodycontent> <info> Print Hello World </info> </tag>
web.xml 文件描述标签库 uri 与标签库描述符位置之间的映射。
此处,唯一的 taglib-uri "http://jakarta.apache.org/taglibs/utilitytags" 与 /WEB-INF/tld/utilitytags.tld 中的标签库描述符关联。
<web-app> <taglib> <taglib-uri> http://jakarta.apache.org/taglibs/utilitytags </taglib-uri> <taglib-location> /WEB-INF/tld/utilitytags.tld </taglib-location> </taglib> </web-app>
以下指令告诉 JSP 容器使用 web.xml 中定义的 "http://jakarta.apache.org/taglibs/utilitytags" uri。"jLib" 被定义为该标签的前缀值。
<%@ taglib uri="http://jakarta.apache.org/taglibs/utilitytags" prefix="jLib" %>
调用 Hello World 标签。标签名称 "Hello" 在标签库描述符中定义。
<jLib:Hello/>
此嵌套标签是 "If" 条件标签的一个示例。根据属性值,将评估或跳过包含的脚本片段。
BodyTagSupport 类实现 BodyTag 接口,并具有 bodyContent 属性的 getter 方法。
public class IfTag extends BodyTagSupport {
doStartTag() 方法在遇到开始标签时调用,并调用本地 getPredicate() 方法。如果返回值为 true,则评估标签主体的其余部分,否则跳过它。
public int doStartTag() { if (getPredicate()) return EVAL_BODY_TAG; else return SKIP_BODY; }
doAfterBody() 在评估某些主体后调用。它不会在空标签或在 doStartTag() 中返回 SKIP_BODY 的标签中调用。
public int doAfterBody() throws JspException { try { bodyContent.writeOut(bodyContent.getEnclosingWriter()); return SKIP_BODY; } catch (IOException ex) { throw new JspTagException(ex.toString()); } }
<!-- IF tag --> <tag> <name>If</name> <tagclass>lang.IfTag</tagclass>
If 标签有一个必需的属性。由于 rtexprvalue 设置为 true,因此属性可以将脚本表达式作为值。该值可以在请求时动态计算。
<attribute> <name>predicate</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <info> Conditional Tag. </info> </tag>
web.xml 文件描述标签库 uri 与标签库描述符位置之间的映射。
此处,唯一的 taglib-uri "http://jakarta.apache.org/taglibs/utilitytags" 与 /WEB-INF/tld/utilitytags.tld 中的标签库描述符关联。
If 标签需要一个属性。谓词属性包含一个将在运行时评估的脚本。基于谓词属性值,jLib:Hello 标签将被评估或跳过。
<jlib:if predicate="<%= x==5 %>"> <jLib:Hello/> </jlib:if>
此自定义标签库不需要除支持 JavaServer Pages 规范 1.1 版 的 servlet 容器之外的任何软件。
按照以下步骤使用此标签库配置 Web 应用程序
<taglib> <taglib-uri>http://jakarta.apache.org/taglibs/utilitytags</taglib-uri> <taglib-location>/WEB-INF/utilitytags.tld</taglib-location> </taglib>
要在 JSP 页面中使用此库中的标签,请在每个页面的顶部添加以下指令
<%@ taglib uri="http://jakarta.apache.org/taglibs/utilitytags" prefix="x" %>
For 标签是一个基本的循环标签。
属性
|
说明
|
必需
|
---|---|---|
iterations
|
要完成的循环迭代次数。任何字符串整数值。
|
是
|
varName
|
与 For 循环关联的变量名称。任何字符串值。
|
no
|
begin
|
循环起始值。任何字符串整数值。
|
no
|