使用Spring MVC表單標(轉)

概述
    在低版本的Spring中,你必須經過JSTL或<spring:bind>將表單對象綁定到HTML表單頁面中,對於習慣了Struts表單標籤的開發者來講,Spring MVC的這一表現確實讓人失望。不過這一狀況已經一去不復返了,從Spring 2.0開始,Spring MVC開始全面支持表單標籤,經過Spring MVC表單標籤,咱們能夠很容易地將控制器相關的表單對象綁定到HTML表單元素中。
在上一篇文章《Spring MVC的表單控制器》中(http://tech.it168.com/j/2007-07-26/200707261434046.shtml)咱們已經使用到了部分的Spring MVC表單標籤,在本文中咱們將對Spring MVC表單標籤進行全面的介紹,讓咱們首先從<form.:form>標籤開始吧。

form標籤
    和使用任何JSP擴展標籤同樣,在使用Spring表單標籤以前,你必須在JSP頁面中添加一行引用Spring表單標籤的聲明,以下所示: css

<% @ page language = " java " contentType = " text/html; charset=UTF-8 " pageEncoding = " UTF-8 " %> <% @ taglib prefix = " form " uri = " http://www.springframework.org/tags/form " %> ①引入標籤的聲明 < html > … ②聲明後,在頁面中就可使用任意Spring表單標籤了 </ html >

    通常狀況下,咱們使用「form」做爲Spring MVC表單標籤的前綴,固然只要願意,你能夠調整爲其它的前綴名。在聲明好標籤引用後,就能夠在該JSP文件中使用全部Spring MVC的表單標籤了。下面是一個使用<form.:form>表單標籤的示例,它將最終生成一個HTML的 form表單:  html

< form.:form > 用戶名: < form.:input path ="userName" /> < br > 密 碼: < form.:password path ="password" />< br > Email: < form.:input path ="email" />< br > < input type ="submit" value ="註冊" name ="testSubmit" /> < input type ="reset" value ="重置" /> </ form.:form >

     
     回憶一下咱們在《Spring MVC的表單控制器》(http://tech.it168.com/j/2007-07-26/200707261434046.shtml)文章中介紹的用戶註冊表單控制器,用戶經過GET請求調用表單控制器時,表單控制器生成一個新的表單對象,而後重定向到表單輸入頁面。正由於表單頁面是經過訪問表單控制器導向過來的,因此<form.:form>標籤自己無需作額外的設置就能夠達到如下兩個目標:
    1) 它不須要象HTML的<form>標籤或Struts的表單標籤同樣經過action屬性指定表單提交的地址。假設和<form.:form>標籤對應的控制器的URL是「/registerUser.html」,應用部署目錄爲「baobaotao」,則最後產生的HTML代碼自動包含表單提交地址:
<form. id="command" method="post" action="/baobaotao//registerUser.html">…</form>
    2) <form.:form>標籤內部的組件標籤(如<form.:input>、<form.:password>等)能夠直接和表單控制器所對應的表單對象進行值綁定。

    默認狀況下,表單控制器將表單對象以「command」爲名放到PageContext中,你能夠經過表單控制器commandName屬性的設置使用其它的名字(假設設置爲「user」),這時你必須經過<form.:form. commandName="user">顯式指定綁定的表單對象名稱。

    除了commandName屬性外,Spring表單標籤擁有豐富的可設置屬性,這些屬性大都是HTML表單標籤屬性的鏡像,如onclick、ondblclick、tabindex等等。須要注意的一點是這些屬性都是小寫的,而對應的HTML標籤的屬性則沒有這個限制。可是有幾個和HTML標籤有區別的屬性,咱們經過表 1進行說明:
    表 1 表單元素標籤特殊屬性 java

 
目錄
說明
cssClass
使用該屬性指定表單元素CSS樣式名,至關於HTML元素的class屬性。示例:<form.:input path="userName" cssClass="inputStyle"/>。
cssStyle
直接經過該屬性指定樣式,至關於HTML元素的style屬性。示例:
<form.:input path="userName" cssStyle="width:100px"/>。
cssErrorClass
cssClass表示表單元素未發生錯誤時對應的樣式,而cssErrorClass表示表單元素髮生錯誤時對應的樣式,示例:
<form.:input path="userName" cssClass="sty1" cssErrorClass= "sty2"/>

 

