(七)struts2之自定义类型转换器

来源:互联网 发布:淘宝开个店铺多少钱 编辑:程序博客网 时间:2024/05/17 20:02

一、概述 

    在B/S应用中,将字符串请求参数转换为相应的数据类型,是MVC框架提供的功能,而Struts2是很好的MVC框架实现者,理所当然,提供了类型转换机制。 

    Struts2的类型转换是基于OGNL表达式的,只要我们把HTML输入项(表单元素和其他GET/POET的参数)命名为合法的OGNL表达式,就可以充分利用Struts2的转换机制。 

    除此之外,Struts2提供了很好的扩展性,开发者可以非常简单的开发自己的类型转换器,完成字符串和自定义复合类型之间的转换。总之,Struts2 的类型转换器提供了非常强大的表现层数据处理机制,开发者可以利用Struts2的类型转换机制来完成任意的类型转换。 


 WEB应用接收到表单提交的数据都是String类型的,Struts2可方便的转换为 常规类型(数值,日期) / 自定义类型(User,Point类).

  如果转换中出现异常,conversionError拦截器会自动处理该异常.


二、 常规类型的转换
  比如表单提交的信息有 用户名,生日, 年龄, Action中对应的数据类型分别是 String, Date, int.  没什么好说的, Struts2会自动完成.
  Struts2内建了常用的类型转换器,如String ,boolean,char,int,long,float,double,Date, 数组(假定元素是String类型), 集合(假定元素是String类型,用ArrayList封装)

三、页面中常用类型的OGNL表达式写法
     在html表单中的文本框里输入的不管是数值类型还是字符类型,最后都是以String类传到后台。如果后台bean的属性是int、double、Date等,Struts就会自动把字符类型转换成相应的类型。
    Struts2中默认提供了一些内置的转换器,包括8个基本类型,Date,array数组,List,Map类。也可以自定义转换器。通过实现ogln.TypeConverter接口实现它的方法就可以定义其他类型的转换,不过还要配置相应的资源文件。其实那几个内置的转换器已经足够使用了,很少会专门定义一个转换器。
    基本数据类型转换器没有什么特殊要求,只要输入的值符合基本数据类型,它都会自动转换,否则会出现错误提示。比如对于int类型,前天就不能输入跟数字无关的字符。再来就是日期类型,默认好像是YY-MM-DD,比如2008-8-8,如果写成8-8-2008提交后就会出现错误提示。

    对于Array数组,List,Map则需要配合OGNL表达式一起使用。比如后台有个属性是String [] name,在前台界面 
  <s:textfield name="names[0]" label="names"/>
   <s:textfield name="names[1]" label="names"/>
   <s:textfield name="names[2]" label="names"/> 

就会对这个数组赋值。List跟数组使用方式一样,但只针对不加泛型的基本数据类型的的List,如果加了泛型则是
<s:textfield name="users[0].username" label="Usernames"/>
<s:textfield name="users[1].username" label="Usernames"/>
<s:textfield name="users[2].username" label="Usernames"/>
比如User类中有个username属性,List<User> users这个属性对应上面的写法。

最后是Map的转换方式
<s:textfield name="maidenNames['beth']" label="Maiden Name"/>
<s:textfield name="maidenNames['sharon']" label="Maiden Name"/>
<s:textfield name="maidenNames['martha']" label="Maiden Name"/>

[]里的值对应到Map中的Key


四、自定义类型转换器
  实现TypeCoverter接口,或者继承DefaultTypeConverter实现类(该类实现了TypeCoverter接口),通过继承该实现类来实现自己的类型转换器。重写convertValue方法即可。 

    为了简化类型转换器的实现,Struts2提供了一个StrutsTypeConverter抽象类,这个抽象类是DefaultConverter的子类。实现了方法,并提供了2个不同转换方向的方法:Object 
convertToString(Map context,String[] values,Class toClass)和String convertFromString(Map context,Object o)。 

 具体使用步骤:
 1)注册应用 
    实现了自定义类型转换器之后,将该类型转换器注册在Web应用中,Struts2框架才可以正常使用该类型转换器。 
关于类型转换器的注册方式,主要有3中: 
A、注册局部类型转换器:仅仅对某个Action的属性起作用。 
B、注册全局类型转换器:对所有Action的特定类型的属性都会生效。 
C、使用JDK1.5的注释来注册类型转换器:通过注释方式来生成类型转换器。 

