struts2數據類型轉換詳解

Web應用程序的交互都是創建在HTTP之上的,互相傳遞的都是字符串。也就是說服務器接收到的來自用戶的數據只能是字符串或者是字符數組,而在Web應用的對象中,每每使用了多種不一樣的類型,如整數(int)、浮點數(float)、日期(Date)或者是自定義數據類型等。所以在服務器端必須將字符串轉換成合適的數據類型。html

         Struts2框架中爲咱們提供了一些簡單類型的轉換器,好比轉換爲int、float等簡單數據類型是不須要咱們本身定義轉換器去轉換的,struts2內部自己就爲咱們提供了轉換的方法,但像一些複雜的類型和咱們自定義的數據類型仍是須要咱們本身去寫轉換器去轉換的。在轉換工程中,若是在類型轉換中出現異常,類型轉換器開發者無需關心異常處理邏輯,Struts2的conversionError攔截器會自動處理該異常,而且提示在頁面上生成提示信息。java

下面咱們就一步步的實現和註冊一個咱們本身的轉換器,也就是自定義類型轉換器的幾個步驟:數組

一:自定義類型轉換器服務器

實現自定義類型轉換器咱們通常有兩種方式:框架

1.實現OGNL提供的TypeConvert接口以及實現了TypeConvert接口的DefaultTypeConvert類來實現自定義的類型轉換器。咱們來看一下DefaultTypeConvert類的源碼:jsp

 

[java]  view plain  copy
 
 print?
  1. publicclass DefaultTypeConverter implements TypeConverter{  
  2.   
  3.     public DefaultTypeConverter(){  
  4.   
  5.         super();  
  6.   
  7.     }  
  8.   
  9. /** 
  10.  
  11.  * @param context:類型轉換的上下文 
  12.  
  13.  * @param value:須要轉換的參數 
  14.  
  15.  * @param toType:轉換後的目的類型 
  16.  
  17. */  
  18.   
  19. public Object convertValue(Map context,   
  20.   
  21. Object value,   
  22.   
  23. Class toType)  
  24.   
  25.     {  
  26.   
  27.         return OgnlOps.convertValue(value, toType);  
  28.   
  29.     }  
  30.   
  31. public Object convertValue(Map context, Object target,   
  32.   
  33. Member member, String propertyName,  
  34.   
  35.  Object value, Class toType)  
  36.   
  37.     {  
  38.   
  39.         return convertValue(context, value, toType);  
  40.   
  41.     }  
  42. }  

convertValue方法的做用:this

該方法負責完成類型的雙向轉換,爲了實現雙向轉換,咱們經過判斷toType的類型便可判斷轉換的方向。toType類型是須要轉換的目標類型,如:當toType類型是User類型時,代表須要將字符串轉換成User實例;當toType類型是String類型時,代表須要把User實例轉換成字符串類型。經過toType類型判斷了類型轉換的方向後,咱們就能夠分別實現兩個方向的轉換邏輯了。實現類型轉換器的關鍵就是實現conertValue方法,該方法有三個參數:spa

第一個參數 context:類型轉換的上下文.net

第二個參數 value:須要轉換的參數orm

第三個參數 toType:轉換後的目的類型

 

2. 基於Struts2的類型轉換器

Struts 2提供了一個StrutsTypeConverter的抽象類,這個抽象類是DefaultTypeConverter類的子類。開發時能夠直接繼承這個類來進行轉換器的構建。經過繼承該類來構建類型轉換器,能夠不用對轉換的類型進行判斷(和第一種方式的區別),下面咱們來看一下StrutsTypeConverter類的源碼:

[java]  view plain  copy
 
 print?
  1. publicabstractclass StrutsTypeConverter extends DefaultTypeConverter {  
  2.   
  3.    //重寫DefaultTypeConverter類的convertValue方法  
  4.   
  5.  public Object convertValue(Map context, Object o, Class toClass) {  
  6.   
  7.         //若是須要把複合類型轉換成字符串類型  
  8.   
  9. if (toClass.equals(String.class)) {  
  10.   
  11.             return convertToString(context, o);  
  12.   
  13.         }   
  14.   
  15.  //若是須要把字符串轉換成符合類型  
  16.   
  17. elseif (o instanceof String[]) {  
  18.   
  19.             return convertFromString(context, (String[]) o, toClass);  
  20.   
  21.         }   
  22.   
  23. //若是須要把字符串轉換成符合類型  
  24.   
  25. elseif (o instanceof String) {  
  26.   
  27.             return convertFromString(  
  28.   
  29. context, new String[]{(String) o}, toClass);  
  30.   
  31.         } else {  
  32.   
  33.             return performFallbackConversion(context, o, toClass);  
  34.   
  35.         }  
  36.   
  37.     }  
  38.   
  39. protected Object performFallbackConversion(Map context,   
  40.   
  41. Object o, Class toClass) {  
  42.   
  43.         returnsuper.convertValue(context, o, toClass);  
  44.   
  45.     }  
  46.   
  47. publicabstract Object convertFromString(Map context,   
  48.   
  49. String[] values, Class toClass);  
  50.   
  51. publicabstract String convertToString(Map context, Object o);  
  52.   
  53. }  

    該類已經實現了DefaultTypeConverter的convertValue方法。實現該方法時,它將兩個不一樣轉換方向替換成不一樣方法——當須要把字符串轉換成複合類型時,調用convertFromString抽象方法;當須要把複合類型轉換成字符串時,調用convertToString抽象方法,下圖展現了其對應關係:

 

 

 

 