輸入組件標籤
    表單中有一些用於接受輸入值的組件,如單行文本框、多行文本框以及密碼框,Spring爲它們提供了對應的表單標籤,請看下面的例子:
代碼清單 1 使用輸入組件標籤的表單 web

< form.:form > 用戶名: < form.:input path ="userName" /> < br > ①單行文件框標籤密 碼: < form.:password path ="password" />< br > ②密碼框標籤描 述: < form.:textarea path ="desc" cols ="20" rows ="3" />< br > ③多行文件框標籤 < form.:hidden path ="times" /> ④隱藏組件的值 < input type ="submit" value ="註冊" name ="testSubmit" /> < input type ="reset" value ="重置" /> </ form.:form >

    正如你看到的,全部表單組件標籤都經過path屬性綁定表單對象的屬性值,它支持級聯屬性,好比path="user.userName"將調用表單對象getUser.getUserName()綁定表單對象的屬性值。這些表單組件標籤擁有大多數HTML組件標籤的鏡像屬性,如③處的<form.:textarea>就使用了cols和rows屬性設定列數和行數。

以上使用表單標籤的頁面的對應HTML頁面以下所示:spring

< form. id ="command" method ="post" action ="/baobaotao//registerUser.html" > 用戶名: < input id ="userName" name ="userName" type ="text" value ="" />< br > 密 碼: < input id ="password" name ="password" type ="password" value ="" />< br > 描 述: < textarea id ="desc" name ="desc" rows ="3" cols ="20" ></ textarea >< br > < input id ="times" name ="times" type ="hidden" value ="0" /> < input type ="submit" value ="註冊" name ="testSubmit" /> < input type ="reset" value ="重置" /> </ form >

單選框和複選框組件標籤
    單選框和複選框組件雖然在HTML中都對應<input>元素標籤,但在Spring MVC表單標籤中,它們分別對應兩個更達意的標籤:     數據庫

< form.:radiobutton > < form.:checkbox > 。 radiobutton 單選框組件由兩個同名的標籤組件組成,當表單對象對應屬性值和value值相等時,單選框選中。下面是一個表明性別的單選框: < form.:form > 性 別: < form.:radiobutton path ="sex" value ="0" /> < form.:radiobutton path ="sex" value ="1" /> </ form.:form > 當表單對象的sex屬性爲0時(能夠是String、int等能夠自動轉換爲String的類型),所生成的HTML代碼以下所示: < form. id ="command" method ="post" action ="/baobaotao//registerUser.html" > 性 別: < input id ="sex1" name ="sex" type ="radio" value ="0" checked ="checked" /> < input id ="sex2" name ="sex" type ="radio" value ="1" /> </ form > 

 

checkbox
    複選框組件標籤相對來講複雜一些,複選框組件對應的表單屬性不但能夠boolean類型,還能夠是String[]、Collection,Enum等類型。針對不一樣屬性類型,複選框的選中狀態的判斷條件是不同的:
 boolean類型:當對應屬性爲true時,該複選框選中(一個屬性僅對應一個複選框);
 String[]、Collection或Enum類型:複選框對應值出如今對應屬性列表中,該複選框選中;
 其它類型:當複選框對應的值能夠轉換爲對應屬性值,該複選框選中。