2)局部类型转换器 
    提供如下格式的文件 
文件名:  ActionName-conversion.properties  
内容:多个propertyName(属性名)=类型转换器类(含包名),如  date=com.aumy.DateConverter 
存放位置:和ActionName类相同路径。 

3)全局类型转换器 
    提供如下格式的文件 
文件名:  xwork-conversion.properties 
内容:   多个“复合类型=对应类型转换器”项组成,如  java.Util.Date=com.aumy.DateConverter 
存放位置:WEB-INF/classes/目录下。 


应用示例

先看几个实体类
 User.java
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">package com.javacrazyer.domain;  
  2.   
  3. import java.util.Date;  
  4.   
  5.   
  6. public class User {  
  7.     private Integer id;  
  8.     private String loginname;  
  9.     private Double score;  
  10.     private Character cha;  
  11.     private Date birthday;  
  12.     private Gender gender;  
  13.       
  14.     public User(){}  
  15.       
  16.     public User(Integer id, String loginname, Double score, Gender gender,  
  17.             Character cha, Date birthday) {  
  18.         this.id = id;  
  19.         this.loginname = loginname;  
  20.         this.score = score;  
  21.         this.gender = gender;  
  22.         this.cha = cha;  
  23.         this.birthday = birthday;  
  24.     }  
  25.     public Integer getId() {  
  26.         return id;  
  27.     }  
  28.     public void setId(Integer id) {  
  29.         this.id = id;  
  30.     }  
  31.     public String getLoginname() {  
  32.         return loginname;  
  33.     }  
  34.     public void setLoginname(String loginname) {  
  35.         this.loginname = loginname;  
  36.     }  
  37.     public Double getScore() {  
  38.         return score;  
  39.     }  
  40.     public void setScore(Double score) {  
  41.         this.score = score;  
  42.     }  
  43.     public Gender getGender() {  
  44.         return gender;  
  45.     }  
  46.     public void setGender(Gender gender) {  
  47.         this.gender = gender;  
  48.     }  
  49.     public Character getCha() {  
  50.         return cha;  
  51.     }  
  52.     public void setCha(Character cha) {  
  53.         this.cha = cha;  
  54.     }  
  55.     public Date getBirthday() {  
  56.         return birthday;  
  57.     }  
  58.     public void setBirthday(Date birthday) {  
  59.         this.birthday = birthday;  
  60.     }  
  61.   
  62.     public String toString() {  
  63.         return "User [birthday=" + birthday + ", cha=" + cha + ", gender="  
  64.                 + gender + ", id=" + id + ", loginname=" + loginname  
  65.                 + ", score=" + score+ "]";  
  66.     }  
  67. }</span></span>  
 Gender.java
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">package com.javacrazyer.domain;  
  2.   
  3. public enum Gender {  
  4.     M,F;  
  5. }</span></span>  
 Tel.java
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">package com.javacrazyer.domain;  
  2.   
  3.   
  4. public class Tel {  
  5.     private String areaCode;  
  6.     private String phoneCode;  
  7.   
  8.     public String getAreaCode() {  
  9.         return areaCode;  
  10.     }  
  11.   
  12.     public void setAreaCode(String areaCode) {  
  13.         this.areaCode = areaCode;  
  14.     }  
  15.   
  16.     public String getPhoneCode() {  
  17.         return phoneCode;  
  18.     }  
  19.   
  20.     public void setPhoneCode(String phoneCode) {  
  21.         this.phoneCode = phoneCode;  
  22.     }  
  23.   
  24. }</span></span>  
 