二.註冊自定義類型轉換器:

實現了自定義的類型轉換器以後,將該類型轉換器註冊在Web應用中,Struts2框架才能夠正常使用該類型轉換器,類型轉換器的註冊分爲兩種

1.註冊局部類型轉換器。

局部類型轉換器僅僅對某個Action起做用。局部類型轉換器很是簡單,只須要在相應的Action目錄下新建一個資源文件。該資源文件名格式以下。ActionName-conversion.properties。其中ActionName表示須要進行轉換的Action的類名,「-conversion.properties」字符串則是固定格式的。該文件也是一個典型Properties文件,文件由鍵值對組成:propertyName = 類型轉換器類

如:name=util.NameConvert

name:表示要進行轉換的屬性

util.NameConvert:表示要進行轉換的自定義類型轉換器。

注意:該屬性文件應該與ActionName.class放在相同位置。

  

2.註冊全局類型轉換器。對全部Action的特定類型的屬性都會生效。

           全局類型轉換器,必須提供一個xwork-conversion.properties文件。文件必須保存在classes目錄下。該資源文件名格式以下:

     複合類型=對應的類型轉換器 

     複合類型:指定須要完成類型轉換的複合類

     對應的類型轉換器:指定所指定類型轉換的轉換器。

 如:註冊User類的全局類型轉換器爲:UserConverter

     cn.wjz.bean.User = cn.wjz.util.UserConverter

 

注意:若是局部類型轉換和全局類型轉換同時存在的話,局部類型轉換具備較高的優先級,也就是以局部類型轉換器爲主。

三.集合類型的類型轉換
對於List元素來講,內容如: Element_attributeName=typeName;

對於Map元素來講,

(1)若是表示key的類型,則:Key_attributeName=typeName;

(2)若是表示value的類型,則爲:Element_attributeName=typeName;

 

好比,此處沒有使用泛型,而是使用了局部類型轉換文件:

[java]  view plain  copy
 
 print?
  1. Conversion02Action.java  
  2.   
  3. public class Conversion02Action extends ActionSupport {  
  4.   
  5.      private List lists;  
  6.   
  7.      private Map maps;  
  8.   
  9.      public String execute()throws Exception{  
  10.   
  11.               System.out.println(((Person)lists.get(0)).getGender());  
  12.   
  13.               System.out.println(((Person)lists.get(0)).getSalary());  
  14.   
  15.               System.out.println(((Person)maps.get("one")).getGender());  
  16.   
  17.               System.out.println(((Person)maps.get("one")).getSalary());  
  18.   
  19.               return SUCCESS;  
  20.   
  21.      }  
  22.   
  23.      public List getLists() {  
  24.   
  25.               return lists;  
  26.   
  27.      }  
  28.   
  29.      public void setLists(List lists) {  
  30.   
  31.               this.lists = lists;  
  32.   
  33.      }  
  34.   
  35.      public Map getMaps() {  
  36.   
  37.               return maps;  
  38.  }  
  39.   
  40.      public void setMaps(Map maps) {  
  41.   
  42.               this.maps = maps;  
  43.   
  44.      }  
  45. }  


Conversion02Action-conversion.properties

 

[html]  view plain  copy
 
 print?
  1. Element_lists=org.person.Person    
  2.   
  3. Key_maps=java.lang.String    
  4.   
  5. Element_maps=org.person.Person    


 頁面表單:

[html]  view plain  copy
 
 print?
  1. <s:fielderror></s:fielderror>    
  2.   
  3.   <s:form action="conversion02" >    
  4.   
  5.        <s:textfield label="list1.salary" name="lists[0].salary"></s:textfield>    
  6.   
  7.         <s:textfield label="list1.gender" name="lists[0].gender"></s:textfield>    
  8.   
  9.         <s:textfield label="map1.gender" name="maps['one'].gender"></s:textfield>    
  10.   
  11.       <s:textfield label="map1.salary" name="maps['one'].salary"></s:textfield>    
  12.   
  13.       <s:submit value="提交"></s:submit>    
  14.   
  15.    </s:form>    


四.Struts 2內建的類型轉換器 :

   Sturts 2爲經常使用的數據類型提供了內建的類型轉換器,因此根本不用自定義轉換器。對於內建的轉換器,Struts在遇到這些類型時,會自動去調用相應的轉換器進行類型轉換。

Struts 2所有的內建轉換器:

   ·基本數據類型以及其封裝類。包括:boolean和Boolean、char和Character、int和Integer、long和Integer、float和Float、double和Double。完成字符串和基本數據類型或其封裝類之間的轉換。

   ·日期類型。使用當前區域的短格式轉換,即DateFormat.getInstance(DateFormat.SHORT)完成字符串和日期類型之間的轉換。

   ·集合(Collection)類型。將request.getParameterValues(String arg)返回的字符串數據與Java.util.Collection轉換。集合元素爲String類型。

   ·集合(Set)類型。與Collection的轉換類似,只是去掉了相同的值。集合元素爲String類型。

   ·數組類型。將request.getParameterValues(String arg)返回的字符串數組中的每一個字符串值取出組成一個數組。數組元素爲String類型。

