使用DefaultTypeConverter

---------------------------

web页面往后台传值,只能传递字符串,要使得字符串能自动的转换成一个类,以便于后台能更好的处理数据,就需要使用到struts中的类型转换器了。

比如,页面上传递一个值"zhangsan,20",表示张三,20岁,action中可以直接获得直接获得这样一个user对象。即在action中能使用如下的代码:

 
  
  1. public class testconvert extends ActionSupport 
  2. private User user333; 
  3. @Override 
  4. public String execute() throws Exception 
  5. System.out.println("username: " + user333.getUsername()); 
  6. System.out.println("age: " + user333.getAge()); 
  7. return SUCCESS; 

定义了user类型,并且在execute方法中可以直接使用user这个对象。

要实现这个功能,就需要把传过来的string转变成user对象。

转换的方式需要一个转换类,并且这个转换类必须继承DefaultTypeConverter类,然后,实现它的convertValue方法。

实现了转换类之后,还需要一个配置文件,来指示说明该转换类用于转换哪个变量的,(java真的很繁琐)。

首先要覆盖掉DefaultTypeConverter类中的convertValue方法,该方法有3个重载,通常覆盖签名如下的方法:

public Object convertValue(Map context, Object value, Class toType)

其中Map context没有什么用。

常规写法如下:

 
  
  1. public class UserConverter extends DefaultTypeConverter { 
  2.     @Override 
  3.     public Object convertValue(Map context, Object value, Class toType) { 
  4.          
  5.         System.out.println("convertValue"); 
  6.         if(myUser.class == toType)  //从页面向后台对象转换 
  7.         { 
  8.             //value是一个数组,因为它是根据表单中可能有多个元素的name属性是相同的,因此只要name属性为指定的表单元素的值都会被传输过来。 
  9.             String[] str = (String[])value; 
  10.              
  11.             //通常只会取第一个。 
  12.             String firstValue = str[0]; 
  13.              
  14.             System.out.println(firstValue); 
  15.              
  16.             StringTokenizer st = new StringTokenizer(firstValue, ","); 
  17.              
  18.             String username = st.nextToken(); 
  19.             int age =Integer.parseInt( st.nextToken()); 
  20.              
  21.             myUser user = new myUser(); 
  22.              
  23.             user.setUsername(username); 
  24.             user.setAge(age); 
  25.              
  26.             return user;         
  27.         } 
  28.         else if(String.class == toType) //从后台对象向页面转换 
  29.         { 
  30.             myUser user = (myUser)value; 
  31.              
  32.             String username = user.getUsername(); 
  33.             int age = user.getAge(); 
  34.              
  35.             String userInfo = "username: " + username + ", age: " + age; 
  36.              
  37.             return userInfo; 
  38.         } 
  39.         return null
  40.     } 
  41.  

然后在action类中,把要转换的对象,完成他们的set和get方法,注意大小写,set,get后的字母要大写,这是基于约定的。OGNL转换会去找这2个方法调用的。

 
  
  1. public class testconvert extends ActionSupport 
  2.     private myUser user333; 
  3.  
  4.     public myUser getUser333() { 
  5.         System.out.println("getuser333"); 
  6.         return user333; 
  7.     } 
  8.  
  9.     public void setUser333(myUser user) { 
  10.         System.out.println("setuser333"); 
  11.         this.user333 = user; 
  12.     } 
  13.  
  14.     @Override 
  15.     public String execute() throws Exception 
  16.     { 
  17.         System.out.println("username: " + user333.getUsername()); 
  18.         System.out.println("age: " + user333.getAge()); 
  19.  
  20.         System.out.println("execute"); 
  21.         return SUCCESS; 
  22.     } 

接下来属性文件的命名,必须是按照固定格式的,action类名-conversion.properties,此例中命名为testconvert-conversion.properties,和action类在同一级目录下。如果要寻找某一个action中的某属性对应的转换类,必须按照这种文件名格式寻找对应的文件。属性文件中如下编码格式为:

属性名=转换类,此例中为:

user333=com.tutorialspoint.sconvert.UserConverter,表示user333这个值用com.tutorialspoint.sconvert.UserConverter这个类做转换。

注意,此处的键名user333,是根据setUser333,getUser333而命名的,并不是根据private myUser  user333,因此,即使把private的user333改成变量user444,只要set和get的名字不改,properties文件中依旧是用user333作为键名。

在jsp提交页面中,编码如下:

 
  
  1. <form action=testconvert method="post"> 
  2.       Please enter your name<br/> 
  3.       <input type="text" name="user333"/> 
  4.       <input type="submit" value="test"/> 
  5.    </form> 

此处的变量名都要对应相同,不然会出错。

对于从Javabean中把值传到前台的HTML,上面的编码已经展示了,唯一要做的是在展示页面把该值读出来。

通过语句<s:property value="user333"/>即可,该语句会调用getUser333这个方法,进而调用 UserConverter 中的convertValue方法,完成转换。

使用StrutsTypeConverter

--------------------------------

由于继承DefaultTypeConverter需要做类型判断等操作,比较麻烦,strut2提供了StrutsTypeConverter,该类一个抽象类,是对DefaultTypeConverter的继承。该类是把之前convertValue方法中的if判断逻辑,封装成2个不同的方法。分别是convertFromString(Map context, String[] values, Class toClass) 和 convertToString(Map context, Object o)

这样的话,逻辑上更为清晰。如可以参照之前的UserConverter类,实现UserConverter2类。完成一样的工作。

 
  
  1. public class UserConverter2 extends StrutsTypeConverter { 
  2.  
  3.     @Override 
  4.     public Object convertFromString(Map arg0, String[] arg1, Class arg2) { 
  5.             System.out.println("convertFromString"); 
  6.              
  7.             //通常只会取第一个。 
  8.             String firstValue = arg1[0]; 
  9.              
  10.             System.out.println(firstValue); 
  11.              
  12.             StringTokenizer st = new StringTokenizer(firstValue, ","); 
  13.              
  14.             String username = st.nextToken(); 
  15.             int age =Integer.parseInt( st.nextToken()); 
  16.              
  17.             myUser user = new myUser(); 
  18.              
  19.             user.setUsername(username); 
  20.             user.setAge(age); 
  21.              
  22.             return user;         
  23.          
  24.     } 
  25.  
  26.     @Override 
  27.     public String convertToString(Map arg0, Object arg1) { 
  28.          
  29.         System.out.println("convertToString"); 
  30.          
  31.         myUser user = (myUser)arg1; 
  32.          
  33.         String username = user.getUsername(); 
  34.         int age = user.getAge(); 
  35.          
  36.         String userInfo = "username: " + username + ", age: " + age; 
  37.          
  38.         return userInfo; 
  39.     } 
  40.  

当然,运行前要记得在properties文件中,将

user333=com.tutorialspoint.sconvert.UserConverter改成

user333=com.tutorialspoint.sconvert.UserConverter2

全局转换器

----------------------------------

对于某些类型,需要在全局实现转换,则对单个action配置properties文件比较繁琐,struts提供了全局转换配置文件,只需在src目录下新建xwork-conversion.properties文件即可,在文件中依旧是键值对,

但是键名有变化,为具体的类型=对应类型转换器。此例中,内容即写为:

com.tutorialspoint.struts2.myUser=com.tutorialspoint.sconvert.UserConverter2,而实现转换逻辑的类依旧不变。