看看自定义Tel类型的转换器
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">package com.javacrazyer.converter;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import org.apache.struts2.util.StrutsTypeConverter;  
  6.   
  7. import com.javacrazyer.domain.Tel;  
  8.   
  9. public class TelConverter extends StrutsTypeConverter {  
  10.   
  11.     //把String转换成Tel类型  
  12.     //context:OGNL上下文的Map对象  
  13.     //values :需要转换的字符串数组  
  14.     //toClass:要转换的目标类型  
  15.   
  16.     @Override  
  17.     public Object convertFromString(Map context, String[] values, Class toClass) {  
  18.           
  19.         if(toClass == Tel.class){  
  20.             String str = values[0];  
  21.               
  22.             String[] strArr = str.split("-");  
  23.               
  24.             Tel tel = new Tel();  
  25.             tel.setAreaCode(strArr[0]);  
  26.             tel.setPhoneCode(strArr[1]);  
  27.             return tel;  
  28.         }  
  29.           
  30.         return null;  
  31.     }  
  32.   
  33.     //把Tel类型转换成String类型  
  34.     //context:OGNL上下文的Map对象  
  35.     //o:需要转换的对象  
  36.     @Override  
  37.     public String convertToString(Map context, Object o) {  
  38.         if(o instanceof Tel){  
  39.             Tel tel = (Tel)o;  
  40.             return tel.getAreaCode() + "-" + tel.getPhoneCode();  
  41.         }  
  42.         return null;  
  43.     }  
  44. }</span></span>  
 
业务处理UserAction.java
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">package com.javacrazyer.web.action;  
  2.   
  3.   
  4. import java.util.HashMap;  
  5. import java.util.HashSet;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import java.util.Set;  
  9. import java.util.Map.Entry;  
  10.   
  11. import com.javacrazyer.domain.Tel;  
  12. import com.javacrazyer.domain.User;  
  13. import com.opensymphony.xwork2.ActionSupport;  
  14.   
  15. /** 
  16.  * 使用注解来配置Action 
  17.  *  
  18.  */  
  19. public class UserAction extends ActionSupport {  
  20.     private static final long serialVersionUID = -2554018432709689579L;  
  21.     private User user;  
  22.     private List<String> list;  
  23.     private List<User> userList;  
  24.     private Set<User> userSet = new HashSet<User>();  
  25.       
  26.     private Map<String, String> map = new HashMap<String, String>();  
  27.       
  28.     private Tel tel;  
  29.       
  30.     public String execute() throws Exception{  
  31.         System.out.println(user);  
  32.           
  33.         System.out.println(list);  
  34.           
  35.           
  36.         for(User user : userList){  
  37.             System.out.println(user);  
  38.         }  
  39.           
  40.         System.out.println("=========================");  
  41.         for(User user : userSet){  
  42.             System.out.println(user);  
  43.         }  
  44.           
  45.           
  46.         for (Entry entry:map.entrySet()){  
  47.             System.out.println(entry.getKey()+"=="+entry.getValue());  
  48.         }  
  49.         System.out.println("区号:" + this.tel.getAreaCode());  
  50.         System.out.println("电话号:" + this.tel.getPhoneCode());  
  51.           
  52.         return SUCCESS;  
  53.     }  
  54.   
  55.     public User getUser() {  
  56.         return user;  
  57.     }  
  58.   
  59.   
  60.     public void setUser(User user) {  
  61.         this.user = user;  
  62.     }  
  63.   
  64.   
  65.     public List<String> getList() {  
  66.         return list;  
  67.     }  
  68.   
  69.   
  70.     public void setList(List<String> list) {  
  71.         this.list = list;  
  72.     }  
  73.   
  74.   
  75.     public List<User> getUserList() {  
  76.         return userList;  
  77.     }  
  78.   
  79.   
  80.     public void setUserList(List<User> userList) {  
  81.         this.userList = userList;  
  82.     }  
  83.   
  84.     public Set<User> getUserSet() {  
  85.         return userSet;  
  86.     }  
  87.   
  88.     public void setUserSet(Set<User> userSet) {  
  89.         this.userSet = userSet;  
  90.     }  
  91.   
  92.     public Map<String, String> getMap() {  
  93.         return map;  
  94.     }  
  95.   
  96.     public void setMap(Map<String, String> map) {  
  97.         this.map = map;  
  98.     }  
  99.   
  100.     public Tel getTel() {  
  101.         return tel;  
  102.     }  
  103.   
  104.     public void setTel(Tel tel) {  
  105.         this.tel = tel;  
  106.     }  
  107.       
  108.       
  109. }</span></span>  
 局部类型转换器,与UserAction.java在同一目录
UserAction-conversion.properties
Xml代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">tel=com.javacrazyer.converter.TelConverter  
  2.   
  3. #集合属性-Set类型     
  4. Element_userSet=com.javacrazyer.domain.User  
  5. #指定索引  
  6. KeyProperty_userSet=id  
  7.   
  8. #指定key类型  
  9. Key_map=java.lang.String  
  10. #指定value类型  
  11. Element_map=java.lang.String</span></span>  
 全局类型转换器src/xwork-conversion.properties
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;">com.qiujy.domain.Tel=com.javacrazyer.converter.TelConverter</span></span>  
 src/struts.xml