假設用戶註冊的User表單對象包含了一個List類型的favorites屬性:
import java.util.List;
public class User {
private List favorites;
public List getFavorites() {
return favorites;
}
public void setFavorites(List favorites) {
this.favorites = favorites;
}
}
咱們但願將其在頁面中使用一個複選框組件綁定這個屬性,則可使用如下的代碼:
代碼清單 2 複選框標籤的使用
<form.:form>
興趣愛好:
<form.:checkbox path="favorites" value="1"/>computer
<form.:checkbox path="favorites" value="2"/>sport
<form.:checkbox path="favorites" value="3"/>entertainment
<form.:checkbox path="favorites" value="4"/>literature
</form.:form>
除了正常的path屬性名外,還必須提供一個value屬性,假設User表單對象的favorites屬性包括了1和3的值,那麼產生的HTML頁面爲:
<form. id="command" method="post" action="/baobaotao//registerUser.html">
興趣愛好:<input id="favorites1" name="favorites" type="checkbox" value="1" checked="checked"/>
<input type="hidden" value="1" name="_favorites"/>computer
<input id="favorites2" name="favorites" type="checkbox" value="2" />
<input type="hidden" value="1" name="_favorites"/>sport
<input id="favorites3" name="favorites" type="checkbox" value="3" checked="checked"/>
<input type="hidden" value="1" name="_favorites"/>entertainment
<input id="favorites4" name="favorites" type="checkbox" value="4"/>
<input type="hidden" value="1" name="_favorites"/>literature
</form>
你們可能已經注意到每一個複選框組件的後臺都跟着一個隱藏組件,這是由於當HTML頁面中的複選框沒有被選中時,這個複選框的值不會在表單提交時做爲HTTP請求參數發送到服務器端,這給Spring的表單數據綁定形成了麻煩——由於沒法觸發setFavorites()方法的調用(若是原來已經有值,這個值不會被設置爲空)。解決方法就是在每一個複選框後面加一個隱藏組件,而且將對應的複選框名字前添加一個下劃線("_")做爲隱藏組件的名字。這樣一來,你至關於告訴Spring「這個表單中存在這樣一個複選框,我但願表單對象中對應的屬性和這個checkbox的狀態保持一致」。
假設複選框對應的選項在數據庫或配置文件中定義,那麼頁面複選框標籤就不能經過硬編碼的方式指定,相反必須根據配置的選項數據動態產生。對於這樣的需求,代碼清單 2的編寫方式顯然不能知足需求。回憶一下表單控制器的工做流程,咱們知道能夠經過複寫referenceData()方法在表單顯示前準備一些須要的數據,如今終於派上用場了,來看一下具體的實現:

代碼清單 3 UserRegisterController:準備表單顯示數據 服務器

