返回介绍

9.5 遍历行为

发布于 2025-04-22 20:10:02 字数 13065 浏览 0 评论 0 收藏

当需要无数次地遍历一个对象集合时,遍历行为就很有帮助。JSTL 提供了 forEach 和 forTokens 两个执行遍历行为的标签,这两个标签将在接下来的小节中介绍。

9.5.1 forEach 标签

forEach 标签会无数次地反复遍历 body content 或者对象集合。可以遍历的对象包括 java.util.Collection 和 java.util.Map 的所有实现,以及对象数组或者基本类型。也可以遍历 java.util.Iterator 和 java.util.Enumeration,但不应该在多个行为中使用 Iterator 或者 Enumeration,因为无法重置 Iterator 或者 Enumeration。

forEach 标签的语法有两种形式。第一种形式是固定次数地重复 body content。

< c:forEach [var="varName"] begin="begin" end="end" step="step">
  body content
< /c:forEach>

第二种形式用于遍历对象集合。

< c:forEach items="collection" [var="varName"]
    [varStatus="varStatusName"] [begin="begin"] [end="end"]
    [step="step"]>
  body content
< /c:forEach>

body content 是 JSP。forEach 标签的属性见表 9.6。

表 9.6 forEach 标签的属性

属性

类型

描述

var

字符串

引用遍历的当前项目的有界变量名称

items+

支持的任意类型

遍历的对象集合

varStatus

字符串

保存遍历状态的有界变量名称。类型值为 javax.servlet.jsp.jstl.core. LoopTagStatus

begin+

整数

如果指定 items,遍历将从指定索引处的项开始,例如,集合中第一项的索引为 0。如果没有指定 items,遍历将从设定的索引值开始。如果指定,begin 的值必须大于或者等于 0

end+

整数

如果指定 items,遍历将在(含)指定索引处的项结束。如果没有指定 items,遍历将在索引到达指定值时结束

step+

整数

遍历将只处理间隔指定 step 的项目,从第一项开始。在这种情况下,step 的值必须大于或者等于 1

例如,下列的 forEach 标签将显示“1,2,3,4,5”。

<c:forEach var="x" begin="1" end="5">
  <c:out value="${x}"/>,
</c:forEach>

下面的 forEach 标签将遍历有界变量 address 的 phones 属性:

<c:forEach var="phone" items="${address.phones}">
  ${phone}"<br/>
</c:forEach>

对于每一次遍历,forEach 标签都将创建一个有界变量,变量名称通过 var 属性定义。在本例中,有界变量命名为 phone。forEach 标签中的 EL 表达式用于显示 phone 的值。这个有界变量只存在于开始和结束的 forEach 标签之间,一到结束的 forEach 标签前,它就会被删除。

forEach 标签有一个类型为 javax.servlet.jsp.jstl.core.LoopTagStatus 的变量 varStatus。LoopTagStatus 接口带有 count 属性,它返回当前遍历的“次数”。第一次遍历时,status.count 值为 1;第二次遍历时,Status.count 值为 2,依此类推。通过测试 status.count%2 的余数,可以知道该标签正在处理的是偶数编号的元素,还是奇数编号的元素。

以 iterator 应用程序中的 BookServlet 类和 BookList.jsp 页面为例。如清单 9.5 所示,BookServer 类在其 doGet 方法中,创建了 3 个 Book 对象,并放入到一个 List 对象中,并将该 List 对象存入 ServletRequest 属性中,最后转到 books.jsp 页面,该页面会通过 forEach 标签遍历图书集合。Book 类如清单 9.6 所示。

清单 9.5 Books Servlet 类

package servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import app05a.model.Book ;

@WebServlet(urlPatterns = {"/books"})
public class BooksServlet extends HttpServlet { 
  private static final int serialVersionUID = -234237; @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List< Book> books = new ArrayList< Book>(); Book book1 = new Book("978-0980839616", "Java 7: A Beginner's Tutorial", BigDecimal.valueOf(45.00)); Book book2 = new Book("978-0980331608", "Struts 2 Design and Programming: A Tutorial", BigDecimal.valueOf(49.95)); Book book3 = new Book("978-0975212820", "Dimensional Data Warehousing with MySQL: A Tutorial", BigDecimal.valueOf(39.95)); books.add(book1); books.add(book2); books.add(book3); request.setAttribute("books", books); RequestDispatcher rd = request.getRequestDispatcher("/books.jsp"); rd.forward(request, response); } }