Java代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;"><?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.1.7.dtd">  
  5.   
  6. <struts>  
  7.     <!-- 请求参数的编码方式 -->  
  8.     <constant name="struts.i18n.encoding" value="UTF-8"/>  
  9.     <!-- 指定被struts2处理的请求后缀类型。多个用逗号隔开 -->  
  10.     <constant name="struts.action.extension" value="action,do,go,xkk"/>  
  11.     <!-- 当struts.xml改动后,是否重新加载。默认值为false(生产环境下使用),开发阶段最好打开  -->  
  12.     <constant name="struts.configuration.xml.reload" value="true"/>  
  13.     <!-- 是否使用struts的开发模式。开发模式会有更多的调试信息。默认值为false(生产环境下使用),开发阶段最好打开  -->  
  14.     <constant name="struts.devMode" value="false"/>  
  15.     <!-- 设置浏览器是否缓存静态内容。默认值为true(生产环境下使用),开发阶段最好关闭  -->  
  16.     <constant name="struts.serve.static.browserCache" value="false" />  
  17.     <!-- 是否允许在OGNL表达式中调用静态方法,默认值为false -->  
  18.     <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>  
  19.       
  20.     <!-- 指定由spring负责action对象的创建   
  21.     <constant name="struts.objectFactory" value="spring" />  
  22.     -->  
  23.     <!-- 是否开启动态方法调用 -->  
  24.     <constant name="struts.enable.DynamicMethodInvocation" value="false"/>  
  25.       
  26.     <package name="my" extends="struts-default" namespace="/">  
  27.         <global-results>  
  28.             <result name="input">/error.jsp</result>  
  29.         </global-results>  
  30.       
  31.         <action name="info" class="com.javacrazyer.web.action.UserAction">  
  32.             <result name="success">/info.jsp</result>  
  33.             <result name="input">/error.jsp</result>  
  34.         </action>  
  35.     </package>  
  36.       
  37. </struts></span></span>  
 converter.jsp
Html代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;"><%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
  2. <%@ taglib uri="/struts-tags" prefix="s" %>  
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  4. <html>  
  5.   <head>  
  6.     <title>Struts2中的转换器</title>  
  7.   </head>  
  8.   <body>  
  9. <h3>Struts2中的转换器</h3><hr/>  
  10. <form action="info.action" method="post">  
  11.     <table>  
  12.       
  13.         <tr>  
  14.             <td>登录名</td>  
  15.             <td><input type="text" name="user.loginname"/></td>  
  16.         </tr>  
  17.         <tr>  
  18.             <td>生日</td>  
  19.             <td><input type="text" name="user.birthday"/></td>  
  20.         </tr>  
  21.         <tr>  
  22.             <td>性别</td>  
  23.              <!--OGNL表达式:user属性的gender属性[由于是日期类型,程序中自定义有日期转换器]写法   -->  
  24.             <td><input type="radio" name="user.gender" value="M" checked="checked"/><input type="radio" name="user.gender" value="F"/></td>  
  25.         </tr>  
  26.         <tr>  
  27.             <td>考试成绩</td>  
  28.             <td><input type="text" name="user.score"/></td>  
  29.         </tr>  
  30.         <tr>  
  31.             <td colspan="2"><input type="submit" value=" 提交 "/></td>  
  32.         </tr>  
  33.     </table>  
  34.       
  35.     <!--OGNL表达式:元素类型为String类型的List的写法   -->  
  36.     <input type="hidden" name="list[0]" value="张三"/>  
  37.     <input type="hidden" name="list[1]" value="李四"/>  
  38.     <input type="hidden" name="list[2]" value="王五"/>  
  39.       
  40.     <!--OGNL表达式:元素类型为user类型的LIST属性的写法   -->  
  41.     <input type="hidden" name="userList[0].loginname" value="张三"/>  
  42.     <input type="hidden" name="userList[1].loginname" value="李"/>  
  43.     <input type="hidden" name="userList[2].loginname" value="王"/>  
  44.       
  45.     <!--OGNL表达式:元素类型为user类型的set属性的写法 -->  
  46.     <input type="hidden" name="userSet.makeNew[0].loginname" value="xxx"/>  
  47.     <input type="hidden" name="userSet.makeNew[1].loginname" value="yyy"/>  
  48.     <input type="hidden" name="userSet.makeNew[2].loginname" value="ggg"/>  
  49.        
  50.      <!--OGNL表达式:map属性的写法   -->  
  51.      <input type="hidden" name="map['jolin']" value="caiyilin"/>  
  52.      <input type="hidden" name="map['jay']" value="zhoujielun"/>  
  53.         
  54.        <!--OGNL表达式:Tel属性的写法   -->  
  55.      <input type="hidden" name="tel" value="010-66298878"/>  
  56. </form>  
  57.   </body>  
  58. </html></span></span>  
 info.jsp
