Struts祕籍之第2段:第3.4式:在表單中使用索引屬性

 

第3.4式. 在表單中使用索引屬性

問題

你想要在表單中創建對應於一個Bean中的索引屬性的一套輸入字段。

動作要領

在Struts html標籤庫的標籤中使用indexed屬性來產生屬性值:

 

None.gif<html:form action="TestOneAction"><p>
None.gif  
<logic:iterate name="MyForm" property="stringArray" 
None.gif                   id
="stringValue" indexId="ctr">
None.gif    
<br/>
None.gif    
<html:text property="stringArray" indexed="true"/>
None.gif
</logic:iterate>
None.gif
</html:form>
None.gif

 

動作變化

如第3.3時所示,訪問索引值以供顯示是很容易的。但是,在表單中使用索引屬性則有些麻煩。如果所產生的輸入字段的名稱沒有正確的格式化,在HTML表單被提交後, Apache Struts Web Framework 便不能正確的裝配ActionForm。Struts 要使用Jakarta Commons BeanUtils 包來從HTTP請求中的值組裝ActionForm。特別地,BeanUtils.populate( )方法是從表單提交時從HTTP請求數據發送的數據中裝載ActionForm的。

對於索引值,BeanUtils.populate( )使用請求參數來決定適當的setter 方法以調用ActionForm。表3-3 列出了不同的表單輸入字段是如何處理的。表中列出了HTML 標籤,對應的HTTP 請求響應對,以及在請求被處理時在ActionForm之上調用的方法。

表3-3. ActionForm 組裝示例

HTML form 輸入標記

產生的請求對

導致的方法調用

<input type="text" name="bar">

bar=someValue

Form.setBar("someValue")

<input type="text" name="sna.fug">

sna.fug=blah

Form.getSna( ).setFug("blah");

<input type="text" name="baz[0]">

baz[0]=someValue

Form.setBaz(0,"firstVal");

<input type="text" name="glub[1].waf">

glub[1].waf=halb

Form.getGlub(1).setWaf("halb");

<input type="text" name="dog.leg[2]">

dog.leg[2]=lame

Form.getDog( ).setLeg(2, "lame");

 

考慮一個允許用戶輸入最喜愛列表,比如顏色和網站,的表單。持有這些數據的ActionForm包含一個表示用戶名稱的String屬性,表示用戶喜好顏色的String數組,以及一個表示用戶喜好網站的WebLink對象的List。WebLink類如Example 3-5所示,它定義了一個簡單的JavaBean,具有表示站點名稱和URL的屬性。

Example 3-5. WebLink JavaBean

 

