5.5 遍历行为 当需要无数次地遍历一个对象集合时,遍历行为就很有帮助。JSTL
提供了forEach
和forTokens
两个执行遍历行为的标签:这两个标签将在接下来的小节中讨论。
5.5.1 forEach标签 forEach
标签会无数次地反复遍历body content
或者对象集合 。可以被遍历的对象包括java.util.Collection
和java.util.Map
的所有实现类,以及对象数组或者主类型。也可以遍历java.util.Iterator
和java.util.Enumeration
,但不应该在多个行为中使用Iterator
或者Enumeration
,因为无法重置Iterator
或者Enumeration
。
形式1 重复执行标签体 forEach
标签的语法有两种形式。第一种形式是固定次数地重复body content
:
1 2 3 4 <c:forEach [var ="varName" ] begin="begin" end="end" step="step" > body content </c:forEach>
形式2 遍历集合 第二种形式用于遍历对象集合:
1 2 3 4 5 <c:forEach items="collection" [var ="varName" ] [varStatus="varStatusName" ] [begin="begin" ] [end="end" ] [step="step" ]> body content </c:forEach>
forEach
标签的标签体body content
之中的代码时JSP
代码.
forEach标签的属性
属性
类型
描述
var
字符串
引用遍历的当前项目的有界变量名称
items+
支持的任意类型
遍历的对象集合
varStatus
字符串
保存遍历状态的有界变量名称。类型值为javax.servlet.jsp.jstl.core.LoopTagStatus
begin+
整数
如果指定items
,遍历将从指定索引处的项目开始,例如,集合中第一个项目的索引为0。如果没有指定items
,遍历将从设定的索引值开始。如果指定,begin
的值必须大于或者等于0
end+
整数
如果指定items
,遍历将在(含)指定索引处的项目结束。如果没有指定items
,遍历将在索引到达指定值时结束
step+
整数
遍历将只处理间隔指定step
的项目,从第一个项目开始。在这种情况下,step
的值必须大于或者等于1
对于每一次遍历,forEach
标签都将创建一个有界变量,变量名称通过var
属性定义。这个有界变量只存在于开始和关闭的forEach
标签之间,一到关闭的forEach
标签前,它就会被删除。
实例 begin end属性 例如,下列的forEach
标签将显示“1 2 3 4 5
”。
1 2 3 <c:forEach var ="x" begin="1" end="5" > <c:out value="${x}" /> </c:forEach>
step属性 1 2 3 <c:forEach var ="x" begin="1" end="10" step="2" > <c:out value="${x}" /> </c:forEach>
运行结果:1 3 5 7 9
遍历有界变量 下面的forEach
标签将遍历有界变量address
的phones
属性:
1 2 3 <c:forEach var ="phone" items="${address.phones}" > ${phone}"<br/> </c:forEach>
在本例中,有界变量命名为phone
。forEach
标签中的EL
表达式用于显示phone
的值。
获取遍历的次数 forEach
标签有一个类型为javax.servlet.jsp.jstl.core.LoopTagStatus
的变量varStatus
。LoopTagStatus
接口带有count
属性,它当前遍历的“次数”。第一次遍历时,status.count
值1;第二次遍历时,status.count
值为2,依次类推。测试status.count%2
的余数,可以知道该标签当前遍历到的是偶数编号的元素,还是奇数编号的元素。
forEach标签遍历ArrayList 以app05a
应用程序中的BookController
类和BookList.jsp
页面为例。BookController
类调用了一个service
方法,返回一个Book
对象List
。
Book类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package app05a.model;public class Book { private String isbn; private String title; private double price; public Book (String isbn, String title, double price) { this .isbn = isbn; this .title = title; this .price = price; } public String getIsbn () { return isbn; } public void setIsbn (String isbn) { this .isbn = isbn; } public String getTitle () { return title; } public void setTitle (String title) { this .title = title; } public double getPrice () { return price; } public void setPrice (double price) { this .price = price; } }
BooksServlet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package app05a.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" , 45.00 ); Book book2 = new Book("978-0980331608" , "Struts 2 Design and Programming: A Tutorial" , 49.95 ); Book book3 = new Book("978-0975212820" , "Dimensional Data Warehousing with MySQL: A " + "Tutorial" , 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); } }
BooksServlet
的doGet
方法中创建了几本书,保存在书籍列表中,然后把书籍列表设置为请求对象的属性.最后再调用book.jsp
进行显示.books.jsp
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <%@page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html> <head> <title>Book List</title> <style> table, tr, td { border: 1px solid #546e7a; } </style> </head> <body> Books in Simple Table <table> <tr> <td>ISBN</td> <td>Title</td> </tr> <!-- 遍历请求对象中的books属性所指向的这个ArrayList对象 遍历变量名为book--> <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: #0288d1" > <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: #ba68c8" > </c:if> <c:if test="${status.count%2 != 0}" > <tr style="background: #f06292" > </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>
其中下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <table> <tr> <td>ISBN</td> <td>Title</td> </tr> <!-- 遍历请求对象中的books属性所指向的这个ArrayList对象 遍历变量名为book,表示Arraylist中的一个元素, 也就是一个Book对象--> <c:forEach items="${requestScope.books}" var ="book" > <tr> <!-- 输出book对象isbn编号 --> <td>${book.isbn}</td> <!-- 输出book对象的书名 --> <td>${book.title}</td> </tr> </c:forEach> </table>
使用了forEach
标签来遍历保存在请求对象中的books
属性(ArrayList
),显示效果如下图所示:
测试forEach的状态对象 varStatus="status"
将创建一个名为status
的状态数据对象,使用状态数据对象可以获取本次遍历的一些信息.如status.count
表示当前遍历的次数. 测试状态对象的JSP
代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <table> <tr style="background: #0288d1" > <td>ISBN</td> <td>Title</td> </tr> <!-- 遍历请求对象中的books属性(ArrayList), 遍历变量为book(表示ArrayList中的一个元素), 并创建名称为status的遍历状态对象. --> <c:forEach items="${requestScope.books}" var ="book" varStatus="status" > <!-- 如果循环是偶数的话,使用xxxxx作为该行的背景颜色 --> <c:if test="${status.count%2 == 0}" > <tr style="background: #ba68c8" > </c:if> <!-- 如果循环次数是奇数的话,使用yyyyy作为该行的背景颜色 --> <c:if test="${status.count%2 != 0}" > <tr style="background: #f06292" > </c:if> <td>${book.isbn}</td> <td>${book.title}</td> </tr> </c:forEach> </table>
显示效果:
最后一个元素 status.last
表示最后的最后一个元素,测试代码如下所示:
1 2 3 4 5 6 7 <br /> ISBNs only: <c:forEach items="${requestScope.books}" var ="book" varStatus="status" > ${book.isbn} <!-- 如果不是最后一个元素则输出逗号作为分隔符 --> <c:if test="${!status.last}">,</c:if> </c:forEach>
forEach标签遍历Map 利用forEach
还可以遍历Map
。要分别利用key
和value
属性引用一个Map key
和一个Map
值。遍历Map
的伪代码如下:
1 2 3 <c:forEach var ="mapItem" items="map" > ${mapItem.key} : ${mapItem.value} </c:forEach>
下一个范例展示了forEach
与Map
的结合使用。CityController
类将两个Map
实例化,并为它们赋予键/值对
。第一个Map
中的每一个元素都是一个String/String
对,第二个Map
中的每一个元素则都是一个String/String[]
对。
BigCitiesServlet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package app05a.servlet;import java.io.IOException;import java.util.Collections;import java.util.HashMap;import java.util.List;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 = -83191871L ; @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); } }
bigCities.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 <%@page contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html> <head> <title>Big Cities</title> <style> table, tr, td { border: 1px solid #aaee77; padding: 3 px; } </style> </head> <body> Capitals <table> <tr style="background: #448755; color: white; font-weight: bold" > <td>Country</td> <td>Capital</td> </tr> <!-- 遍历请求对象中的 capitals属性 --> <c:forEach items="${requestScope.capitals}" var ="mapItem" > <tr> <!-- 取出map的key --> <td>${mapItem.key}</td> <!-- 取出对应的value --> <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> <!-- 遍历请求对象中的bigCities这个属性(Map)--> <c:forEach items="${requestScope.bigCities}" var ="mapItem" > <tr> <td>${mapItem.key}</td> <!-- 遍历Map的值,也就是String[]数组 --> <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>
遍历String/String 类型的Map 设置capitals属性 Servlet
中设的的capitals
请求对象的属性如下所示:
1 2 3 4 5 6 7 8 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);
然后在JSP
页面中通过forEach
标签遍历该请求对象中的属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Capitals <table> <tr style="background: #448755; color: white; font-weight: bold" > <td>Country</td> <td>Capital</td> </tr> <!-- 遍历请求对象中的 capitals属性 --> <c:forEach items="${requestScope.capitals}" var ="mapItem" > <tr> <!-- 取出map的key --> <td>${mapItem.key}</td> <!-- 取出对应的value --> <td>${mapItem.value}</td> </tr> </c:forEach> </table>
显示效果:
遍历String/String[]类型的Map 设置请求对象的bigCities
属性
1 2 3 4 5 6 7 8 9 10 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("bigCities" , bigCities);
遍历请求对象的bigCities
属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <br /> Big Cities <table> <tr style="background: #448755; color: white; font-weight: bold" > <td>Country</td> <td>Cities</td> </tr> <!-- 遍历请求对象中的bigCities这个属性(Map)--> <c:forEach items="${requestScope.bigCities}" var ="mapItem" > <tr> <td>${mapItem.key}</td> <!-- 遍历Map的值,也就是String[]数组 --> <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>
显示效果如下:
原文链接: 5.5 遍历行为