清单 9.6 Book 类

package domain;
import java.math.BigDecimal;
public class Book {
  private String isbn;
  private String title;
  private BigDecimal price;

  public Book(String isbn, String title, BigDecimal price) {
    this.isbn = isbn;
    this.title = title;
    this.price = price;
  }

  // getters and setters not shown
}

清单 9.7 books.jsp 页面

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<title>Book List</title>
<style>table, tr, td { 
   border: 1px solid brown; 
}
</style>
</head>
<body>
Books in Simple Table
<table> 
  <tr>
    <td>ISBN</td> 
    <td>Title</td>
  </tr> 
  <c:forEach items="${requestScope.books}" var="book">
  <tr> 
    <td>${book.isbn}</td>
    <td>${book.title}</td>
  </tr>
  </c:forEach>
</table> 
<br/>
Books in Styled Table
<table> 
  <tr style="background:#ababff">
    <td>ISBN</td> 
    <td>Title</td>
  </tr> 
  <c:forEach items="${requestScope.books}" var="book"
      varStatus="status"> 
    <c:if test="${status.count%2 == 0}">
      <tr style="background:#eeeeff"> 
    </c:if>
    <c:if test="${status.count%2 != 0}"> 
      <tr style="background:#dedeff">
    </c:if> 
    <td>${book.isbn}</td> 
    <td>${book.title}</td>
  </tr> 
  </c:forEach>
</table> 

<br/>
ISBNs only: 
  <c:forEach items="${requestScope.books}" var="book" 
      varStatus="status"> 
    ${book.isbn}<c:if test="${!status.last}">,</c:if>
  </c:forEach> 
</body> 
</html>

注意,books.jsp 页面显示了图书 3 次,第一次是利用没有 varStatus 属性的 forEach 标签。

<table>
  <tr>
    <th>ISBN</th>
    <th>Title</th>
  </tr>
  <c:forEach items="${requestScope books}" var="book">
  <tr>
    <td>${book.isbn}</td>
    <td>${book.title}</td>
  </tr>
  </c:forEach>
</table>

第二次是利用有 varStatus 属性的 forEach 标签来显示,这是为了根据偶数行或奇数行来给表格行设计不同的颜色。

<table> 
  <tr style="background:#ababff">
    <td>ISBN</td> 
    <td>Title</td>
  </tr> 
  <c:forEach items="${requestScope.books}" var="book"
      varStatus="status"> 
    <c:if test="${status.count%2 == 0}">
      <tr style="background:#eeeeff"> 
    </c:if>
    <c:if test="${status.count%2 != 0}"> 
      <tr style="background:#dedeff">
    </c:if> 
    <td>${book.isbn}</td> 
    <td>${book.title}</td>
  </tr> 
  </c:forEach>
</table>

最后一个 forEach 用来展示以逗号分隔的 ISBN,status.last 用来避免在文末有逗号。

<c:forEach items="${requestScope.books}" var="book" 
    varStatus="status"> 
  ${book.isbn}<c:if test="${!status.last}">,</c:if>
</c:forEach>

利用以下 URL 可以查看以上范例:

http://localhost:8080/iterator/books

其输出结果与图 9.3 所示的屏幕截图相似。

图片 2

图 9.3 对 List 使用 forEach

利用 forEach 还可以遍历 Map。要分别利用 key 和 value 属性引用一个 Map key 和一个 Map 值。遍历 Map 的伪代码如下所示:

< c:forEach var="mapItem" items="map">
  ${mapItem.key} : ${mapItem.value}
< /c:forEach>

清单 9.8 展示了 forEach 与 Map 的结合使用。清单 9.8 中的 BigCitiesServlet 类将两个 Map 实例化,并为它们赋予键/值对。第一个 Map 中的每一个元素都是一个 String/String 对,第二个 Map 中的每一个元素则都是一个 String/String[]对。

清单 9.8 BigCitiesServlet 类

package servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

@WebServlet(urlPatterns = {"/bigCities"})
public class BigCitiesServlet extends HttpServlet { 
  private static final long serialVersionUID = 1L; 

