为了演示 EL 的用法,我们介绍了 core 库中的三个标记:、 和 。 和 用于管理限定了作用域的变量;而 用于显示数据,尤其是显示用 EL 计算出的值。在此基础上,接下来本文把注意力集中在 core 库的其余标记上,这些标记可以大致归为两大类别:流控制和 URL 管理。示例应用程序为了演示 JSTL 标记,我们将使用来自一个工作应用程序的示例,本系列中余下的文章都将使用此应用程序。由于基于 Java 的 Weblog 日渐流行及为人们所熟悉,因此我们将出于此目的使用一个简单的基于 Java 的 Weblog;参阅参考资料以下载该应用程序的 JSP 页面和源代码。Weblog(也称为 blog)是一种基于 Web 的简短注释的日志,这些注释是有关 Weblog 的作者所感兴趣的主题,通常带有与 Web 上其它地方的相关文章及讨论的链接。图 1 中显示了该应用程序正在运行时的抓屏。图 1. Weblog 应用程序
虽然完整的实现需要二十四个 Java 类,但在表示层中却只涉及 Weblog 应用程序中的两个类,Entry 和 UserBean。这样,对于理解 JSTL 示例而言,只有这两个类比较重要。图 2 显示了 Entry 和 UserBean 的类图。图 2. Weblog 应用程序的类图
Entry 类表示 Weblog 中一个标有日期的项。其 id 属性用于在数据库中存储及检索该项,而 title 和 text 属性则表示该项的实际内容。created 和 lastModified 属性引用了 Java 语言中 Date 类的两个实例,分别用来表示最初创建该项的时间和最后编辑该项的时间。author 属性引用了标识该项的创建者的 UserBean 实例。UserBean 类存储了有关应用程序的已认证用户的信息,如用户名、全名和电子邮件地址。该类还包含一个用于与相关数据库进行交互的 id 属性。其最后一个属性 roles 引用一列 String 值,这列值标识与相应用户相关的、特定于应用程序的角色。对于 Weblog 应用程序,相关的角色是“User”(所有应用程序用户常用的缺省角色)和“Author”(该角色指定可以创建和编辑 Weblog 项的用户)。流控制由于可以用 EL 替代 JSP 表达式来指定动态属性值,因此页面创作人员无需使用脚本编制元素。因为脚本编制元素可能是引起 JSP 页面中维护问题的主要原因,所以 JSTL 的主要优点就在于提供了这样简单(且标准)的替代方法。EL 从 JSP 容器检索数据,遍历对象层次结构,然后对结果执行简单的操作。不过,除了访问和操作数据之外,JSP 脚本编制元素的另一个常见用法是流控制。尤其是,页面创作人员常借助 scriptlet 来实现迭代或条件内容。然而,因为这样的操作超出了 EL 的能力,所以 core 库提供了几个定制操作来管理流控制,其形式有迭代、条件化和异常处理。迭代在 Web 应用程序环境中,迭代主要用于访存和显示数据集,通常是以列表或表中的一系列行的形式显示。实现迭代内容的主要 JSTL 操作是 定制标记。该标记支持两种不同样式的迭代:整数范围上的迭代(类似 Java 语言的 for 语句)和集合上的迭代(类似 Java 语言的 Iterator 和 Enumeration 类)。进行整数范围迭代用到了清单 1 中所示的 标记的语法。begin 和 end 属性要么是静态整数值,要么是可以得出整数值的表达式。它们分别指定迭代索引的初始值以及迭代索引的终止值。当使用 在整数范围内进行迭代时,这两个属性是必需的,而其它所有属性都是可选的。清单 1. 通过 操作进行数字迭代的语法body content当出现 step 时,它也必须是整数值。它指定每次迭代后索引的增量。这样,迭代索引从 begin 属性的值开始,以 step 属性的值为增量进行递增,在迭代索引超过 end 属性的值时停止迭代。注:如果省略了 step 属性,那么步长缺省为 1。如果指定了 var 属性,那么将会创建一个带有指定名称的并限定了作用域的变量,并将每次迭代的当前索引值赋给该变量。这一限定了作用域的变量具有嵌套式可视性 ― 只可以在 标记体内对其进行访问。(我们很快将讨论可选属性 varStatus 的用法。)清单 2 显示了对一组固定整数值进行迭代的 操作示例。清单 2. 使用 标记来生成表列数据,这些数据对应于某一范围内的数值。ValueSquare
如图 3 中所示,上面的示例代码生成了一张表,显示前五个偶数及其平方。这是通过将 begin 和 step 属性值指定为 2,而将 end 属性值指定为 10 实现的。此外,用 var 属性创建用于存储索引值的限定了作用域的变量, 标记体内引用了该变量。尤其是,使用了一对 操作来显示索引及其平方,其中索引的平方是使用一个简单的表达式计算得来的。图 3. 清单 2 的输出
在对集合的成员进行迭代时,用到了 标记的另一个属性:items 属性,清单 3 中显示了该属性。当使用这种形式的 标记时,items 属性是唯一必需的属性。items 属性的值应该是一个集合,对该集合的成员进行迭代,通常使用 EL 表达式指定值。如果变量名称是通过 标记的 item 属性指定的,那么对于每次迭代该已命名变量都将被绑定到集合后续元素上。清单 3. 通过 操作对集合进行迭代的语法body content 标记支持 Java 平台所提供的所有标准集合类型。此外,您可以使用该操作来迭代数组(包括基本类型数组)中的元素。表 1 列出了 items 属性所支持的所有值。正如表的最后一行所指出的那样,JSTL 定义了它自己的接口 javax.servlet.jsp.jstl.sql.Result,用来迭代 SQL 查询的结果。(我们将在本系列后面的文章中详细讨论这一功能。)表 1. 标记的 items 属性所支持的集合可以使用 begin、end 和 step 属性来限定在迭代中包含集合中哪些元素。和通过 进行数字迭代的情形一样,在迭代集合中的元素时同样要维护一个迭代索引。 标记实际上只处理那些与索引值相对应的元素,这些索引值与指定的 begin、end 和 step 值相匹配。清单 4 显示了用来迭代集合的 标记。对于该 JSP 代码段,entryList 这一限定了作用域的变量被设置成了 Entry 对象列表(确切的说,ArrayList)。 标记依次处理列表中的每个元素,将其赋给一个限定了作用域的变量 blogEntry,然后生成两个表行 ― 一个用于 Weblog 项的 title,另一个则用于该项 text。这些特性是通过一对带有相应 EL 表达式的 操作从 blogEntry 变量检索得到的。注:由于 Weblog 项的标题和文本都可能包含 HTML 标记,因此这两个 标记的 escapeXml 属性都被设置成了 false。图 4 显示了结果。清单 4. 使用 标记显示表示给定日期的 Weblog 项
图 4. 清单 4 的输出
不论是对整数还是对集合进行迭代, 剩余的属性 varStatus 所起的作用相同。和 var 属性一样,varStatus 用于创建限定了作用域的变量。不过,由 varStatus 属性命名的变量并不存储当前索引值或当前元素,而是赋予 javax.servlet.jsp.jstl.core.LoopTagStatus 类的实例。该类定义了一组特性,它们描述了迭代的当前状态,表 2 中列出了这些特性。表 2. LoopTagStatus 对象的特性清单 5 显示了关于如何使用 varStatus 属性的一个示例。这个示例修改了清单 4 中的代码,将 Weblog 项的编号添加到显示 Weblog 标题(title)的表行。它是通过为 varStatus 属性指定一个值,然后访问所生成的限定了作用域的变量的 count 特性来实现这一点的。结果显示在图 5 中。清单 5. 使用 varStatus 属性来显示 Weblog 项的数目