JSTL 学习2 - 3

来源:互联网 发布:特效拍摄软件 编辑:程序博客网 时间:2024/03/29 14:42

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> 操作的最后两个(可选的)属性是 varscopevar 属性会导致从指定 URL 获取的内容(作为 String 值)被存储在一个限定了作用域的变量中,而不是包含在当前 JSP 页面中。 scope 属性控制该变量的作用域,缺省情况下是页面作用域。如同我们在今后的文章中将要看到的那样,JSTL xml 库中的标记利用了 <c:import> 这种能力,即将整个文档存储在一个限定了作用域的变量中。

还要注意的是,可以使用(可选的)嵌套的 <c:param> 标记来为正在导入的 URL 指定请求参数。与在 <c:url> 中嵌套 <c:param> 标记一样,必要时也要对参数名称和参数值进行 URL 编码。

 




回页首


请求重定向

最后一个 core 库标记是 <c:redirect> 。该操作用于向用户的浏览器发送 HTTP 重定向响应,它是 JSTL 中与 javax.servlet.http.HttpServletResponsesendRedirect() 方法功能相当的标记。清单 19 中显示了该标记的 urlcontext 属性,它们的行为分别等同于 <c:import>urlcontext 属性的行为,是嵌套任何 <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 相结合使用时更是如此。

原创粉丝点击