第3.3式. 显示索引属性
问题
在一个JSP 页面中,你需要访问一个对象中的索引的属性。
动作要领
使用bean.property[index]来访问索引的值,如Example 3-1所示。
Example 3-1. 访问索引属性
<@taglib uri=http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<ul>
<li><bean:write name="foo" property="bar.baz[0]"/></li>
<li><bean:write name="foo" property="bar.baz[1]"/></li>
<li><bean:write name="foo" property="bar.baz[2]"/></li>
</ul>
JSTL 也支持对索引属性的访问,如Example 3-2 所示。
Example 3-2. 访问索引属性(JSTL)
<@taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
<ul>
<li><c:out value="${foo.bar.baz[0]}"/></li>
<li><c:out value="${foo.bar.baz[1]}"/></li>
<li><c:out value="${foo.bar.baz[1]}"/></li>
</ul>
动作变化
索引的属性是Struts标签中最容易误解的一个部分。一个索引属性是表达一组值的JavaBean 属性,而不是一个单独的标量值。索引属性通过下面格式的getter 方法进行访问:
public Foo getSomeProperty (int index) { }
同时,索引属性则通过下面格式的setter 方法进行设置:
public void setFoo(int index, Foo someProperty) { }
我们来考虑一个表示日历的JavaBean。CalendarHolder类的代码如Example 3-3 所示,它有一个名为monthSet的嵌套属性,表达日历中的月份。
Example 3-3. Calendar JavaBean
package com.oreilly.strutsckbk;
public class CalendarHolder {
private MonthSet monthSet;
public CalendarHolder( ) {
monthSet = new MonthSet( );
}
public MonthSet getMonthSet( ) {
return monthSet;
}
}
MonthSet类的代码则如Example 3-4 所示,它是一个具有索引属性的类,该属性表达月份的名称("January," "February," 等等)。
Example 3-4. 具有索引属性的类
package com.oreilly.strutsckbk;
public class MonthSet {
static String[] months = new String[] {
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
};
public String[] getMonths( ) {
return months;
}
public String getMonth(int index) {
return months[index];
}
public void setMonth(int index, String value) {
months[index] = value;
}
}
我们的目标是访问在JSP页面中访问CalendarHolder实例的monthSet属性的索引属性month,代码片断如下所示:
<jsp:useBean id="calendar" class="com.oreilly.strutsckbk.CalendarHolder"/>
<ul>
<li><bean:write name="calendar" property="monthSet.months[0]"/></li>
<li><bean:write name="calendar" property="monthSet.months[1]"/></li>
<li><bean:write name="calendar" property="monthSet.months[2]"/></li>
</ul>
如果显示的索引属性要动态才能决定它是什么,那么使用的索引要使用JSP 脚本变量来进行设置。你可以使用scriptlet 来产生属性值,如下所示:
You have selected month number <bean:write name="monthIndex"/>:
<bean:write name="calendar"
property='<%= "monthSet.month[" + monthIndex + "]" %>'
但是使用scriptlet 会导致极端难以阅读和维护的JSP 页面。如果使用JSTL,事情会变得更清爽一些:
You have selected month number <c:out value="${monthIndex}"/>:
<c:out value="${calendar.monthSet.month[monthIndex]}"/>
通常,索引属性是在一个循环内动态访问的。假设你想要使用Struts logic:iterate标签显示月份的列表。这个标签将在整个Collection 或者数组之上进行迭代。下面是你可以如何以一个排序列表显示所有月份的例子:
<ol>
<logic:iterate id="monthName" name="calendar" property="monthSet.months">
<li><bean:write name="monthName"/></li>
</logic:iterate>
</ol>
重申一下, JSTL 也是一个替代选择。JSTL c:forEach标签将比Struts logic:iterate标签要容易使用一些。下面是如何使用JSTL来产生上面的同一个排序列表的代码:
<ol>
<c:forEach var="monthName" items="${calendar.monthSet.months}">
<li><c:out name="${monthName}"/></li>
</c:forEach>
</ol>
相关动作
第3.4式在JSTL循环中使用索引属性。
第3.5式则提供了一个更加详细的关于在JSTL循环中使用索引属性的说明。