9.3.7 <c:forEach>标签
<c:forEach>标签用于根据集合对象或指定的次数循环迭代标签体中的内容。<c:forEach>标签有如下两种语法格式:
1 语法1:根据集合对象进行迭代
<c:forEach[var="varName"] items="collection"
[varStatus="varStatusName"]
[begin="begin"] [end="end"] [step="step"]>
body content
</c:forEach>
2 语法2:根据指定的次数进行迭代
<c:forEach [var="varName"]
[varStatus="varStatusName"]
begin="begin" end="end" [step="step"]>
body content
</c:forEach>
<c:forEach>标签的属性说明如表9.7所示。
表9.7 <c:forEach>标签的属性
属性名 | 是否支持动态属性值 | 属性类型 | 属性描述 |
var | false | String | 指定将当前迭代元素保存在page域中的属性名。 |
items | true | 任何支持的类型 | 用于迭代的集合对象。 |
varStatus | false | String | 指定将表示当前迭代元素状态信息的对象保存在page域中的属性名。当前迭代元素的状态信息对象实际上是javax.servlet.jsp.jstl.core.LoopTagStatus类的对象实例。 |
begin | true | int | 如果指定items属性,就从集合中第begin个元素开始迭代。begin属性的索引值从0开始编号。如果未指定items属性,那从begin属性指定的值开始迭代,直到end属性指定的值结束。 |
end | true | int | 如果指定items属性,则迭代到第end个集合元素为止。如果未指定items属性,则迭代到end属性所指定的值为止。 |
step | true | int | 指定迭代的步长,即每迭代一步的迭代增量。 |
在使用<c:forEach>标签时应注意如下几点:
1 如果指定begin属性,该属性的值必须大于或等于0,否则会抛出javax.servlet.jsp.JspTagException异常。
2 如果指定end属性,该属性的值不能小于begin属性的值,否则不会进行迭代操作。
3 如果指定step属性,该属性的值必须大于或等于1,否则会抛出javax.servlet.jsp.JspTagException异常。
4 如果items属性的值为null,或items属性指定的集合对象不存在,items属性值将被作为一个空集合对待。<c:forEach>标签不会进行迭代操作。
5 如果begin属性值大于或等于集合对象的元素个数,则不会进行迭代操作。
6 如果begin属性值在有效的范围内,但end属性值大于或等于集合对象的元素个数,则迭代到集合对象的最后一个元素为止。
<c:forEach>标签的items属性支持如下的数据类型:
7 任意类型的数组
8 java.util.Collection
9 java.util.Iterator
10 java.util. Enumeration
11 java.util.Map
12 String
如果items属性值是String类型,该字符串必须用逗号(,)分隔。<c:forEach>标签会将以逗号分隔的字符串当作String数组来处理(每一个被逗号分隔的子串相当于String数组中的一个元素)。
1. 迭代数组
forEach_array.jsp页面是一个使用<c:forEach>标签迭代数组的例子,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String[] strArray = new String[]{"超人", "飞机", "神化", "地球"};
int[] intArray = new int[]{100, 200, 320, 400, 1200};
chapter9.Message[] messages = new chapter9.Message[3];
messages[0] = new chapter9.Message();
messages[0].setName("bill");
messages[1] = new chapter9.Message();
messages[1].setName("Mike");
messages[2] = new chapter9.Message();
messages[2].setName("赵明");
// 将数组保存在request域中
request.setAttribute("strArray", strArray);
request.setAttribute("intArray", intArray);
request.setAttribute("messages", messages);
%>
迭代输出String数组中的元素<br>
<c:forEach var="str" items="${strArray}" >
${str}
</c:forEach>
<hr>
迭代输出int数组中的元素,并指定begin、end和varStatus属性<br>
<c:forEach var="int" items="${intArray}" begin = "1" end = "3" varStatus="status" >
intArray[${status.index}]=${int}
</c:forEach>
<hr>
迭代Message对象数组,并通过step属性指定迭代步长<br>
<c:forEach var="message" items="${messages}" step="2" varStatus="status">
messages[${status.index}].name =${message.name}<br>
</c:forEach>
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach_array.jsp
浏览器的显示结果如图9.9所示。
图9.9 使用<c:forEach>标签迭代数组
2. 迭代Collection和Iterator类型的集合对象
forEach_collection.jsp页面是一个使用<c:forEach>标签迭代Collection和Iterator类型的集合对象的例子,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
java.util.List<Object[]> objList = new java.util.ArrayList<Object[]>();
java.util.Random random = new java.util.Random();
for (int i = 0; i < 7; i++)
{
Object[] objArray = new Object[]
{ "随机数" + String.valueOf(i + 1), random.nextInt(10000) };
objList.add(objArray);
}
// 将Collection和Iterator类型的集合对象保存在request域中
request.setAttribute("objList", objList);
request.setAttribute("objIterator", objList.iterator());
%>
<table width="100%">
<tr>
<td align="right" style="padding-right: 20px">
<table border="1">
<tr>
<th>名称</th>
<th>随机数</th>
</tr>
<!-- 迭代Collection类型的集合对象 -->
<c:forEach var="obj" items="${objList}">
<tr>
<td>${obj[0]}</td>
<td>${obj[1]}</td>
</tr>
</c:forEach>
</table>
</td>
<td style="padding-left: 20px">
<table border="1">
<tr>
<th>随机数</th>
<th>名称</th>
</tr>
<!-- 迭代Iterator类型的集合对象 -->
<c:forEach var="obj" items="${objIterator}" >
<tr>
<td>${obj[1]}</td>
<td>${obj[0]}</td>
</tr>
</c:forEach>
</table>
</td>
</tr>
</table>
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach_collection.jsp
浏览器显示的结果如图9.10所示。
图9.10 使用<c:forEach>标签迭代Collection和Iterator类型的集合对象
3. 使用双重循环迭代Enumeration类型的集合对象和数组
forEach_enumeration.jsp页面是一个使用<c:forEach>标签迭代Enumeration类型的集合对象和数组的例子。内层循环迭代数组,外层循环迭代Enumeration类型的集合,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
java.util.Vector v = new java.util.Vector();
String[] strArray = new String[]
{ "超人", "飞机", "神化", "地球" };
int[] intArray = new int[6];
java.util.Random random = new java.util.Random();
for (int i = 0; i < intArray.length; i++)
{
intArray[i] = random.nextInt(123456);
}
v.add(strArray);
v.add(intArray);
// 将Enumeration对象保存在request域中
request.setAttribute("elements", v.elements());
%>
使用双重循环输出Enumeration对象中的值<hr>
<!-- 迭代Enumeration集合对象 -->
<c:forEach var="element" items="${elements}">
<!-- 迭代Enumeration集合对象中的元素,每一个元素是一个数组 -->
<c:forEach var="value" items="${element}">
${value}
</c:forEach>
<br>
</c:forEach>
Vector对象的elements方法返回了一个Enumeration对象。该对象描述了Vector对象中的所有元素。
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach_enumeration.jsp
浏览器显示的结果如图9.11所示。
图9.11 使用双重循环迭代Collection类型的集合对象和数组
4. 迭代Map类型的集合对象
foreach_map.jsp页面是一个使用<c:forEach>标签迭代Map类型的集合对象的例子,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
java.util.Map<String, Integer> map = new java.util.HashMap<String, Integer>();
map.put("自行车", 23);
map.put("皮球", 20);
map.put("电脑", 120);
// 将Map对象保存在request域中
request.setAttribute("map", map);
%>
<br>
<center>迭代输出Map对象中的key-value对<p/>
<table border="1">
<tr>
<th>商品</th>
<th>数量</th>
</tr>
<!-- 迭代Map类型的集合对象 -->
<c:forEach var="entry" items="${map}">
<tr>
<!-- 输出集合元素的key -->
<td>${entry.key}</td>
<!-- 输出集合元素的value --
<td>${entry.value}</td
</tr>
</c:forEach>
</table>
</center>
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach_map.jsp
浏览器显示的结果如图9.12所示。
图9.12 使用<c:forEach>标签迭代Map类型的集合对象
5. 迭代用逗号(,)分隔的字符串
<c:forEach>标签除了可以迭代各种类型的集合对象和数组外,还可以迭代用逗号分隔的字符串。但要注意,分隔符必须是逗号。forEach_string.jsp页面是一个使用<c:forEach>标签迭代以逗号分隔的字符串的例子,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<center>
<table border="1">
<tr>
<!-- 迭代用逗号分隔的字符串 -->
<c:forEach var="s" items="超人, 飞机, 神化, 地球">
<td>${s}</td>
</c:forEach>
</tr>
</table>
</center>
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach_string.jsp
浏览器显示的结果如图9.13所示。
图9.13 使用<c:forEach>标签迭代以逗号分隔的字符串
6. 获得当前迭代元素的状态信息
通过<c:forEach>标签的status属性可以指定保存当前迭代元素状态信息的对象名。该对象被保存在page属性。这个对象实际上就是javax.servlet.jsp.jstl.core.LoopTagStatus对象实例。在LoopTagStatus接口有如下几个方法可以获得当前迭代元素的状态信息:
1 public Object getCurrent():该方法返回当前迭代的元素对象。
2 public int getCount():该方法返回当前已循环迭代的次数。
3 public int getIndex():该方法返回当前迭代的元素索引号。
4 public boolean isFirst():如果当前迭代元素是迭代集合对象的第一个元素,该方法返回true,否则返回false。
5 public boolean isLast():如果当前迭代元素是迭代集合对象的最后一个元素,该方法返回true,否则返回false。
6 public Integer getBegin():该方法返回<c:forEach>标签的begin属性值。如果未设置begin属性,则返回null。
7 public Integer getEnd():该方法返回<c:forEach>标签的end属性值。如果未设置end属性,则返回null。
8 public Integer getStep():该方法返回<c:forEach>标签的step属性值。如果未设置step属性,则返回null。
forEach_status.jsp页面是一个使用<c:forEach>标签输出当前迭代元素状态信息的例子,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
String[] strArray = new String[]{ "超人", "飞机", "神化", "地球" };
// 将数组保存在request域中
request.setAttribute("strArray", strArray);
%>
<center>
未设置begin、end和step属性<p/>
<table border="1">
<tr>
<th>当前迭代元素</th>
<th>current</th>
<th>count</th>
<th>index</th>
<th>first</th>
<th>last</th>
<th>begin</th>
<th>end</th>
<th>step</th>
</tr>
<c:forEach var="s" items="${strArray}" varStatus="status">
<tr>
<td>${s}</td>
<td>${status.current}</td>
<td>${status.count}</td>
<td>${status.index}</td>
<td>${status.first}</td>
<td>${status.last}</td>
<td>${status.begin}</td>
<td>${status.end}</td>
<td>${status.step}</td>
</tr>
</c:forEach>
</table>
<hr>
设置了begin、end和step属性<p/>
<table border="1">
<tr>
<th>当前迭代元素</th>
<th>current</th>
<th>count</th>
<th>index</th>
<th>first</th>
<th>last</th>
<th>begin</th>
<th>end</th>
<th>step</th>
</tr>
<c:forEach var="s" items="${strArray}" varStatus="status" begin = "1" end = "3" step="2">
<tr>
<td>${s}</td>
<td>${status.current}</td>
<td>${status.count}</td>
<td>${status.index}</td>
<td>${status.first}</td>
<td>${status.last}</td>
<td>${status.begin}</td>
<td>${status.end}</td>
<td>${status.step}</td>
</tr>
</c:forEach>
</table>
</center>
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach_status.jsp
浏览器显示的结果如图9.14所示。
图9.14 使用<c:forEach>标签输出当前迭代元素的状态信息
7. 设置表格偶数行的背景色
使用迭代元素状态信息对象的属性可以实现很多有趣的功能。如使用count属性可以实现改变表格的偶数行背景色的功能,代码如下:
<!-- forEach.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
java.util.Map<String, Integer[]> map =
new java.util.HashMap<String, Integer[]>();
map.put("自行车", new Integer[]{ 321, 23 });
map.put("皮球", new Integer[]{ 45, 20 });
map.put("电脑", new Integer[]{ 4320, 120 });
map.put("啤酒", new Integer[]{ 3, 320 });
map.put("照相机", new Integer[]{ 1200, 12 });
// 将Map对象保存在request域中
request.setAttribute("map", map);
%>
<br>
<center>设置表格偶数行的背景色<p/>
<table border="1" width="80%">
<tr>
<th>商品</th>
<th>单价</th>
<th>数量</th>
</tr>
<!-- 迭代Map类型的集合对象 -->
<c:forEach var="entry" items="${map}" varStatus="status">
<!-- 使用EL判断count属性值是否为偶数,以便设置偶数行的背景色 -->
<tr ${status.count % 2 == 0? 'style="background-color:#00CCEE"':""}>
<!-- 输出集合元素的key -->
<td>${entry.key}</td>
<!-- 输出集合元素的value中的第一个元素 -->
<td>${entry.value[0]}</td>
<!-- 输出集合元素的value中的第二个元素 -->
<td>${entry.value[1]}</td>
</tr>
</c:forEach>
</table>
</center>
在上面的代码中,使用了EL表达式判断了count属性值是否为偶数(不包括表头)。如果count属性值为偶数,则使用CSS设置了偶数行的背景色。
在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/chapter9/forEach.jsp
浏览器显示的结果如图9.15所示。
图9.15 设置表格偶数行的背景色