package com.baobaotao.web.user; … import org.springframework.ui.ModelMap; public class UserRegisterController extends SimpleFormController { private BbtForum bbtForum; ①建立初始表單對象 protected Object formBackingObject(HttpServletRequest request) throws Exception { int userId = ServletRequestUtils.getIntParameter(request, " userId " , - 1 ); User user = bbtForum.getUser(userId); user.setUserName( " tom " ); List favorites = new ArrayList();① - 1默認選中值爲1和3的選項 favorites.add( " 1 " ); favorites.add( " 3 " ); user.setFavorites(favorites); return user; } @Override ②準備表單顯示時須要的數據 protected Map referenceData(HttpServletRequest request) throws Exception { Map favoriteMap = new LinkedHashMap(); favoriteMap.put( " 1 " , " computer " ); favoriteMap.put( " 2 " , " sport " ); favoriteMap.put( " 3 " , " entertainment " ); favoriteMap.put( " 4 " , " literature " ); ② - 1將表單頁面須要的對象以ModelMap返回,最終將以屬性名值對方式出如今請求屬性中 return new ModelMap().addObject( " favoriteMap " , favoriteMap); } @Override protected ModelAndView onSubmit(Object command, BindException errors) throws Exception { User user = (User) command; bbtForum.registerUser(user); return new ModelAndView(getSuccessView(), " user " , user); } }

    在以上代碼中咱們覆蓋了SimpleFormController的referenceData()和formBackingObject ()方法。參照《Spring MVC的表單控制器》中(http://tech.it168.com/j/2007-07-26/200707261434046.shtml)介紹的表單控制器工做流程,能夠知道formBackingObject()方法用於表單頁面初始化時使用的表單對象。咱們在formBackingObject()方法中,將User的favorites屬性的初始值設置爲1和3(分別對應computer和entertainment的選項),如①所示。
在②處,咱們覆蓋了referenceData()方法,該方法爲表單頁面準備一些數據。該方法返回值類型爲Map,該Map的鍵值將會綁定到請求的屬性中。ModelMap是Spring 2.0新增的Map實現類,它提供了鏈式方法和默認鍵值的機制。這裏,咱們使用ModelMap綁定了一個鍵爲「favoriteMap」,值爲favoriteMap的數據對象。favoriteMap是全部興趣愛好的選項,在實際的應用中,你能夠從數據庫中或配置文件中進行加載。
當請求中綁定了favoriteMap時,對應的表單頁面就能夠遍歷該Map並動態構造出複選框列表了:    框架

<% @ page language = " java " contentType = " text/html; charset=UTF-8 " pageEncoding = " UTF-8 " %> <% @ taglib prefix = " form " uri = " http://www.springframework.org/tags/form " %> <% @ taglib uri = " http://java.sun.com/jsp/jstl/core " prefix = " c " %> < html > < head > < title > 寶寶淘論壇用戶註冊 </ title > </ head > < body > < form.:form > … 興趣愛好: < c:forEach items = " ${favoriteMap} " var = " favorite " > ①引用favoriteMap的請求屬性 ②引用Map的鍵和值 < form.:checkbox path = " favorites " value = " ${favorite.key} " /> ${favorite.value} </ c:forEach > < input type = " submit " value = " 註冊 " name = " testSubmit " /> < input type = " reset " value = " 重置 " /> </ form.:form > </ body > </ html >

    在①處,咱們經過JSTL標籤對屬性名爲favoriteMap的模型數據對象進行遍歷,爲每個元素項生成一個複選框。注意②處的複選框代碼,它有兩個明顯的特徵:1)使用Spring複選框標籤;2)經過EL引用Map類型的模型數據。因爲favorite是Map類型,因此咱們能夠經過${favorite.key}和${favorite.value}引用Map元素的鍵和值。

    提示:
    對於同時使用JSTL和Spring表單標籤的JSP文件,JSTL的標籤會被首先解析,而後再解析Spring表單標籤,所以如實例那樣混合使用兩者能夠如預期同樣輸出正確的結果。
下拉框組件標籤
    下拉框標籤的典型形式爲: <form.:select path="city" items="${cityList}"/>,它包括兩方面的數據:1)對應表單對象屬性值(city);2)用於構造整個下拉框選項的數據(cityList)。嚴格地說,下拉框組件分爲單選和多選兩種形式,當表單對象對應屬性爲複數形態的類型時(如String[]、List、Set),產生的目標組件爲多選下拉框,反之爲單選下拉框。
用於構造下拉框選項的數據也必須在referenceData()方法中準備好(可能從數據庫字典表中加載或從外部配置文件中加載):
代碼清單 4 UserRegisterController:爲下拉框標籤準備數據 jsp

package com.baobaotao.web.user; … public class UserRegisterController extends SimpleFormController { @Override protected Map referenceData(HttpServletRequest request) throws Exception { Map favoriteMap = new LinkedHashMap(); favoriteMap.put( " 1 " , " computer " ); favoriteMap.put( " 2 " , " sport " ); favoriteMap.put( " 3 " , " entertainment " ); favoriteMap.put( " 4 " , " literature " ); List cityList = new ArrayList();①爲下拉框選項準備的數據 cityList.add( " 北京 " ); cityList.add( " 上海 " ); cityList.add( " 天津 " ); cityList.add( " 廈門 " ); return new ModelMap() .addObject( " favoriteMap " , favoriteMap) .addObject( " cityList " , cityList); } … } 這時,生成的下拉框HTML代碼以下所示: < select id = " city " name = " city " > < option value = " 北京 " > 北京 </ option > < option value = " 上海 " > 上海 </ option > < option value = " 天津 " > 天津 </ option > < option value = " 廈門 " > 廈門 </ option > </ select > < input type = " hidden " name = " _city " value = " 1 " />

    首先,咱們注意到②處有一個和複選框組件類似的配套隱藏組件,之因此會須要這個隱藏組件是出於和複選框相同的緣由。下拉框的值和標籤是相同的,都是cityList列表中的元素值。在實際應用中,咱們通常爲每個選項提供一個代碼,而非採用和標籤相同的值,這樣可使用規範簡短的代碼保存數據,爲後續的查詢、引用帶來方便。這時,能夠採用下拉框標籤的另外一種屬性設置方式:
