首页 > 代码库 > struts2 数据转换器

struts2 数据转换器

四、数据类型的转换(明白原理,实际开发中几乎不用)

      1、开发中的情况:

              实际开发中用户通过浏览器输入的数据都是String或者String[]。

              String/String[]————填充模型(set方法)————>POJO(plain old java object)  pojo中有java的数据类型。

              POJO————————获取(get方法)————>页面展示:String

      2、类型转换情况

               写数据:(增,删,改)都是String或String[]数组转换为其他类型。

              读数据:(查)其他类型转换为String。

      3、Struts2提供的常用类型转换

              a.基本数据类型自动转换。

              b.日期类型:默认按照本地日期格式转换(yyyy-MM-dd)。

              c.字符串数组:默认用逗号+空格,连接成一个字符串。

      4、自定义类型转换器(知道)

                   示例:把日期格式按照 MM/dd/yyyy的格式转换

           4.1、Struts2中的类型转换器结构:

        

技术分享
 1 /**
 2  * Interface for accessing the type conversion facilities within a context.
 3  * 
 4  * This interface was copied from OGNL‘s TypeConverter
 5  * 
 6  * @author Luke Blanshard (blanshlu@netscape.net)
 7  * @author Drew Davidson (drew@ognl.org)
 8  */
 9 public interface TypeConverter
