一、簡介
說明:HTTP 協議傳輸數據沒有類型的概念,在服務器端是通過 request.getParameter()、request.getParameterValue() 方法得到請求參數為 String 或 String[] 類型。
但是這樣使用起來不方便,我們希望開源框架能自動的完成類型轉換,到使用的時候能直接獲取目標類型。
二、Struts2 類型轉換
1. Struts2 本身完成了字符串類型到基本數據類型的自動轉換,其他情況需要我們定義自己的類型轉換器。=
2.類型轉換失敗時的處理方式
(1) 默認情況下 Struts2 對於類型轉換失敗後是不做任何處理的。
(2) 若請求參數到目標基本類型轉化出錯時,會對目標基本類型賦值為默認值。
(3) 若請求參數到目標基本類型包裝類轉化出錯時,會對目標字段賦值為 null。
(4) 若希望在發生錯誤時給出提示,則需要讓目標 Action 類實現 com.opensymphony.xwork2.ValidationAware 接口,這個接口 ActionSupport 已經幫我們實現。
說明:com.opensymphony.xwork2.ValidationAware
包含了 ActionErrors 和 FieldErrors 兩個級別的錯誤消息,實現了該接口的 Action 類,在類型轉換出錯時,會前往 name=input 的 result,若沒有配置,則返回404。
在類型轉換出錯時,不會到目標方法,而是直接返回。對應的是一個攔截器。
(5) 在錯誤顯示頁面,可以從值棧的 Action 類中獲取到錯誤消息,且此錯誤消息可以自定義。
自定義錯誤提示消息:在當前 Action 類所在的包下添加 ActionName.properties 的屬性文件,然後在該屬性文件中添加如下鍵值對:
invalid.fieldvalue.目標字段名=定制的錯誤提示消息
(6) 在值棧中,錯誤消息的數據結構為:Map<String, List<String>>,可以通過 OGNL 表達式的方式來獲取,也可以通過 Struts2 標簽來獲取,如下:
<s:fielderror fieldName="errorFiledName"></s:fielderror>
3.自定義類型轉換器
繼承 StrutsTypeConverter 類,兩個抽象方法
public Object convertFromString(Map context, String[] values, Class toClass) : context 可以看做是 Map 棧,values 代表傳入的請求參數, toClass 代表要轉換的目標類。
public String convertToString(Map context, Object o) : 將傳入的 o 轉換為字符串。
(1) 類級別的
在同包下創建包含要轉換的屬性的類簡單類名 + "-conversion.properties", 如:TypeConverterTestAction-conversion.properties,TypeConverterTestAction 類中包含一個 person 屬性。
在創建的類型轉換資源文件中添加:要轉換的屬性=類型轉換器全類名,如: person=com.nucsoft.struts2.convert.MyTypeConverter
(2) 全局級別的
在類路徑的根目錄下創建:xwork-conversion.properties 屬性文件
內容:需要轉換的類的全類名=類型轉換器的全類名,如:com.nucsoft.struts2.helloworld.Person=com.nucsoft.struts2.convert.MyTypeConverter
自定義類型轉換出錯的處理方式也和之前一樣。
4.復雜類型數據的類型轉換
(1)目標 Action 不實現 ModelDriven 接口,也就是說棧頂對象是當前 Action 類的情況
[1]單獨的一個復雜對象,表單標簽與對象屬性對應:person
<s:form action="converter/typeConverter" method="post"> <s:textfield name="person.userName" label="userName"/> <s:textfield name="person.age" label="age"/> <s:submit value="submit"/> </s:form>
(2) 目標 Action 實現 ModelDriven 接口,棧頂對象為 getModel 返回值類型。
[1] 單獨一個復雜類型,對應多個標簽
<s:form action="converter/typeConverter" method="post"> <s:textfield name="userName" label="person"/> <s:textfield name="age" label="age"/> <s:submit value="submit"/> </s:form>
[2]單獨的一個復雜對象,只有一個表單標簽,按照指定格式進行轉換為對應的復雜對象:
<s:form action="converter/typeConverter" method="post"> <s:textfield name="person" label="person"/> <s:submit value="submit"/> </s:form>
輸入的格式:
AA,12
需要對目標 Action 自定義 person 類型轉換器,或定義全局的類型轉換器,如:
/** * @author solverpeng * @create 2016-07-09-11:00 */ public class MyTypeConverter extends StrutsTypeConverter { @Override public Object convertFromString(Map context, String[] values, Class toClass) { Person person = null; if(Person.class == toClass) try { person = (Person) toClass.newInstance(); String strs = values[0]; person.setUserName(strs.split(",")[0]); person.setAge(Integer.parseInt(strs.split(",")[1])); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); } return person; } @Override public String convertToString(Map context, Object o) { return null; } } MyTypeConverter[3]復雜對象中包含另一個復雜對象,如 Person 中包含 Address。
對應多個標簽:
<s:form action="converter/typeConverter" method="post"> <s:textfield name="userName" label="person"/> <s:textfield name="age" label="age"/> <s:textfield name="address.addressName" label="addressName"/> <s:textfield name="address.location" label="location"/> <s:submit value="submit"/> </s:form>
三個標簽,固定格式:address 用一個標簽,固定格式 addressName,location
<s:form action="converter/typeConverter" method="post"> <s:textfield name="userName" label="userName"/> <s:textfield name="age" label="age"/> <s:textfield name="address" label="address"/> <s:submit value="submit"/> </s:form>
因為 Person 類中包含 Address 屬性,所以在 Person 同包下新建 Person-conversion.properties 文件
內容:address=com.nucsoft.struts2.convert.MyTypeConverter
類型轉換器:
/** * @author solverpeng * @create 2016-07-09-11:00 */ public class MyTypeConverter extends StrutsTypeConverter { @Override public Object convertFromString(Map context, String[] values, Class toClass) { if(Person.class == toClass) { Person person = null; try { person = (Person) toClass.newInstance(); String strs = values[0]; person.setUserName(strs.split(",")[0]); person.setAge(Integer.parseInt(strs.split(",")[1])); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); } return person; } if(Address.class == toClass) { Address address = null; try { address = (Address) toClass.newInstance(); String strs = values[0]; address.setAddressName(strs.split(",")[0]); address.setLocation(strs.split(",")[1]); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); } return address; } return null; } @Override public String convertToString(Map context, Object o) { return null; } } MyTypeConverter5.集合元素對象中的類型轉換
[1] 目標 Action 類包含 List 的復雜對象,如 List<Person>,其中 Address 進行類型轉換時,還是使用 Person 轉換器,且因為為 List<Person>,所以不需要實現 ModelDriven 接口,所以棧頂對象為 當前Action類對象。
<s:form action="converter/typeConverter" method="post"> <s:textfield name="persons[0].userName" label="userName[0]"/> <s:textfield name="persons[0].age" label="age[0]"/> <s:textfield name="persons[0].address" label="address[0]"/> <s:textfield name="persons[1].userName" label="userName[1]"/> <s:textfield name="persons[1].age" label="age[1]"/> <s:textfield name="persons[1].address" label="address[1]"/> <s:submit value="submit"/> </s:form>
[2] 只有一個復雜對象,但是該復雜對象包含 List 屬性,如 Person 類存在 List<Address> 屬性。因為只有一個復雜對象,所以實現 ModelDriven 接口
<s:form action="converter/typeConverter" method="post"> <s:textfield name="userName" label="userName"/> <s:textfield name="age" label="age"/> <s:textfield name="addresses[0].addressName" label="address[0].addressName" /> <s:textfield name="addresses[0].location" label="address[0].location" /> <s:textfield name="addresses[1].addressName" label="address[1].addressName" /> <s:textfield name="addresses[1].location" label="address[1].location" /> <s:submit value="submit"/> </s:form>
6.json類型的數據的類型轉換
未完,待續。