今天剛學習了Struts2的類型轉換器,感覺非常不錯
12.Struts2的類型轉換
(1). 定義類型轉換器
類型轉換器主要用於一個字符串與一個複雜對象之間的相互轉換。Struts2的類型轉換器是基於OGNL實現的,在OGNL中提供了TypeConverter接口,如果要實現類型轉換器則必須實現上述接口。
TypeConverter接口:
public interface TypeConverter{
public Object convertValue(Map context, Object target, Member member,
String propertyName, Object value, Class toType);
}
從上面的接口定義可以看出TypeConverter接口的方法太過於複雜,基於此原因,OGNL提供了一個該接口的實現類:DefaultTypeConverter,可以通過繼續該類並重寫此類中的convertValue方法來實現自己的類型轉換器。
convertValue方法負責完成類型的轉換,這種轉換是雙向的,可以通過toType的類型來判斷轉換的方向,toType參數的類型是需要轉換的目標類型,如當toType爲User時表明將字符串轉換爲User類型;當toType爲String時,表明將User轉換爲String類型。
DefaultTypeConverter轉換器把所有的請求參數作爲字符串數組,而非字符串。
(2). 註冊類型轉換器
要使類型轉換器起作用,必須要將其註冊到WEB應用中,根據註冊方式的不同,可以分爲以下三種:
l 註冊爲局部類型轉換器;
l 註冊爲全局類型轉換器;
l 使用JDK1.5的註釋來註冊類型轉換器。
要註冊局部類型轉換器,只需要提供文件名如下格式的文件並放在與相應的Action路徑相同的位置:
ActionName-conversion.properties
其中ActionName是需要轉換器生效的Action的類名。
其文件內容爲:
propertyName = 類型轉換器類
ActionName-conversion.properties文件由多個“propertyName = 類型轉換器類”組成,其中propertyName是Action中需要類型轉換器轉換的屬性名,類型轉換器是用戶開發的類型轉換器的全限定類名。
例如:user = com.demo.converter.UserConverter
要註冊全局類型轉換器需要提供一個xwork-conversion.properties文件,其內容由多個“複合類型 = 對應類型轉換器”項組成,其中“複合類型”批定需要完成類型轉換的複合類,“對應類型轉換器”指類型轉換器的全限定類名。
例如:com.demo.User = com.demo.converter.UserConverter
(3). 基於Struts2的類型轉換器
Struts2框架爲了簡化類型轉換器的實現,提供了StrutsTypeConverter抽象類,此類繼承自DefaultTypeConverter類,並提供了兩個抽象方法:
l convertFromString(Map context, String[] values, Class toClass);
l convertToString(Map context, Object o);
(4). 基於OGNL表達式方式的類型轉換
①.由於Struts2支持OGNL表達式,故我們可以使用另外一種方式來將請求參數轉換成複合類型。具體做法是在JSP頁面中利用OGNL表達式來直接生成複合類型實例,示例:
<form action=”Login.do”>
用戶名:
<input type=”text” name=”user.name” />
密碼:
<input type=”text” name=”user.password” />
</formd>
上述的兩個請求參數user.name, user.password,是一種表達式的寫法,Struts2會把user.name參數的值賦值給Action實例的user屬性的name屬性,把user.password參數的值賦給Action實例的user屬性的password屬性,這樣的話就可以把字符串參數直接轉換成複合類型對象,使用這種方式時需要注意:
l 必須爲複合類型提供無參數的構造器;
l 複合類型必須爲要設值的屬性提供set方法,同時需要在Action中提供針對該複合類型的set方法。例如,要使用user.name爲user屬性的name屬性賦值,必須提供setName方法,同時在Action中也必須提供setUser方法。
②.Struts2直接將參數封裝成Map裏的對象
設置JSP表單域的name屬性爲”Action屬性名[‘key值’].屬性名”的形式,其中Action屬性名是Action類裏包含的Map類型屬性,最後一個屬性名是Map對象裏複合類型對象的屬性名。
(5). Struts2對Collection和Map的支持
在Action屬性中若使用了集合類型,如List, Map, Set等的同時,又想讓類型轉換器起作用的話,有以下兩種方法:
l 使用泛型來限制集合裏的元素的類型;
l 使用Struts2的局部類型轉換配置文件來指定集合元素的數據類型;
下面對局部類型轉換配置文件進行說明:
需要在配置文件中提供以下key-value對:
Element_xxx = 複合類型
其中Element是固定的,xxx是Action中的集合屬性名,複合類型是集合元素類型的全限定類名,例如指定Action類address集合屬性的元素爲com.demo.Address實例,代碼:
Element_address = com.demo.Address
如果是Map類型的屬性,則需要同時指定Map的key類型和value類型,指定key類型需要增加:
Key_xxx = 複合類型
其中Key爲固定的,xxx是Map類型屬性的屬性名,複合類型指定的是Map屬性的key類型的全限定類名;
指定Map類型屬性的value類型,需要增加:
Element_xxx = 複合類型
通過以上設置後,包含集合類型的Action所配置的類型轉換器才能正常使用。
在JSP上輸出List屬性的某個元素的值,可以使用如下格式:
<s:property value=”集合屬性名[索引].集合元素屬性名” />
在集合類中,Set類型的處理是比較特殊的,爲了方便訪問Set屬性中的集合元素,需要指定集合元素的索引屬性,這通過在局部類型轉換文件中增加如下語句來實現:
KeyProperty_集合屬性名 = 集合元素的索引屬性名
其中集合屬性名是Action中的集合屬性名,集合元素的索引屬性名是可以唯一表示集合元素的屬性名,例如:
#指定集合屬性users的集合元素類型爲com.demo.User
Element_users = com.demo.User
#指定users集合屬性裏集合元素的索引屬性是name
KeyProperty_users = name;
通過上述配置後,就可以直接通過該索引屬性值來訪問該集合元素,訪問方式爲:
集合屬性名(‘索引屬性值’)
例如:訪問users集合屬性裏索引屬性值爲yuzp的元素的name屬性
users(‘yuzp’).name
(6). 類型轉換的錯誤處理
Struts2在struts-default.xml文件中配置一個conversionError攔截器,如果Struts2的類型轉換器在執行轉換時出錯,該攔截器將負責將對應的錯誤封裝成表單域錯誤,並放入ActionContext中,然後系統會跳轉到input邏輯視圖。
爲了輸出錯誤信息,使用標籤<s:fielderor/>,錯誤信息默認爲英文,如果需要輸出中文出錯信息,則需要在資源文件中增加如下代碼:
xwork.default.invalid.fieldvalue = {0}字段類型轉換失敗!
除此之外,如果想對某一特定字段指定特別的提示信息,則需要提供名爲ActionName. properties的Action局部資源文件,並加入以下代碼:
invalid.fieldvalue.屬性名 = 提示信息
其中invalid.fieldvalue爲固定值,屬性名是Action中屬性名