CSDN博客

img RaistlinD

学习JSTL摘要2——CORE库

发表于2004/9/14 17:34:00  1478人阅读

分类: JAVA

迭代<c:forEach>

该标记支持两种不同样式的迭代:整数范围上的迭代(类似 Java 语言的 for 语句)和集合上的迭代(类似 Java 语言的 IteratorEnumeration 类)。

1.用于整数范围迭代:

(必需)beginend属性为整数值或结果为整数值的表达式。 分别指定迭代索引的初始值以及迭代索引的终止值。

(可选)step参数,必须是整数值。它指定每次迭代后索引的增量,如果省略了step属性,那么步长缺省为1。使用var 属性,会创建一个带有指定名称的并限定了作用域的变量,并将每次迭代的当前索引值赋给该变量,只可以在 <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>

2.用于集合迭代
 
<c:forEach var="name" items="expression" varStatus="name"
    begin="expression" end="expression" step="expression">
  body content
</c:forEach>

<c:forEach> 标记支持 Java 平台所提供的所有标准集合类型。

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 查询所获得的行

使用 beginendstep 属性来限定在迭代中包含集合中哪些元素。迭代集合中的迭代索引指定的 beginend step 值相匹配。(注:对于包含 HTML 标记的内容,<c:out> 标记的 escapeXml 属性被设置成了 false则可以避免转义为XML实体)
 

<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>

不论是对整数还是对集合进行迭代,<c:forEach> 的属性 varStatus 用于创建限定了作用域的变量,是javax.servlet.jsp.jstl.core.LoopTagStatus 类的实例。该类描述了迭代的当前状态。

特性 Getter 描述
current getCurrent() 当前这次迭代的(集合中的)项
index getIndex() 当前这次迭代从 0 开始的迭代索引
count getCount() 当前这次迭代从 1 开始的迭代计数
first isFirst() 用来表明当前这轮迭代是否为第一次迭代的标志
last isLast() 用来表明当前这轮迭代是否为最后一次迭代的标志
begin getBegin() begin 属性值
end getEnd() end 属性值
step getStep() step 属性值
<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>

条件化

<c:if> 条件操作的语法
<c:if test="expression" var="name" scope="scope">
  body content
</c:if>

<c:forEach> 标记的 LoopTagStatus 对象的 first 特性一起使用的 <c:if>。例子实现只在第一项上显示这组项的创建日期,而不在任何其它项前面重复该日期。

<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>

<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> 标记的主体内容。

<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,那么会将异常赋给(具有页面作用域的)指定的变量,这使得能够在页面自身内部进行定制错误处理。
 
<c:catch var="name">
  body content
</c:catch>

URL 操作
<c:url> 提供了三个功能元素:

1.在前面附加当前 servlet 上下文的名称

2.为会话管理重写 URL

3.请求参数名称和值的 URL 编码

value 属性用来指定基本 URL,然后在必要时标记对其进行转换。如果这个基本 URL 以一个斜杠开始,那么会在它前面加上 servlet 的上下文名称。可以使用 context 属性提供显式的上下文名称。如果省略该属性,那么就使用当前 servlet 上下文的名称。这一点特别有用,因为 servlet 上下文名称是在部署期间而不是开发期间决定的。(如果这个基本 URL 不是以斜杠开始的,那么就认为它是一个相对 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 属性的值。

<a href="<c:url value='/content/sitemap.jsp'/>">View sitemap</a>

最后,如果通过嵌套 <c:param> 标记指定了任何请求参数,那么将会使用 HTTP GET 请求的标准表示法将它们的名称和值添加到生成的 URL 后面。此外,还进行 URL 编码:为了生成有效的 URL,将对这些参数的名称或值中出现的任何字符适当地进行转换。

<c:url value="/content/search.jsp">
  <c:param name="keyword" value="${searchTerm}"/>
  <c:param name="month" value="02/2003"/>
</c:url>

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

/blog/content/search.jsp?keyword=foo+bar&month=02%2F2003

当没有会话 cookie 时,生成的结果如下所示。同样,servlet 上下文被添加到了前面,而 URL 编码的请求参数被附加到了后面。不过,除此以外还重写了基本 URL 以包含指定的会话标识。当浏览器发送用这种方式重写的 URL 请求时,JSP 容器自动抽取会话标识,并将请求与相应的会话进行关联。这样,需要会话管理的 J2EE 应用程序就无需依赖由应用程序用户启用的 cookie 了。

/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 页面中。

<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 文档的检索将会失败,因此会显示有关这种情况的错误消息。

<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 scopevar 属性会导致从指定 URL 获取的内容(作为 String 值)被存储在一个限定了作用域的变量中,而不是包含在当前 JSP 页面中。scope 属性控制该变量的作用域,缺省情况下是页面作用域。还要注意的是,可以使用(可选的)嵌套的 <c:param> 标记来为正在导入的 URL 指定请求参数。与在 <c:url> 中嵌套 <c:param> 标记一样,必要时也要对参数名称和参数值进行 URL 编码。

请求重定向

 <c:redirect>用于向用户的浏览器发送 HTTP 重定向响应,它是 JSTL 中与 javax.servlet.http.HttpServletResponsesendRedirect() 方法功能相当的标记。

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

可以为<c:redirect> 操作捕获异常,用一个到指定错误页面的重定向代替页面错误消息。注意,通过请求分派器<jsp:forward>进行转发是在服务器端实现的,而重定向却是由浏览器来执行的。从开发人员的角度来讲,转发比重定向更有效率,但 <c:redirect> 操作却更灵活一些,因为 <jsp:forward> 只能分派到当前 servlet 上下文内的其它 JSP 页面。

<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> 还取决于所期望的用户体验。

0 0

相关博文

我的热门文章

img
取 消
img