Html代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;"><%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
  2. <%@ taglib uri="/struts-tags" prefix="s" %>  
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  4. <html>  
  5.   <head>  
  6.     <title>显示提交的数据</title>  
  7.   </head>  
  8.   <body>  
  9. <h3>显示提交的数据</h3><hr/>  
  10.     <table>  
  11.         <tr>  
  12.             <td>登录名</td>  
  13.             <td><s:property value="user.loginname"/> </td>  
  14.         </tr>  
  15.         <tr>  
  16.             <td>生日</td>  
  17.             <td><s:date name="user.birthday" format="yyyy-MM-dd HH:mm:ss"/></td>  
  18.         </tr>  
  19.         <tr>  
  20.             <td>性别</td>  
  21.             <td><s:property value="user.gender"/> </td>  
  22.         </tr>  
  23.         <tr>  
  24.             <td>考试成绩</td>  
  25.             <td><s:property value="user.score"/></td>  
  26.         </tr>  
  27.         <tr>  
  28.             <td>电话号</td>  
  29.             <td><s:property value="tel"/></td>  
  30.         </tr>  
  31.         <tr>  
  32.             <td colspan="2"><input type="button" value=" 返回 " onclick="history.go(-1);" /></td>  
  33.         </tr>  
  34.     </table>  
  35.   
  36. <hr/><s:debug/>  
  37.   </body>  
  38. </html></span></span>  
 error.jsp
Html代码  收藏代码
  1. <span style="font-size: large;"><span style="font-size: large;"><%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
  2. <%@ taglib uri="/struts-tags" prefix="s" %>  
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  4. <html>  
  5.   <head>  
  6.     <title>出现内部错误</title>  
  7.   </head>  
  8.   <body>  
  9. <h3>出现内部错误</h3><hr/>  
  10.   
  11. <s:actionerror/>  
  12.   </body>  
  13. </html></span></span>  
 
总结
Struts2中的类型转换器
  1) Struts2中内置了一些常用的类型转换器:可以把客户端提交的String数据转换成对应类型的数据。
     a) 基本类型
     b) java.util.Date:
     c) 数组和列表
  2) 自定义类型转换器: 
     a) 继承自org.apache.struts2.util.StrutsTypeConverter类
  public abstract Object convertFromString(Map context, String[] values, Class toClass);
        context:OGNL上下文的Map对象
        values :需要转换的字符串数组
        toClass:要转换的目标类型
  public abstract String convertToString(Map context, Object o);
         context:OGNL上下文的Map对象
         o:需要转换的对象
     b) 注册:以全局方式
                    在应用程序的classpath下创建一属性文件,名为:xwork-conversion.properties
                    文件内容:待转换类型的全限定名=类型转换器类的全限定名
  3) 转换Set:
     0) Action中的Set属性需要进行初始化:如:
        private Set<User> userSet = new HashSet<User>();
     a) 添加针对某个Action的转换器配置文件:ActionName-conversion.properties 如:
        UserAction-conversion.properties
        
     b) 在这个文件中添加:Action的Set属性的相关配置
        Element_属性名=Set中的元素类型的全限定名                 #指定Set中的元素类型
        KeyProperty_属性名=Set中的元素类型中的某个属性  #指定Set的索引字段
                   如下示例:
        Element_userSet=com.qiujy.domain.User
        KeyProperty_userSet=id
        
     c) JSP页面: <input type="text" name="Set属性名.makeNew[0].属性名"/>
                    如:<input type="text" name="userSet.makeNew[0].loginname"/>
原创粉丝点击