10 {
11     /**
12        * Converts the given value to a given type.  The OGNL context, target, member and
13        * name of property being set are given.  This method should be able to handle
14        * conversion in general without any context, target, member or property name specified.
15        * @param context context under which the conversion is being done
16        * @param target target object in which the property is being set
17        * @param member member (Constructor, Method or Field) being set
18        * @param propertyName property name being set
19        * @param value value to be converted
20        * @param toType type to which value is converted
21        * @return Converted value of type toType or TypeConverter.NoConversionPossible to indicate that the
22                  conversion was not possible.
23      */
24     public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType);
25     
26     public static final Object NO_CONVERSION_POSSIBLE = "ognl.NoConversionPossible";
27     
28     public static final String TYPE_CONVERTER_CONTEXT_KEY = "_typeConverter";
29 }
TypeConverter(类型转换父接口)
技术分享
 1 /**
 2  * Default type conversion. Converts among numeric types and also strings.  Contains the basic 
 3  * type mapping code from OGNL.
 4  * 
 5  * @author Luke Blanshard (blanshlu@netscape.net)
 6  * @author Drew Davidson (drew@ognl.org)
 7  */
 8 public class DefaultTypeConverter implements TypeConverter {
 9 
10     protected static String MILLISECOND_FORMAT = ".SSS";
11 
12     private static final String NULL_STRING = "null";
13 
14     private final Map<Class, Object> primitiveDefaults;
15 
16     public DefaultTypeConverter() {
17         Map<Class, Object> map = new HashMap<Class, Object>();
18         map.put(Boolean.TYPE, Boolean.FALSE);
19         map.put(Byte.TYPE, Byte.valueOf((byte) 0));
20         map.put(Short.TYPE, Short.valueOf((short) 0));
21         map.put(Character.TYPE, new Character((char) 0));
22         map.put(Integer.TYPE, Integer.valueOf(0));
23         map.put(Long.TYPE, Long.valueOf(0L));
24         map.put(Float.TYPE, new Float(0.0f));
25         map.put(Double.TYPE, new Double(0.0));
26         map.put(BigInteger.class, new BigInteger("0"));
27         map.put(BigDecimal.class, new BigDecimal(0.0));
28         primitiveDefaults = Collections.unmodifiableMap(map);
29     }
30 
31     public Object convertValue(Map<String, Object> context, Object value, Class toType) {
32         return convertValue(value, toType);
33     }
34 
35     public Object convertValue(Map<String, Object> context, Object target, Member member,
36             String propertyName, Object value, Class toType) {
37         return convertValue(context, value, toType);
38     }
39     
DefaultTypeConverter部分(Abstract)
技术分享
 1 public abstract class StrutsTypeConverter extends DefaultTypeConverter {
 2     public Object convertValue(Map context, Object o, Class toClass) {
 3         if (toClass.equals(String.class)) {
 4             return convertToString(context, o);
 5         } else if (o instanceof String[]) {
 6             return convertFromString(context, (String[]) o, toClass);
 7         } else if (o instanceof String) {
 8             return convertFromString(context, new String[]{(String) o}, toClass);
 9         } else {
10             return performFallbackConversion(context, o, toClass);
11         }
12     }
13 
14     /**
15      * Hook to perform a fallback conversion if every default options failed. By default
16      * this will ask Ognl‘s DefaultTypeConverter (of which this class extends) to
17      * perform the conversion.
18      *
19      * @param context
20      * @param o
21      * @param toClass
22      * @return The fallback conversion
23      */
24     protected Object performFallbackConversion(Map context, Object o, Class toClass) {
25         return super.convertValue(context, o, toClass);
26     }
27 
28 
29     /**
30      * Converts one or more String values to the specified class.
31      *
32      * @param context the action context
33      * @param values  the String values to be converted, such as those submitted from an HTML form
34      * @param toClass the class to convert to
35      * @return the converted object
36      */
37     public abstract Object convertFromString(Map context, String[] values, Class toClass);
38 
39     /**
40      * Converts the specified object to a String.
41      *
42      * @param context the action context
43      * @param o       the object to be converted
44      * @return the converted String
45      */
46     public abstract String convertToString(Map context, Object o);
47 }
Struts2TypeConverter(abstract)

DefaultTypeConverter 实现接口 TypeConverTer ;

Struts2TypeConverter 继承了DefaultTypeConverter 

             其它转换器都几乎继承自 Struts2TypeConverter 

      

           4.2、编写类型转换器(编写一个类继承StrutsTypeConverter,实现抽象方法)

             

技术分享
 1 /**
 2  * 需求:
 3  *       把表单中的MM/dd/yyyy格式的数据转成日期类型
 4  *   把数据库中的本地日期格式,转成MM/dd/yyyy形式输出
 5  * 
 6  * 自定义子类转换器:
 7  *     第一步:编写一个类,继承自StrutsTypeConverter,实现convertFromString,convertToString抽象方法
 8  * @author zhy
 9  *
10  */
11 public class MyTypeConvertor extends StrutsTypeConverter {
12     
13     //定义一个类型转换器
14     private DateFormat format = new SimpleDateFormat("MM/dd/yyyy");
15     
16     /**
17      * 把字符串数组中的数据转成日期类型
18      * 
19      * 方法参数详解:
20      *     Map context:是OGNL的上下文对象,我们暂时不知道,所以暂时也不用
21      *  String[] values:要转换的数据
22      *  Class toClass:目标类型
23      */
24     public Object convertFromString(Map context, String[] values, Class toClass) {
25         //1.先看看有没有数据
26         if(values == null || values.length == 0){
27             return null;
28         }
29         //2.取出数组中的第一个元素
30         String date = values[0];
31         //3.判断目标类型的字节码是不是日期类型
32         if(toClass == java.util.Date.class){
33             try {
34                 //4.使用DateFormat进行转换,并且返回转换后的结果
35                 return format.parse(date);
36             } catch (ParseException e) {
37                 e.printStackTrace();
38                 return null;
39             }
40         }
41         return null;
42     }
43     
44     /**
45      * 把日期类型的数据转换成字符串
46      * 
47      * 方法参数详解:
48      *     Map context:是OGNL的上下文对象,我们暂时不知道,所以暂时也不用
49      *  Object o:要转换的数据
50      */
51     public String convertToString(Map context, Object o) {
52         //1.判断object是不是日期类型
53         if(o instanceof Date){
54             Date date = (Date)o;
55             //2.是日期类型,使用转换器转成指定格式的字符串,并返回
56             return format.format(date);
57         }
58         return null;
59     }
60 
61 }
MyTypeConverter(自己的转换器)

 

           4.3、注册类型转换器

                             局部类型转换器:只能指定javabean中的属性用

                                          按照属性来注册。在属性所属的javabean的包下建立一个.properties文件。文件名称:javabean名称-conversion.properties

技术分享
1 #局部类型转换器文件名的命名规范:javabean的名称-conversion.properties
2 #局部类型转换器声明,声明方式是以使用的属性名称作为key,以类型转换器的全类名作为value
3 birthday=com.itheima.web.converter.MyTypeConvertor
javabean的名称-conversion.properties

                            全局类型转换器:(推荐)

                                          按照要转换的数据类型来注册。

                                          at the top op classpath,建立一个固定名称xwork-conversion.properties的属性文件。

技术分享
1 #全局类型转换器文件名的命名规范:xwork-conversion.properties。文件放到类路径的根路径
2 #全局类型转换器声明,声明方式是以使用的数据类型(全类名)作为key,以类型转换器的全类名作为value
3 java.util.Date=com.itheima.web.converter.MyTypeConvertor
xwork-conversion.properties         

      5、转换失败后的处理(需要掌握)

              当转换失败后,页面提示:

              一串英文的错误提示

              解决办法:配置回显结果视图  

技术分享
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE struts PUBLIC
 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 4     "http://struts.apache.org/dtds/struts-2.3.dtd">
 5 <struts>
 6     <constant name="struts.devMode" value="http://www.mamicode.com/true"/>
 7     <package name="p1" extends="struts-default">
 8         <action name="register" class="com.itheima.web.action.UserAction" method="register" >
 9             <result type="redirect">/success.jsp</result><!-- 当注册成功之后重定向的结果视图 -->
10             <result name="exists">/message.jsp</result><!-- 当用户名已经存在之后,转向的结果视图 -->
11             <!-- 当出现问题之后,需要从哪来回哪去 -->
12             <result name="input">/register1.jsp</result>
13         </action>
14     </package>
15 </struts>
struts2.xml

              问题:

                     配置了回显视图后,当转换失败时,可以回到请求页面,但是表单数据都没了?

                      

                     显示错误提示:借助Struts2的标签库。

                     回显数据:使用struts2的标签库生成表单。(建议使用)

技术分享
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%--导入struts2的标签库 --%>
 3 <%@ taglib uri="/struts-tags" prefix="s" %>
 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 5 <html>
 6   <head>
 7     <title>用户注册,使用的是struts2的标签</title>
 8     <s:head></s:head>
 9   </head>
10   <body>
11       <s:actionerror/><%-- 动作错误 --%>
12       <s:fielderror /><%-- 字段错误 --%>
13       <%--struts2的form标签,它提供了和原始html表单标签几乎一致的属性
14           action:请求的地址。直接写动作名称。不用写contextPaht
15           method:请求的方式。在这里不用写。struts2的form表单默认就是post
16           enctype:表单编码的MIME类型
17       --%>
18       <s:form action="register.action">
19           <s:textfield name="username" label="用户名" requiredLabel="true" requiredPosition="left"/>
20           <s:password name="password" label="密码" showPassword="true"/>
21           <s:textfield name="birthday" label="生日"/>
22           <s:submit value="注册"/>
23       </s:form>
24   </body>
25 </html>
jsp代码

    

              错误信息中文提示:使用的是struts2的国际化。

             (在国际化中进行详解)

                    

                     问题:

                            类型转换器当转换失败后,如何进入input视图的?

                     原因:

                            是由一个叫做conversionError的拦截器完成的。

                     注意:

                            要想使用类型转换中的错误处理,在定义Action时必须继承ActionSupport

struts2 数据转换器