  @Override
  public void doGet(HttpServletRequest request, 
      HttpServletResponse response) 
      throws ServletException, IOException { 
    Map<String, String> capitals = 
        new HashMap<String, String>(); 
    capitals.put("Indonesia", "Jakarta"); 
    capitals.put("Malaysia", "Kuala Lumpur"); 
    capitals.put("Thailand", "Bangkok"); 
    request.setAttribute("capitals", capitals); 
    Map<String, String[]> bigCities = 
        new HashMap<String, String[]>(); 
    bigCities.put("Australia", new String[] {"Sydney", 
        "Melbourne", "Perth"});
    bigCities.put("New Zealand", new String[] {"Auckland", 
        "Christchurch", "Wellington"}); 
    bigCities.put("Indonesia", new String[] {"Jakarta", 
        "Surabaya", "Medan"}); 
    request.setAttribute("capitals", capitals);
    request.setAttribute("bigCities", bigCities); 
    RequestDispatcher rd = 
        request.getRequestDispatcher("/bigCities.jsp");
    rd.forward(request, response); 
  } 
}

在 doGet 方法的结尾处,servlet 跳转到 bigcities.jsp 页面,它利用 forEach 遍历 Map。bigcities.jsp 页面如清单 9.9 所示。

清单 9.9 bigcities.jsp 页面

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<title>Big Cities</title>
<style>
table, tr, td {
  border: 1px solid #aaee77;
  padding: 3px;
}
</style>
</head>
<body>
Capitals
<table>
  <tr style="background:#448755;color:white;font-weight:bold">
    <td>Country</td>
    <td>Capital</td>
  </tr>
  <c:forEach items="${requestScope.capitals}" var="mapItem">
  <tr>
    <td>${mapItem.key}</td>
    <td>${mapItem.value}</td>
  </tr>
  </c:forEach>
</table>
<br/>
Big Cities
<table>
  <tr style="background:#448755;color:white;font-weight:bold">
    <td>Country</td>
    <td>Cities</td>
  </tr>
  <c:forEach items="${requestScope.bigCities}" var="mapItem">
  <tr>
    <td>${mapItem.key}</td>
    <td>
      <c:forEach items="${mapItem.value}" var="city"
            varStatus="status">
        ${city}<c:if test="${!status.last}">,</c:if>
      </c:forEach>
    </td>
  </tr>
  </c:forEach>
</table>
</body>
</html>

最重要的是,第二个 forEach 中还嵌套了另一个 forEach:

<c:forEach items="${requestScope.bigCities}" var="mapItem">
    <c:forEach items="${mapItem.value}" var="city"
          varStatus="status">
      ${city}<c:if test="${!status.last}">,</c:if>
    </c:forEach>
</c:forEach>

这里的第二个 forEach 是遍历 Map 的元素值,它是一个 String 数组。

登录以下网站可以查看到以上范例:

http://localhost:8080/iterator/bigCities

打开网页后,浏览器上应该会以 HTML 表格的形式,显示出几个国家的首都和大城市,如图 9.4 所示。

图片 3

图 9.4 对 Map 使用 forEach

9.5.2 forTokens 标签

forTokens 标签用于遍历以特定分隔符隔开的令牌,其语法如下:

< c:forTokens items="stringOfTokens" delims="delimiters"
    [var="varName"] [varStatus="varStatusName"]
    [begin="begin"] [end="end"] [step="step"]
>
  body content
< /c:forTokens>

body content 是 JSP。forTokens 标签的属性见表 9.7。

表 9.7 forTokens 标签的属性

属性

类型

描述

var

字符串

引用遍历的当前项目的有界变量名称

items+

支持的任意类型

要遍历的 token 字符串

varStatus

字符串

保存遍历状态的有界变量名称。类型值为 javax.servlet.jsp.jstl. core.LoopTagStatus

begin+

整数

遍历的起始索引,此处索引是从 0 开始的。如有指定,begin 的值必须大于或者等于 0

end+

整数

遍历的终止索引,此处索引是从 0 开始的

step+

整数

遍历将以 step 指定的间隔的 token 来处理字符串,从第一个 token 开始。如有指定,step 的值必须大于或者等于 1

delims+

字符串

一组分隔符

下面是一个 forTokens 范例:

<c:forTokens var="item" items="Argentina,Brazil,Chile" delims=",">
  <c:out value="${item}"/><br/>
</c:forTokens>

当将以上 forTokens 粘贴到 JSP 中时,它将会产生如下结果:

Argentina
Brazil
Chile

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。