首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

JSTL入门:core (2)

2012-10-24 
JSTL入门:core (二)通过阅读本系列的 第一篇文章,您对 JSTL 有了初步的了解。我们描述了使用其 表达式语言(

JSTL入门:core (二)

通过阅读本系列的 第一篇文章,您对 JSTL 有了初步的了解。我们描述了使用其 表达式语言(EL)来访问数据和操作数据。正如您所了解的那样,EL 用来为 JSTL 定制标记的属性赋予动态值,因此,它所起的作用与 JSP 表达式一样,为内置操作及其它定制标记库指定请求时的属性值。

为了演示 EL 的用法,我们介绍了 core 库中的三个标记: <c:set><c:remove><c:out><c:set><c:remove> 用于管理限定了作用域的变量;而 <c:out> 用于显示数据,尤其是显示用 EL 计算出的值。在此基础上,接下来本文把注意力集中在 core 库的其余标记上,这些标记可以大致归为两大类别:流控制和 URL 管理。

?

name" begin=" expression" end=" expression" step=" expression"> body content</c:forEach>

?

当出现 step 时,它也必须是整数值。它指定每次迭代后索引的增量。这样,迭代索引从 begin 属性的值开始,以 step 属性的值为增量进行递增,在迭代索引超过 end 属性的值时停止迭代。注:如果省略了 step 属性,那么步长缺省为 1。

如果指定了 var 属性,那么将会创建一个带有指定名称的并限定了作用域的变量,并将每次迭代的当前索引值赋给该变量。这一限定了作用域的变量具有嵌套式可视性 ― 只可以在 <c:forEach> 标记体内对其进行访问。(我们很快将讨论可选属性 varStatus 的用法。)清单 2 显示了对一组固定整数值进行迭代的 <c:forEach> 操作示例。


清单 2. 使用 <c:forEach> 标记来生成表列数据,这些数据对应于某一范围内的数值

?

如图 3 中所示,上面的示例代码生成了一张表,显示前五个偶数及其平方。这是通过将 beginstep 属性值指定为 2,而将 end 属性值指定为 10 实现的。此外,用 var 属性创建用于存储索引值的限定了作用域的变量, <c:forEach> 标记体内引用了该变量。尤其是,使用了一对 <c:out> 操作来显示索引及其平方,其中索引的平方是使用一个简单的表达式计算得来的。


?

在对集合的成员进行迭代时,用到了 <c:forEach> 标记的另一个属性: items 属性,清单 3 中显示了该属性。当使用这种形式的 <c:forEach> 标记时, items 属性是唯一必需的属性。 items 属性的值应该是一个集合,对该集合的成员进行迭代,通常使用 EL 表达式指定值。如果变量名称是通过 <c:forEach> 标记的 item 属性指定的,那么对于每次迭代该已命名变量都将被绑定到集合后续元素上。


清单 3. 通过 <c:forEach> 操作对集合进行迭代的语法

expression" varStatus=" name" begin=" expression" end=" expression" step=" expression"> body content</c:forEach>

?

<c:forEach> 标记支持 Java 平台所提供的所有标准集合类型。此外,您可以使用该操作来迭代数组(包括基本类型数组)中的元素。表 1 列出了 items 属性所支持的所有值。正如表的最后一行所指出的那样,JSTL 定义了它自己的接口 javax.servlet.jsp.jstl.sql.Result ,用来迭代 SQL 查询的结果。(我们将在本系列后面的文章中详细讨论这一功能。)


?

不论是对整数还是对集合进行迭代, <c:forEach> 剩余的属性 varStatus 所起的作用相同。和 var 属性一样, varStatus 用于创建限定了作用域的变量。不过,由 varStatus 属性命名的变量并不存储当前索引值或当前元素,而是赋予 javax.servlet.jsp.jstl.core.LoopTagStatus 类的实例。该类定义了一组特性,它们描述了迭代的当前状态,表 2 中列出了这些特性。

?

<c:forEach> 以外, core 库还提供了另一个迭代标记: <c:forTokens> 。JSTL 的这个定制操作与 Java 语言的 StringTokenizer 类的作用相似。清单 6 中显示的 <c:forTokens> 标记除了比 <c:forEach> 的面向集合版本多一个属性之外,其它属性都相同。对于 <c:forTokens> 而言,通过 items 属性指定要标记化的字符串,而通过 delims 属性提供用于生成标记的一组定界符。和 <c:forEach> 的情形一样,可以使用 beginendstep 属性将要处理的标记限定为那些与相应索引值相匹配的标记。


清单 6. 使用 <c:forTokens> 操作来迭代字符串标记的语法

expression" delims=" expression" varStatus=" name" begin=" expression" end=" expression" step=" expression"> body content</c:forTokens>

?

name" scope=" scope"> body content</c:if>

?

清单 8 显示了与 <c:forEach> 标记的 LoopTagStatus 对象的 first 特性一起使用的 <c:if> 。在这种情况下,只在 Weblog 项的第一项上显示这组项的创建日期,而不在任何其它项前面重复该日期。


清单 8. 使用 <c:if> 来为 Weblog 项显示日期

?

如清单 8 所示, <c:if> 标记为条件化内容的一些简单情形提供了一种非常简洁的表示法。对于需要进行互斥测试来确定应该显示什么内容的情况下,JSTL core 库还提供了 <c:choose> 操作。清单 9 中显示了 <c:choose> 的语法。


清单 9. <c:choose> 操作的语法

expression" var=" name" scope=" scope"> <c:param name=" expression" value=" expression"/> ...</c:url>

?

URL 重写是由 <c:url> 操作自动执行的。如果 JSP 容器检测到一个存储用户当前会话标识的 cookie,那么就不必进行重写。但是,如果不存在这样的 cookie,那么 <c:url> 生成的所有 URL 都会被重写以编码会话标识。注:如果在随后的请求中存在适当的 cookie,那么 <c:url> 将停止重写 URL 以包含该标识。

如果为 var 属性提供了一个值(还可以同时为 scope 属性提供一个相应的值,这是可选的),那么将生成的 URL 赋值给这个限定了作用域的指定变量。否则,将使用当前的 JspWriter 输出生成的 URL。这种直接输出其结果的能力允许 <c:url> 标记作为值出现,例如,作为 HTML <a> 标记的 href 属性的值,如清单 13 中所示。


清单 13. 生成 URL 作为 HTML 标记的属性值

?

清单 14 中的 JSP 代码被部署到一个名为 blog 的 servlet 上下文,限定了作用域的变量 searchTerm 的值被设置为 "core library" 。如果检测到了会话 cookie,那么清单 14 生成的 URL 将类似于清单 15 中的 URL。注:在前面添加上下文名称,而在后面附加请求参数。此外, keyword 参数值中的空格和 month 参数值中的斜杠都被按照 HTTP GET 参数的需要进行了编码(确切地说,空格被转换成了 + ,而斜杠被转换成了 %2F 序列)。


清单 15. 有会话 cookie 时生成的 URL

expression" charEncoding=" expression" var=" name" scope=" scope"> <c:param name=" expression" value=" expression"/> ...</c:import>

?

通过 url 属性指定将要导入内容的 URL,这个属性是 <c:import> 的唯一一个必选属性。这里允许使用相对 URL,并且根据当前页面的 URL 来解析这个相对 URL。但是,如果 url 属性的值以斜杠开始,那么它就被解释成本地 JSP 容器内的绝对 URL。如果没有为 context 属性指定值,那么就认为这样的绝对 URL 引用当前 servlet 上下文内的资源。如果通过 context 属性显式地指定了上下文,那么就根据指定的 servlet 上下文解析绝对(本地)URL。

<c:import> 操作并不仅仅限于访问本地内容。也可以将包含协议和主机名的完整 URI 指定为 url 属性的值。实际上,协议甚至不仅局限于 HTTP。 <c:import>url 属性值可以使用 java.net.URL 类所支持的任何协议。清单 18 中显示了这种能力。

其中, <c:import> 操作用来包含通过 FTP 协议访问的文档内容。此外,还使用了 <c:catch> 操作,以便在本地处理 FTP 文件传送期间可能发生的任何错误。错误处理是这样实现的:使用 <c:catch>var 属性为异常指定一个限定了作用域的变量,然后使用 <c:if> 检查其值。如果产生了异常,那么就会对那个限定了作用域的变量进行赋值:如清单 18 中的 EL 表达式所显示的那样,该变量的值将 会为空。由于 FTP 文档的检索将会失败,因此会显示有关这种情况的错误消息。


清单 18. 将 <c:import> 与 <c:catch> 相结合的示例

expression"> <c:param name=" expression" value=" expression"/> ...</c:redirect>

?

清单 20 显示了 <c:redirect> 操作,它用一个到指定错误页面的重定向代替了清单 18 中的错误消息。在该示例中, <c:redirect> 标记的用法与标准 <jsp:forward> 操作的用法类似。不过请回忆一下:通过请求分派器进行转发是在服务器端实现的,而重定向却是由浏览器来执行的。从开发人员的角度来讲,转发比重定向更有效率,但 <c:redirect> 操作却更灵活一些,因为 <jsp:forward> 只能分派到当前 servlet 上下文内的其它 JSP 页面。


清单 20. 响应异常的重定向

<c:catch var="exception">  <c:import url="ftp://ftp.example.com/package/README"/></c:catch><c:if test="${not empty exception}">  <c:redirect url="/errors/remote.jsp"/></c:if>

?

从用户的角度来看,主要区别在于重定向会更新浏览器所显示的 URL,并因此影响书签的设置。转发却不这样,它对最终用户是透明的。这样,选择 <c:redirect> 还是 <jsp:forward> 还取决于所期望的用户体验。

?

结束语

JSTL core 库含有多种通用的定制标记,广大的 JSP 开发人员都会使用这些标记。例如,URL 和异常处理标记很好地补充了现有的 JSP 功能,如 <jsp:include><jsp:forward> 操作、 include 伪指令以及 page 伪指令的 errorpage 属性。迭代和条件操作使得无需脚本编制元素就能够实现复杂的表示逻辑,尤其在将变量标记( <c:set><c:remove> )与 EL 相结合使用时更是如此。

热点排行
Bad Request.