<form.:select path="city" items="${cityMap}" itemValue="key" itemLabel="value"/>
cityMap是一個已經經過referenceData()方法準備好的Map對象,itemValue對應下拉框的value屬性,而itemValue="key"表示使用cityMap元素的鍵,itemLable對應下拉框的標籤值, itemLabel="value"表示使用cityMap元素的值。實際上,items屬性所綁定的也能夠是一個List對象,其元素能夠是一個JavaBean,這時能夠經過itemValue和itemLabel指定引用JavaBean的屬性。以下所示:
<form.:select path="city" items="${cities}" itemValue="code" itemLabel="name"/>
cities對應一個經過referenceData()方法準備好的List對象,其元素爲City對象,City對象包括code和name兩個屬性。經過以上這些方式,咱們能夠獲得一個選項的值和標籤不相同的下拉框:
<select id="city" name="city">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">天津</option>
<option value="4" >廈門</option>
</select>
<input type="hidden" name="_city" value="1"/>
通常狀況下,下拉框會提供一個相似於「請選擇」或「--未選擇--」的默認選項,這個選項自己不是有效的數據項,它們的存在僅僅爲提示用戶做選擇或表明一個未做選擇的空值。這時,咱們可能會考慮手工提供一個下拉框選項,而其它的選項經過referenceData()提供的數據動態生成:
<form.:select path="city">
<form.:option value="" label="--請選擇--"/> ①提示性的選項
<form.:options items="${cityMap}" itemValue="key" itemLabel="value"/>②真實的選項數據
</form.:select>
這樣產生的下拉框在默認狀況下將顯示①處對應的選項,若是用戶沒有選擇,選項至關因而一個空值。②處對應的<form.:options>會將cityMap的數據轉換爲下拉框選項列表。
錯誤標籤
    錯誤標籤是和服務端校驗信息關聯的對應物,假設在服務端經過如下代碼對錶單數據進行校驗:
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName","required.username", "用戶名必須填寫");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password","required.password", "密碼不能爲空");

    當提交的表單數據不合法引起校驗錯誤時,提交的表單將被駁回,請求被重定向到表單輸入頁面,在該頁面中經過ide

< form.:errors > 標籤就能夠顯示出校驗的錯誤信息: < form.:form > 用戶名: < form.:input path ="userName" cssClass ="inputStyle" cssErrorClass ="asdfe" /> < font color ="red" >< form.:errors path ="userName" /></ font > < br > 密 碼: < form.:password path ="password" /> < font color ="red" >< form.:errors path ="password" /></ font > < br > </ form.:form >

    經過path和表單對象特定屬性錯誤信息進行綁定,一個表單對象屬性可能包括一個或多個錯誤信息,也能夠沒有錯誤信息,<form.:errors>會根據錯誤信息的狀況進行合理的展現。此外,path還支持通配符匹配的表示方式:
 path="*": 顯示全部的錯誤信息;
 path="lastName*": 顯示全部屬性名前綴爲lastName的錯誤信息。

小結
    在Spring 2.0中,新增的表單標籤是Spring MVC的一個顯著的升級,它能夠綁定服務端的表單對象,讓頁面數據的渲染工做變得輕鬆。由於Spring MVC框架自己的優越性,使得許多Spring MVC表單標籤無需進行過多的屬性設置就能夠正確使用,所以相比於Struts的表單標籤,Spring MVC在使用上更加方便,更加輕鬆。

 轉自http://blog.csdn.net/xuantian868/article/details/3076264

相關文章
相關標籤/搜索