注意:Struts 2提供的所有內建轉換器都是雙向的,也就是說從用戶輸入頁到服務器端時會將字符串類型轉換成相應的數據類型。在顯示輸出時,又會將相應的數據類型轉換成字符串類型來顯

數組類型的轉換器。這個轉換器很是有用,好比多個表單元素的name屬性相同,那麼提交的參數就再也不是字符串而是一個字符串數組。經過Sturts 2提供的數組類型的轉換器就能很方便的將多個相同name屬性的表單元素的值封裝到Action中的一個數組中。

五.類型轉換中錯誤處理:

1.類型轉換的錯誤處理流程:

Struts2提供了一個名爲conversionError的攔截器,這個攔截器被註冊在默認的攔截器棧中,在Struts-default.xml中的配置信息:

[html]  view plain  copy
 
 print?
  1. <interceptor-stack name="defaultStack">  
  2.   
  3.      .. .. ..   
  4.   
  5.      <!—- 處理類型轉換錯誤的攔截器 -->  
  6.   
  7. <interceptor-ref name="conversionError"/>  
  8.   
  9.      <!—- 處理數據校驗的攔截器 -->  
  10.   
  11. <interceptor-ref name="validation">  
  12.   
  13.           <param name="excludeMethods">input,back,cancel,browse</param>  
  14.   
  15.      </interceptor-ref>  
  16.   
  17.      <interceptor-ref name="workflow">  
  18.   
  19.           <param name="excludeMethods">input,back,cancel,browse</param>  
  20.   
  21.      </interceptor-ref>  
  22.   
  23. </interceptor-stack>  


若是Struts2的類型轉換器執行類型轉換時出現錯誤,該攔截器將負責將對應的錯誤封裝成表單域錯誤(fieldError),並將這些錯誤信息放入ActionContext中。

Struts2的錯誤處理流程:

 

 

                                        

二、錯誤信息的友好顯示

在進行類型轉換中,若是出現錯誤將會提示錯誤信息。Struts 2默認提供了錯誤信息提示,可是這些錯誤信息提示不夠友好,下面將介紹如何自定義錯誤信息來取代Struts 2的默認錯誤信息。

·定義全局類型轉換錯誤處理信息:

 在應用的國際化資源文件中增長以下的信息:

 xwork.default.invalid.fieldvalue = key

key的值就是用戶但願在頁面中顯示的提示信息。  例如:

#改變默認的類型轉換失敗後的提示信息

xwork.default.invalid.fieldvalue = {0}字段類型轉換失敗!!

由於包含非西歐字符,所以使用 native2ascii 命令處理

xwork.default.invalid.fieldvalue =

 {0}\u5b57\u6bb5\u7c7b\u578b\u8f6c\u6362\u5931\u8d25\uff01\uff01

 

·定義局部類型轉換錯誤處理信息:

 在某些時候可能還須要對特定的字段指定特別的提示信息,此時能夠提供該Action的局部資源文件,文件名:ActionName.properties , 在文件中增長以下一項:

     invalid.fieldvalue.屬性名 =提示信息

  例如:

#改變Action中birth屬性類型轉換錯誤後的提示信息

invalid.fieldvalue.birth = 生日信息必須知足yyyy-MM-DD格式

使用 native2ascii 命令處理

invalid.fieldvalue.birth =

\u751f\u65e5\u4fe1\u606f\u5fc5\u987b\u6ee1

\u8db3yyyy-MM-DD\u683c\u5f0f

 

 

六.類型轉換的流程

 一、用戶進行請求,根據請求名在struts.xml中尋找Action

 二、在Action中,根據請求域中的名字去尋找對應的set方法。找到後在賦值以前會檢查這個屬性有沒有自定義的類型轉換。沒有的話,按照默認進行轉換;若是某個屬性已經定義好了類型轉換,則會去檢查在Action同一目錄下的action文件名-conversion.properties文件。

 三、從文件中找到要轉換的屬性及其轉換類。

 四、而後進入轉換類中,在此類中判斷轉換的方向。咱們是先從用戶請求開始的,因此這時先進入從字符串到類的轉換。返回轉換後的對象。流程返回Action。

 五、將返回的對象賦值給Action中的屬性,執行Action中的execute()

 六、執行完execute()方法,根據struts.xml的配置轉向頁面

 七、在jsp中顯示內容時,根據頁面中的屬性名去調用相應的get方法,以便輸出

 八、在調用get方法以前,會檢查有沒有此屬性的自定義類型轉換。若是有,再次跳轉到轉換類當中。

 九、在轉換類中再次判斷轉換方向,進入由類到字符串的轉換,完成轉換後返回字符串。

 十、將返回的值直接帶出到要展現的頁面當中去展現。

相關文章
相關標籤/搜索