第3.3式. 顯示索引屬性
問(wèn)題
在一個(gè)JSP 頁(yè)面中,你需要訪問(wèn)一個(gè)對(duì)象中的索引的屬性。
動(dòng)作要領(lǐng)
使用bean.property[index]來(lái)訪問(wèn)索引的值,如Example 3-1所示。
Example 3-1. 訪問(wèn)索引屬性
<@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 也支持對(duì)索引屬性的訪問(wèn),如Example 3-2 所示。
Example 3-2. 訪問(wèn)索引屬性(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>

動(dòng)作變化
索引的屬性是Struts標(biāo)簽中最容易誤解的一個(gè)部分。一個(gè)索引屬性是表達(dá)一組值的JavaBean 屬性,而不是一個(gè)單獨(dú)的標(biāo)量值。索引屬性通過(guò)下面格式的getter 方法進(jìn)行訪問(wèn):

public Foo getSomeProperty (int index)
{
}
同時(shí),索引屬性則通過(guò)下面格式的setter 方法進(jìn)行設(shè)置:

public void setFoo(int index, Foo someProperty)
{
}
我們來(lái)考慮一個(gè)表示日歷的JavaBean。CalendarHolder類(lèi)的代碼如Example 3-3 所示,它有一個(gè)名為monthSet的嵌套屬性,表達(dá)日歷中的月份。
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類(lèi)的代碼則如Example 3-4 所示,它是一個(gè)具有索引屬性的類(lèi),該屬性表達(dá)月份的名稱(chēng)("January," "February," 等等)。
Example 3-4. 具有索引屬性的類(lèi)
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;
}
}

我們的目標(biāo)是訪問(wèn)在JSP頁(yè)面中訪問(wèn)CalendarHolder實(shí)例的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>

如果顯示的索引屬性要?jiǎng)討B(tài)才能決定它是什么,那么使用的索引要使用JSP 腳本變量來(lái)進(jìn)行設(shè)置。你可以使用scriptlet 來(lái)產(chǎn)生屬性值,如下所示:
You have selected month number <bean:write name="monthIndex"/>:
<bean:write name="calendar"
property='<%= "monthSet.month[" + monthIndex + "]" %>'

但是使用scriptlet 會(huì)導(dǎo)致極端難以閱讀和維護(hù)的JSP 頁(yè)面。如果使用JSTL,事情會(huì)變得更清爽一些:
You have selected month number <c:out value="${monthIndex}"/>:
<c:out value="${calendar.monthSet.month[monthIndex]}"/>

通常,索引屬性是在一個(gè)循環(huán)內(nèi)動(dòng)態(tài)訪問(wèn)的。假設(shè)你想要使用Struts logic:iterate標(biāo)簽顯示月份的列表。這個(gè)標(biāo)簽將在整個(gè)Collection 或者數(shù)組之上進(jìn)行迭代。下面是你可以如何以一個(gè)排序列表顯示所有月份的例子:
<ol>
<logic:iterate id="monthName" name="calendar" property="monthSet.months">
<li><bean:write name="monthName"/></li>
</logic:iterate>
</ol>

重申一下, JSTL 也是一個(gè)替代選擇。JSTL c:forEach標(biāo)簽將比Struts logic:iterate標(biāo)簽要容易使用一些。下面是如何使用JSTL來(lái)產(chǎn)生上面的同一個(gè)排序列表的代碼:
<ol>
<c:forEach var="monthName" items="${calendar.monthSet.months}">
<li><c:out name="${monthName}"/></li>
</c:forEach>
</ol>

相關(guān)動(dòng)作
第3.4式在JSTL循環(huán)中使用索引屬性。
第3.5式則提供了一個(gè)更加詳細(xì)的關(guān)于在JSTL循環(huán)中使用索引屬性的說(shuō)明。