|
|
内容: |
|
|
|
相关内容: |
|
|
<!--Related Zone content--> |
|
<!--Related Zone Navigation content-->
|
|
|
使用定制标记进行流控制和 URL 管理
Mark A. Kolb(mak@taglib.com) 软件工程师 2003 年 6 月
顾名思义,JSP 标准标记库(JSP Standard Tag Library,JSTL)core 库为一些基本功能(如,管理限定了作用域的变量和与 URL 交互等)和基本操作(如,迭代和条件化)提供了定制标记。这些标记不仅可以由页面设计人员直接利用,而且还为与其它 JSTL 库相结合从而提供更复杂的表示逻辑奠定了基础。Mark Kolb 在本文中继续对 JSTL 和 core 库进行探讨,研究用标记来协助流控制和 URL 管理。
通过阅读本系列的第一篇文章,您对 JSTL 有了初步的了解。我们描述了使用其表达式语言(EL)来访问数据和操作数据。正如您所了解的那样,EL 用来为 JSTL 定制标记的属性赋予动态值,因此,它所起的作用与 JSP 表达式一样,为内置操作及其它定制标记库指定请求时的属性值。
为了演示 EL 的用法,我们介绍了 core 库中的三个标记:<c:set> 、<c:remove> 和 <c:out> 。<c:set> 和 <c:remove> 用于管理限定了作用域的变量;而 <c:out> 用于显示数据,尤其是显示用 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 操作是 <c:forEach> 定制标记。该标记支持两种不同样式的迭代:整数范围上的迭代(类似 Java 语言的 for 语句)和集合上的迭代(类似 Java 语言的 Iterator 和 Enumeration 类)。
进行整数范围迭代用到了清单 1 中所示的 <c:forEach> 标记的语法。begin 和 end 属性要么是静态整数值,要么是可以得出整数值的表达式。它们分别指定迭代索引的初始值以及迭代索引的终止值。当使用 <c:forEach> 在整数范围内进行迭代时,这两个属性是必需的,而其它所有属性都是可选的。
清单 1. 通过 <c:forEach> 操作进行数字迭代的语法
<c:forEach var="name" varStatus="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> 标记来生成表列数据,这些数据对应于某一范围内的数值。
<table> <tr><th>Value</th> <th>Square</th></tr> <c:forEach var="x" begin="0" end="10" step="2"> <tr><td><c:out value="${x}"/></td> <td><c:out value="${x * x}"/></td></tr> </c:forEach> </table>
|
如图 3 中所示,上面的示例代码生成了一张表,显示前五个偶数及其平方。这是通过将 begin 和 step 属性值指定为 2,而将 end 属性值指定为 10 实现的。此外,用 var 属性创建用于存储索引值的限定了作用域的变量,<c:forEach> 标记体内引用了该变量。尤其是,使用了一对 <c:out> 操作来显示索引及其平方,其中索引的平方是使用一个简单的表达式计算得来的。
图 3. 清单 2 的输出
在对集合的成员进行迭代时,用到了 <c:forEach> 标记的另一个属性:items 属性,清单 3 中显示了该属性。当使用这种形式的 <c:forEach> 标记时,items 属性是唯一必需的属性。items 属性的值应该是一个集合,对该集合的成员进行迭代,通常使用 EL 表达式指定值。如果变量名称是通过 <c:forEach> 标记的 item 属性指定的,那么对于每次迭代该已命名变量都将被绑定到集合后续元素上。
清单 3. 通过 <c:forEach> 操作对集合进行迭代的语法
<c:forEach var="name" items="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 查询的结果。(我们将在本系列后面的文章中详细讨论这一功能。)
表 1. <c:forEach> 标记的 items 属性所支持的集合
items 的值 |
所产生的 item 值 |
java.util.Collection |
调用 iterator() 所获得的元素 |
java.util.Map |
java.util.Map.Entry 的实例 |
java.util.Iterator |
迭代器元素 |
java.util.Enumeration |
枚举元素 |
Object 实例数组 |
数组元素 |
基本类型值数组 |
经过包装的数组元素 |
用逗号定界的 String
|
子字符串 |
javax.servlet.jsp.jstl.sql.Result |
SQL 查询所获得的行 |
可以使用 begin 、end 和 step 属性来限定在迭代中包含集合中哪些元素。和通过 <c:forEach> 进行数字迭代的情形一样,在迭代集合中的元素时同样要维护一个迭代索引。<c:forEach> 标记实际上只处理那些与索引值相对应的元素,这些索引值与指定的 begin 、end 和 step 值相匹配。
清单 4 显示了用来迭代集合的 <c:forEach> 标记。对于该 JSP 代码段,entryList 这一限定了作用域的变量被设置成了 Entry 对象列表(确切的说,ArrayList )。<c:forEach> 标记依次处理列表中的每个元素,将其赋给一个限定了作用域的变量 blogEntry ,然后生成两个表行 — 一个用于 Weblog 项的 title ,另一个则用于该项 text 。这些特性是通过一对带有相应 EL 表达式的 <c:out> 操作从 blogEntry 变量检索得到的。注:由于 Weblog 项的标题和文本都可能包含 HTML 标记,因此这两个 <c:out> 标记的 escapeXml 属性都被设置成了 false。图 4 显示了结果。
清单 4. 使用 <c:forEach> 标记显示表示给定日期的 Weblog 项
<table> <c:forEach items="${entryList}" var="blogEntry"> <tr><td align="left" class="blogTitle"> <c:out value="${blogEntry.title}" escapeXml="false"/> </td></tr> <tr><td align="left" class="blogText"> <c:out value="${blogEntry.text}" escapeXml="false"/> </td></tr> </c:forEach> </table>
|
图 4. 清单 4 的输出
不论是对整数还是对集合进行迭代,<c:forEach> 剩余的属性 varStatus 所起的作用相同。和 var 属性一样,varStatus 用于创建限定了作用域的变量。不过,由 varStatus 属性命名的变量并不存储当前索引值或当前元素,而是赋予 javax.servlet.jsp.jstl.core.LoopTagStatus 类的实例。该类定义了一组特性,它们描述了迭代的当前状态,表 2 中列出了这些特性。
表 2. LoopTagStatus 对象的特性
特性 |
Getter |
描述 |
current |
getCurrent() |
当前这次迭代的(集合中的)项 |
index |
getIndex() |
当前这次迭代从 0 开始的迭代索引 |
count |
getCount() |
当前这次迭代从 1 开始的迭代计数 |
first |
isFirst() |
用来表明当前这轮迭代是否为第一次迭代的标志 |
last |
isLast() |
用来表明当前这轮迭代是否为最后一次迭代的标志 |
begin |
getBegin() |
begin 属性值 |
end |
getEnd() |
end 属性值 |
step |
getStep() |
step 属性值 |
清单 5 显示了关于如何使用 varStatus 属性的一个示例。这个示例修改了清单 4 中的代码,将 Weblog 项的编号添加到显示 Weblog 标题(title)的表行。它是通过为 varStatus 属性指定一个值,然后访问所生成的限定了作用域的变量的 count 特性来实现这一点的。结果显示在图 5 中。
清单 5. 使用 varStatus 属性来显示 Weblog 项的数目
<table> <c:forEach items= "${entryList}" var="blogEntry" varStatus="status"> <tr><td align="left" class="blogTitle"> <c:out value="${status.count}"/>. <c:out value="${blogEntry.title}" escapeXml="false"/> </td></tr> <tr><td align="left" class="blogText"> <c:out value="${blogEntry.text}" escapeXml="false"/> </td></tr> </c:forEach> </table>
|
图 5. 清单 5 的输出
除 <c:forEach> 以外,core 库还提供了另一个迭代标记:<c:forTokens> 。JSTL 的这个定制操作与 Java 语言的 StringTokenizer 类的作用相似。清单 6 中显示的 <c:forTokens> 标记除了比 <c:forEach> 的面向集合版本多一个属性之外,其它属性都相同。对于 <c:forTokens> 而言,通过 items 属性指定要标记化的字符串,而通过 delims 属性提供用于生成标记的一组定界符。和 <c:forEach> 的情形一样,可以使用 begin 、end 和 step 属性将要处理的标记限定为那些与相应索引值相匹配的标记。
清单 6. 使用 <c:forTokens> 操作来迭代字符串标记的语法
<c:forTokens var="name" items="expression" delims="expression" varStatus="name" begin="expression" end="expression" step="expression"> body content </c:forTokens>
|
条件化 对于包含动态内容的 Web 页面,您可能希望不同类别的用户看到不同形式的内容。例如,在我们的 Weblog 中,访问者应该能够阅读各项,也许还应该能够提交反馈,但只有经过授权的用户才能公布新项,或编辑已有内容。
在同一个 JSP 页面内实现这样的功能,然后使用条件逻辑来根据每条请求控制所显示的内容,这样做常常能够改善实用性和软件维护。core 库提供了两个不同的条件化标记 — <c:if> 和 <c:choose> — 来实现这些功能。
<c:if> 是这两个操作中较简单的一个,它简单地对单个测试表达式进行求值,接下来,仅当对表达式求出的值为 true 时,它才处理标记的主体内容。如果求出的值不为 true ,就忽略该标记的主体内容。如清单 7 所示,<c:if> 可以通过其 var 和 scope 属性(它们所起的作用和在 <c:set> 中所起的作用一样)选择将测试结果赋给限定了作用域的变量。当测试代价非常高昂时,这种能力尤为有用:可以将结果高速缓存在限定了作用域的变量中,然后在随后对 <c:if> 或其它 JSTL 标记的调用中检索该结果。
清单 7. <c:if> 条件操作的语法
<c:if test="expression" var="name" scope="scope"> body content </c:if>
|
清单 8 显示了与 <c:forEach> 标记的 LoopTagStatus 对象的 first 特性一起使用的 <c:if> 。如图 6 中所示,在这种情况下,只在 Weblog 项的第一项上显示这组项的创建日期,而不在任何其它项前面重复该日期。
清单 8. 使用 <c:if> 来为 Weblog 项显示日期
<table> <c:forEach items= "${entryList}" var="blogEntry" varStatus="status"> <c:if test="${status.first}"> <tr><td align="left" class="blogDate"> <c:out value="${blogEntry.created}"/> </td></tr> </c:if> <tr><td align="left" class="blogTitle"> <c:out value="${blogEntry.title}" escapeXml="false"/> </td></tr> <tr><td align="left" class="blogText"> <c:out value="${blogEntry.text}" escapeXml="false"/> </td></tr> </c:forEach> </table>
|
图 6. 清单 8 的输出
如清单 8 所示,<c:if> 标记为条件化内容的一些简单情形提供了一种非常简洁的表示法。对于需要进行互斥测试来确定应该显示什么内容的情况下,JSTL core 库还提供了 <c:choose> 操作。清单 9 中显示了 <c:choose> 的语法。
清单 9. <c:choose> 操作的语法
<c:choose> <c:when test="expression"> body content </c:when> ... <c:otherwise> body content </c:otherwise> </c:choose>
|
每个要测试的条件都由相应的 <c:when> 标记来表示,至少要有一个 <c:when> 标记。只会处理第一个其 test 值为 true 的 <c:when> 标记体内的内容。如果没有一个 <c:when> 测试返回 true ,那么会处理 <c:otherwise> 标记的主体内容。注:尽管如此,<c:otherwise> 标记却是可选的;<c:choose> 标记至多可有一个嵌套的 <c:otherwise> 标记。如果所有 <c:when> 测试都为 false ,而且又没有给出 <c:otherwise> 操作,那么不会处理任何 <c:choose> 标记的主体内容。
清单 10 显示了运用 <c:choose> 标记的示例。在这里,检索请求对象而获得协议信息(通过 EL 的 pageContext 隐式对象),并用简单的字符串比较对协议信息进行测试。根据这些测试的结果,会显示相应的文本消息。
清单 10. 使用 <c:choose> 进行内容条件化
<c:choose> <c:when test="${pageContext.request.scheme eq 'http'}"> This is an insecure Web session. </c:when> <c:when test="${pageContext.request.scheme eq 'https'}"> This is a secure Web session. </c:when> <c:otherwise> You are using an unrecognized Web protocol. How did this happen?! </c:otherwise> </c:choose>
|
异常处理 最后一个流控制标记是 <c:catch> ,它允许在 JSP 页面内进行初级的异常处理。更确切地说,在该标记的主体内容中产生的任何异常都会被捕获并被忽略(即,不会调用标准的 JSP 错误处理机制)。然而,如果产生了一个异常并且已经指定了 <c:catch> 标记的可选属性 var ,那么会将异常赋给(具有页面作用域的)指定的变量,这使得能够在页面自身内部进行定制错误处理。清单 11 显示了 <c:catch> 的语法(稍后在清单 18 中给出一个示例)。
清单 11. <c:catch> 操作的语法
<c:catch var="name"> body content </c:catch>
|
URL 操作 JSTL core 库中的其余标记主要是关于 URL。这些标记中的第一个被适当地命名为 <c:url> 标记,用于生成 URL。尤其是,<c:url> 提供了三个功能元素,它们在为 J2EE Web 应用程序构造 URL 时特别有用:
- 在前面附加当前 servlet 上下文的名称
- 为会话管理重写 URL
- 请求参数名称和值的 URL 编码
清单 12 显示了 <c:url> 标记的语法。value 属性用来指定基本 URL,然后在必要时标记对其进行转换。如果这个基本 URL 以一个斜杠开始,那么会在它前面加上 servlet 的上下文名称。可以使用 context 属性提供显式的上下文名称。如果省略该属性,那么就使用当前 servlet 上下文的名称。这一点特别有用,因为 servlet 上下文名称是在部署期间而不是开发期间决定的。(如果这个基本 URL 不是以斜杠开始的,那么就认为它是一个相对 URL,这时就不必添加上下文名称。)
清单 12. <c:url> 操作的语法
<c:url value="expression" context="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 标记的属性值
<a href="<c:url value='/content/sitemap.jsp'/>">View sitemap</a>
|
最后,如果通过嵌套 <c:param> 标记指定了任何请求参数,那么将会使用 HTTP GET 请求的标准表示法将它们的名称和值添加到生成的 URL 后面。此外,还进行 URL 编码:为了生成有效的 URL,将对这些参数的名称或值中出现的任何字符适当地进行转换。清单 14 演示了 <c:url> 的这种行为。
清单 14. 生成带请求参数的 URL
<c:url value="/content/search.jsp"> <c:param name="keyword" value="${searchTerm}"/> <c:param name="month" value="02/2003"/> </c:url>
|
清单 14 中的 JSP 代码被部署到一个名为 blog 的 servlet 上下文,限定了作用域的变量 searchTerm 的值被设置为 "core library" 。如果检测到了会话 cookie,那么清单 14 生成的 URL 将类似于清单 15 中的 URL。注:在前面添加上下文名称,而在后面附加请求参数。此外,keyword 参数值中的空格和 month 参数值中的斜杠都被按照 HTTP GET 参数的需要进行了编码(确切地说,空格被转换成了 + ,而斜杠被转换成了 %2F 序列)。
清单 15. 有会话 cookie 时生成的 URL
/blog/content/search.jsp?keyword=foo+bar&month=02%2F2003
|
当没有会话 cookie 时,生成的结果如清单 16 中所示。同样,servlet 上下文被添加到了前面,而 URL 编码的请求参数被附加到了后面。不过,除此以外还重写了基本 URL 以包含指定的会话标识。当浏览器发送用这种方式重写的 URL 请求时,JSP 容器自动抽取会话标识,并将请求与相应的会话进行关联。这样,需要会话管理的 J2EE 应用程序就无需依赖由应用程序用户启用的 cookie 了。
清单 16. 没有会话 cookie 时生成的 URL
/blog/content/search.jsp;jsessionid=233379C7CD2D0ED2E9F3963906DB4290 ?keyword=foo+bar&month=02%2F2003
|
导入内容 JSP 有两种内置机制可以将来自不同 URL 的内容合并到一个 JSP 页面:include 伪指令和 <jsp:include> 操作。不过,不管是哪种机制,要包含的内容都必须属于与页面本身相同的 Web 应用程序(或 servlet 上下文)。两个标记之间的主要区别在于:include 伪指令在页面编译期间合并被包含的内容,而 <jsp:include> 操作却在请求处理 JSP 页面时进行。
从本质上讲,core 库的 <c:import> 操作是更通用、功能更强大的 <jsp:include> 版本(好像是 <jsp:include> “服用了兴奋剂”的)。和 <jsp:include> 一样,<c:import> 也是一种请求时操作,它的基本任务就是将其它一些 Web 资源的内容插入 JSP 页面中。如清单 17 中所示,它的语法非常类似于 <c:url> 的语法。
清单 17. <c:import> 操作的语法
<c:import url="expression" context="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> 相结合的示例
<c:catch var="exception"> <c:import url="ftp://ftp.example.com/package/README"/> </c:catch> <c:if test="${not empty exception}"> Sorry, the remote content is not currently available. </c:if>
|
<c:import> 操作的最后两个(可选的)属性是 var 和 scope 。var 属性会导致从指定 URL 获取的内容(作为 String 值)被存储在一个限定了作用域的变量中,而不是包含在当前 JSP 页面中。scope 属性控制该变量的作用域,缺省情况下是页面作用域。如同我们在今后的文章中将要看到的那样,JSTL xml 库中的标记利用了 <c:import> 这种能力,即将整个文档存储在一个限定了作用域的变量中。
还要注意的是,可以使用(可选的)嵌套的 <c:param> 标记来为正在导入的 URL 指定请求参数。与在 <c:url> 中嵌套 <c:param> 标记一样,必要时也要对参数名称和参数值进行 URL 编码。
请求重定向 最后一个 core 库标记是 <c:redirect> 。该操作用于向用户的浏览器发送 HTTP 重定向响应,它是 JSTL 中与 javax.servlet.http.HttpServletResponse 的 sendRedirect() 方法功能相当的标记。清单 19 中显示了该标记的 url 和 context 属性,它们的行为分别等同于 <c:import> 的 url 和 context 属性的行为,是嵌套任何 <c:param> 标记的结果。
清单 19. <c:redirect> 操作的语法
<c:redirect url="expression" context="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 相结合使用时更是如此。
|
相关推荐
### JSTL使用手册 #### 一、JSTL概览与重要性 JSTL(JSP Standard Tag Library)是一种用于简化JSP(JavaServer Pages)开发的技术,旨在通过一组标准化的标签来减少页面中Java代码的数量,提高可读性和可维护性。...
本文将深入探讨“jstl使用xml出错”这一问题,以及如何解决相关问题。 首先,要正确使用JSTL处理XML,你需要确保在项目中包含三个关键的JAR文件: 1. **xalan.jar**:这个文件包含了XSLT处理器,用于将XML转换为...
这个"JSTL使用手册 帮助文档"涵盖了JSTL的核心概念、使用方法和实例,旨在帮助开发者更深入地理解和运用这一强大的工具。 JSTL的核心组成部分包括Core(核心)、XML、Internationalization(国际化)、Function...
### EL和JSTL使用详解 #### 一、EL(Expression Language)介绍及使用方法 EL,即Expression Language,是一种简化了JSP页面中的Java代码编写的一种表达式语言。它主要用于获取存储在JSP页面作用域中的数据对象,...
**JSTL(JavaServer Pages Standard Tag Library...同时,`jstl.jsr standard.jar` 和 `jstl.jar` 是使用JSTL所必需的库文件,它们包含了JSTL的实现和标准标签库,而`APACHE_LICENSE.TXT` 则揭示了其开源许可证的细节。
**JSTL(JSP Standard Tag Library)**是Java服务器页面(JSP)的一个扩展,旨在简化JSP页面的开发,通过提供一组预定义的标签,使得开发者可以在不使用脚本语言的情况下处理业务逻辑。JSTL的出现是为了替代JSP页面...
**JSTL(JavaServer Pages Standard Tag Library)**是Java Web开发中的一种标准标签库,它为JSP页面提供了一套方便使用的标签,使得开发者能够更高效、更简洁地编写JSP代码。JSTL 1.0版本是较早的一个稳定版本,...
**JSTL(JavaServer Pages Standard Tag Library)**是Java EE平台中用于增强JSP页面功能的一组标准标签库,它允许开发者使用更简洁、更易于维护的方式编写JSP页面,减少页面中的Java脚本。JSTL的核心库主要包含了...
在Java Servlet和JSP开发中,JSTL(Java...使用JSTL时,首先需要在JSP页面上引入JSTL库,这通常通过在页面指令中声明`taglib`来完成: ```jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ...
- **jstl的使用.txt**:更深入的JSTL使用指南,包括各种标签的详细用法和示例。 - **Ext.MessageBox.Show()属性.txt**:ExtJS的弹出对话框,JSTL无法直接处理,但前后端交互时可能会用到。 - **CDATA的使用.txt**:...
### jstl使用手册 #### 重要知识点概览 1. **JSTL(JSP Standard Tag Library)**: 是一种标准化的标签库,用于简化JSP页面中的代码编写,提高可读性和可维护性。 2. **JSTL版本**: 包括Standard-1.0Taglib与...
JSTL(JSP Standard Tag Library ,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。JSTL只能运行在支持JSP1.2和Servlet2.3规范的容器上,如tomcat 4.x。在JSP 2.0中也...
这是一份JSP标准标签库的使用介绍,能够让大家给好的学习JSTL的使用。
在这个压缩包中,`jstl帮助`可能包含了详细的JSTL使用教程、API参考、示例代码等内容。开发者可以通过阅读这些资料,了解每个标签的功能、用法以及注意事项,从而更好地将JSTL应用于实际项目中,提高开发效率。对于...
**JSTL与EL的协同工作**:虽然EL可以独立于JSTL使用,但两者结合使用能发挥更大的效能。JSTL的标签可以接收EL表达式作为参数,使得页面逻辑更加简洁。例如,`<c:choose>`标签可以配合EL来做出基于变量值的条件判断。...
JSTL,全称为JSP Standard Tag Library,是Java服务器端的一个强大工具,它提供了一系列预定义的标签,用于简化JSP页面的开发。JSTL的主要目标是减少在JSP...正确配置和使用JSTL,能够使得JSP应用更加整洁、易于维护。
**JSTL使用手册:** 这份PDF文档提供了JSTL的详细使用指南,包括每个标签的用法、属性和示例,是学习JSTL的重要参考资料。它会帮助开发者快速上手,了解如何在实际项目中应用JSTL标签。 **Doc文档:** 通常,`doc...
### JSTL开发使用手册概览与核心知识点 #### JSTL简介 JSTL(JavaServer Pages Standard Tag Library)是一种标准的标签库,旨在简化JavaServer Pages (JSP) 页面的开发。它提供了一系列预定义的标签,帮助开发者...