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方法以前,会检查有没有此属性的自定义类型转换。若是有,再次跳转到转换类当中。

 九、在转换类中再次判断转换方向,进入由类到字符串的转换,完成转换后返回字符串。

 十、将返回的值直接带出到要展现的页面当中去展现。

相关文章
相关标签/搜索