None.gifpackage com.oreilly.strutsckbk;
None.gif
ExpandedBlockStart.gif
public class WebLink {
ExpandedSubBlockStart.gif    
public String getName( ) {
InBlock.gif        
return name;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public void setName(String name) {
InBlock.gif        
this.name = name;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public String getUrl( ) {
InBlock.gif        
return url;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public void setUrl(String url) {
InBlock.gif        
this.url = url;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
private String url;
InBlock.gif    
private String name;
ExpandedBlockEnd.gif}

None.gif

 

form bean, FavoritesForm, 則包含了用戶名稱,喜愛顏色,以及喜好網站。如Example 3-6所示:

Example 3-6. FavoritesForm form bean

 

None.gifpackage com.oreilly.strutsckbk;
None.gif
None.gifimport java.util.ArrayList;
None.gifimport java.util.List;
None.gif
None.gifimport org.apache.struts.action.ActionForm;
None.gif
ExpandedBlockStart.gif
public final class FavoritesForm extends ActionForm  {
ExpandedSubBlockStart.gif    
public FavoritesForm( ) {
InBlock.gif        webLinks 
= new ArrayList( );
InBlock.gif        
for (int i=0; i<5; i++) webLinks.add(new WebLink( )); 
InBlock.gif        colors 
= new String[3];
ExpandedSubBlockEnd.gif    }
    
ExpandedSubBlockStart.gif    
public String getName( ) {
InBlock.gif        
return name;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public void setName(String name) {
InBlock.gif        
this.name = name;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public String getColor(int index) {
InBlock.gif        
return colors[index];
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public void setColor(int index, String color) {
InBlock.gif        colors[index] 
= color;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public String[] getColor( ) {
InBlock.gif        
return colors;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public List getWebLinks( ) {
InBlock.gif        
return webLinks;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public WebLink getWebLink(int index) {
InBlock.gif        
return (WebLink)webLinks.get(index);
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gif    
public void setWebLink(int index, WebLink webLink) {
InBlock.gif        webLinks.
set(index, webLink);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedSubBlockStart.gif    
public void reset( ) {
InBlock.gif        webLinks.clear( );
InBlock.gif        colors 
= new String[3];
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
private List webLinks;
InBlock.gif    
private String name;        
InBlock.gif    
private String[] colors;    
ExpandedBlockEnd.gif}

None.gif

 

現在你可以創建一個JSP 頁面 (favorites.jsp) ,通過它用戶可以輸入表單中的相應數據,其代碼如Example 3-7所示.

Example 3-7. FavoritesForm JSP

 

None.gif<%@ page contentType="text/html;charset=UTF-8" language="java" %>
None.gif
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
None.gif
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
None.gif
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
None.gif
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
None.gif
None.gif
<html:html locale="true">
None.gif
<head>
None.gif
<title><bean:message key="index.title"/></title>
None.gif
<html:base/>
None.gif
</head>
None.gif
<body bgcolor="white">
None.gif
<h2>Favorites Poll</h2>
None.gif
<html:form action="/admin/ViewFavorites">
None.gif    
<p>
None.gif        What is your name:
None.gif        
<br/><html:text property="name"/>
None.gif    
</p>
None.gif    
<p>
None.gif        What are your three favorite colors:
None.gif        
<br/><html:text property="color[0]"/>
None.gif        
<br/><html:text property="color[1]"/>
None.gif        
<br/><html:text property="color[2]"/>
None.gif    
</p>
None.gif   
<p>
None.gif      What are your favorite links?
None.gif      
<table>
None.gif         
<tr>
None.gif            
<th>Name</th>
None.gif            
<th>URL</th>
None.gif         
</tr>
None.gif         
<tr>
None.gif            
<td><html:text property="webLink[0].name"/></td>
None.gif            
<td><html:text property="webLink[0].url"/></td>
None.gif         
</tr>
None.gif      
</table>
None.gif   
</p>
None.gif    
<html:submit/>
None.gif    
<html:reset/>
None.gif
</html:form>
None.gif
</body>
None.gif
</html:html>
None.gif

 

因爲Example 3-7 中的索引值是硬編碼,不是動態的,html:text標籤的property值便很容易構造,所以產生的HTML 標籤便具有適當的name屬性值。然而,假設你想要使用logic:iterate標籤來產生重複的輸入字段。比如,爲了對color屬性這樣做,你可能想要嘗試以下的JSP 代碼:

 

None.gifWhat are your three favorite colors:
None.gif  
<logic:iterate name="FavoritesForm" id="theColor">
None.gif    
<br/><html:text property="color" indexed="true"/>
None.gif  
</logic:iterate>
None.gif

 

但是這段代碼不會產生需要的HTML 標記。indexed屬性對爲特定的Struts html標籤(這裏是html:text)的name屬性所指定的值應用一個索引(即, [n]) 。如果你使用上面的片斷部署了一個JSP ,所產生的HTML可能是下面的樣子:

 

None.gifWhat are your three favorite colors:
None.gif
<br/><input type="text" name="org.apache.struts.taglib.html.
None.gifBEAN[0].color"
 value="[Ljava.lang.String;@5f1ba8">
None.gif
<br/><input type="text" name="org.apache.struts.taglib.html.
None.gifBEAN[1].color"
 value="[Ljava.lang.String;@5f1ba8">
None.gif
<br/><input type="text" name="org.apache.struts.taglib.html.
None.gifBEAN[2].color"
 value="[Ljava.lang.String;@5f1ba8">
None.gif

 

索引並沒有應用到屬性的值。相反,卻被應用到了Form Bean的內部internal Apache Struts Web Framework 名稱。另外,value包含了對數組調用toString( )方法的結果,而不是數組中特定的元素。.

說到底,意思就是當你需要設置一個本身是複雜對象,比如一個JavaBean 的索引屬性的嵌套的簡單屬性時,indexed屬性時很有用的。你可以在logic:iterate標籤中爲一個非嵌套屬性產生輸入字段,但是你卻必須藉助scriptlet 來產生數組索引:

 

None.gifWhat are your three favorite colors:
None.gif  
<logic:iterate name="FavoritesForm" id="theColor" indexId="ctr">
None.gif    
<br/><html:text property='<%="color["+ctr+"]"%>'/>
None.gif  
</logic:iterate>
None.gif

 

假設你想要使用logic:iterate標籤來爲喜好鏈接(WebLink對象)產生輸入字段。這種情況下,indexed的行爲則正如你願:

 

None.gifWhat are your favorite links?
None.gif
<table>
None.gif  
<tr>
None.gif     
<th>Name</th>
None.gif     
<th>URL</th>
None.gif  
</tr>
None.gif  
<logic:iterate id="webLink" name="FavoritesForm" property="webLinks">
None.gif    
<tr>
None.gif      
<td><html:text name="webLink" property="name" indexed="true"/></td>
None.gif      
<td><html:text name="webLink" property="url" indexed="true"/></td>
None.gif    
</tr>
None.gif  
</logic:iterate>
None.gif
<table>
None.gif

 

在html標籤中使用indexed屬性多少有點使人混淆。混淆之處主要來自於name屬性的不同意義。大多數情況下,在使用html標籤時,name都可以忽略因爲值將基於action mapping 中聲明的form-bean。然而,在使用indexed屬性時,name卻引用到對應的ActionForm的嵌套的索引屬性。

我們回去看color屬性的問題,你可以選擇使用scriptlet之外的方式。可以使用Struts html-el標籤或者JSTL。它們都可以做一些和scriptlet相同的基本事情,但是它們是通過EL 表達式來進行的。最簡潔的方法是使用html-el標籤:

 

None.gifWhat are your three favorite colors:
None.gif  
<logic:iterate name="FavoritesForm" id="theColor" indexId="ctr">
None.gif    
<br/><html-el:text property='color[${ctr}]>'/>
None.gif  
</logic:iterate>
None.gif

 

如你喜歡JSTL,你也可以直接產生需要的輸入標籤而不是使用Struts html標籤:

 

None.gifWhat are your three favorite colors:
None.gif
<logic:iterate id="color" name="FavoritesForm" property="color" indexId="ctr"> 
None.gif  
<br/><input type="text" name="color[<c:out value='${ctr}'/>]"
None.gif             
None.gifvalue
="<c:out value='${FavoritesForm.color[ctr]}'/>"/>
None.gif
None.gif
</logic:iterate>
None.gif

 

這個JSTL 版本幾乎和原來使用scriptlet的版本一樣醜陋。另外,因爲Struts html:text和html-el:text標籤都沒使用, HTML input標籤的value屬性必須是顯式編碼的。如果你使用Struts html:text標籤,這個值就是自動設置的。

相關招式

第3.3式討論了在表單之外顯示索引屬性所用的技術。

第3.5式討論如何在JSTL c:forEach循環中使用索引屬性。

Jakarta Commons項目的BeanUtils包定義了索引屬性如何解析。相關信息可訪問:http://jakarta.apache.org/commons/beanutils/api/org/apache/commons/beanutils/package-summary.html#package_description.

[引用提示]阿泠引用了該文章, 地址: http://blog.donews.com/inclear/archive/2005/11/12/624363.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章