zoukankan      html  css  js  c++  java
  • Struts2类型转换(二)-自定义类型转换器

    一、自定义类型转换器

    1). 为什么需要自定义的类型转换器 ?

    因为Struts不能自动完成字符串到引用类型的转换。

    2). 如何定义类型转换器?

    I. 开发类型转换器的类: 扩展 StrutsTypeConverter 类;

    II. 配置类型转换器。

    有两种配置方式
    ①. 基于字段的配置
    > 在字段所在的 Model(可能是 Action,也可能是一个JavaBean) 的包下, 新建一个 ModelClassName-conversion.properties 文件
    > 在该文件中输入键值对: fieldName=类型转换器的全类名。(fieldName即带转换字段的名称)

    > 两个相关结论:

      ·第一次使用该转换器时创建实例.

        ·类型转换器是单实例的! 


    ②. 基于类型的配置:
    > 在 src 下新建 xwork-conversion.properties文件

    > 键入: 待转换的类型=类型转换器的全类名.

    > 两个相关结论:

      ·在当前 Struts2 应用被加载时创建实例.

      · 在这种情况下类型转换器被创建了两次,即不是单实例的(了解 )

    二、示例

    1)基于字段的配置方式

    修改“Struts2类型转换(一)”的JSP代码如下:(JSP页面的名称为index.jsp)

     1 <s:form action="testConversion" theme="simple">
     2     Age: <s:textfield name="age" label="Age"></s:textfield>
     3     ${fieldErrors.age[0]}
     4     <s:fielderror fieldName="age"></s:fielderror>
     5     <br><br>
     6         
     7     Birth: <s:textfield name="birth"></s:textfield>
     8     <s:fielderror fieldName="birth"></s:fielderror>
     9     <br><br>
    10     <s:submit></s:submit>
    11 </s:form>

    当Model为一个Action时,Java代码如下:

    package com.atguigu.struts2.app;
    
    import java.util.Date;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class ConversionAction extends ActionSupport{
    
        private int age;
        private Date birth;
        
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
        
        public Date getBirth() {
            return birth;
        }
    
        public void setBirth(Date birth) {
            this.birth = birth;
        }
    
        public String execute(){
            System.out.println("age: " + age);
            System.out.println("birth: " + birth);
            return "success";
        }
        
    }

    定义String与Date之间的类型转换器如下:

     1 package com.atguigu.struts2.app.converters;
     2 
     3 import java.text.DateFormat;
     4 import java.text.ParseException;
     5 import java.text.SimpleDateFormat;
     6 import java.util.Date;
     7 import java.util.Map;
     8 
     9 import javax.servlet.ServletContext;
    10 
    11 import org.apache.struts2.ServletActionContext;
    12 import org.apache.struts2.util.StrutsTypeConverter;
    13 
    14 public class DateConverter extends StrutsTypeConverter {
    15 
    16     private DateFormat dateFormat;
    17     
    18     public DateConverter() {
    19         System.out.println("DateConverter's constructor...");
    20         
    21          //获取当前 WEB 应用的初始化参数 pattern
    22          /**
    23          * web.xml的根节点中添加有如下配置:
    24          * <context-param>
    25          *         <param-name>pattern</param-name>
    26          *        <param-value>yyyy-MM-dd HH:mm:ss</param-value>
    27          * </context-param>
    28          */
    29         ServletContext servletContext = ServletActionContext.getServletContext();
    30         System.out.println(servletContext); 
    31         String pattern = servletContext.getInitParameter("pattern");
    32         dateFormat = new SimpleDateFormat(pattern);
    33     }
    34     
    35     @Override
    36     public Object convertFromString(Map context, String[] values, Class toClass) {
    37         
    38         System.out.println("convertFromString...");
    39         
    40         if(toClass == Date.class){
    41             if(values != null && values.length > 0){
    42                 String value = values[0];
    43                 try {
    44                     return dateFormat.parseObject(value);
    45                 } catch (ParseException e) {
    46                     e.printStackTrace();
    47                 }
    48             }
    49         }
    50         
    51         //若没有转换成功, 则返回 values
    52         return values;
    53     }
    54 
    55     @Override
    56     public String convertToString(Map context, Object o) {
    57         
    58         System.out.println("convertToString...");
    59         
    60         if(o instanceof Date){
    61             Date date = (Date) o;
    62             return dateFormat.format(date);
    63         }
    64         
    65         //若转换失败返回 null
    66         return null;
    67     }
    68 
    69 }    

    对应的配置文件名称为:ConversionAction-conversion.properties配置内容如下:

    birth=com.atguigu.struts2.app.converters.DateConverter

    当Model为一个JavaBean时,Java代码如下:

     1 //JavaBean为Customer
     2 package com.atguigu.struts2.model;
     3 
     4 import java.util.Date;
     5 
     6 public class Customer {
     7 
     8     private int age;
     9 
    10     public void setAge(int age) {
    11         this.age = age;
    12     }
    13 
    14     public int getAge() {
    15         return age;
    16     }
    17 
    18     private Date birth;
    19 
    20     public void setBirth(Date birth) {
    21         this.birth = birth;
    22     }
    23 
    24     public Date getBirth() {
    25         return birth;
    26     }
    27     
    28     @Override
    29     public String toString() {
    30         return "Customer [age=" + age + ", birth=" + birth + "]";
    31     }
    32     
    33 }
    34 
    35 //Action代码,Action实现了ModelDriven接口
    36 package com.atguigu.struts2.app;
    37 
    38 import com.atguigu.struts2.model.Customer;
    39 import com.opensymphony.xwork2.ActionSupport;
    40 import com.opensymphony.xwork2.ModelDriven;
    41 
    42 public class ConversionAction extends ActionSupport implements ModelDriven<Customer>{
    43     
    44     public String execute(){
    45         System.out.println("model: " + model);
    46         return "success";
    47     }
    48     
    49     private Customer model;
    50 
    51     @Override
    52     public Customer getModel() {
    53         model = new Customer();
    54         return model;
    55     }
    56     
    57 }

    对应的配置文件名称为:Customer-conversion.properties配置内容如下:

    birth=com.atguigu.struts2.app.converters.DateConverter

    struts.xml中的基本配置如下:

    <action name="testConversion" class="com.atguigu.struts2.app.ConversionAction">
        <result>/success.jsp</result>
        <result name="input">/index.jsp</result>
    </action>

    通过以上代码即可完成字符串与Date类型之间的类型转换工作。

    2)基于类型的配置方式

    在基于类型的配置方式中,JSP页面代码与Action的代码都与基于字段的配置方式的代码相同,但是在类型转换器的代码有所不同:

     1 package com.atguigu.struts2.app.converters;
     2 
     3 import java.text.DateFormat;
     4 import java.text.ParseException;
     5 import java.text.SimpleDateFormat;
     6 import java.util.Date;
     7 import java.util.Map;
     8 
     9 import javax.servlet.ServletContext;
    10 
    11 import org.apache.struts2.ServletActionContext;
    12 import org.apache.struts2.util.StrutsTypeConverter;
    13 
    14 public class DateConverter extends StrutsTypeConverter {
    15 
    16     private DateFormat dateFormat;
    17     
    18     public DateConverter() {
    19         System.out.println("DateConverter's constructor...");
    20     }
    21     
    22     public DateFormat getDateFormat(){
    23         if(dateFormat == null){
    24             //获取当前 WEB 应用的初始化参数 pattern
    25             /**
    26              * web.xml的根节点中添加如下配置:
    27              * <context-param>
    28              *         <param-name>pattern</param-name>
    29              *        <param-value>yyyy-MM-dd HH:mm:ss</param-value>
    30              * </context-param>
    31              */
    32             ServletContext servletContext = ServletActionContext.getServletContext();
    33             System.out.println(servletContext); 
    34             String pattern = servletContext.getInitParameter("pattern");
    35             dateFormat = new SimpleDateFormat(pattern);
    36         }
    37         
    38         return dateFormat;
    39     }
    40     
    41     @Override
    42     public Object convertFromString(Map context, String[] values, Class toClass) {
    43         
    44         System.out.println("convertFromString...");
    45         
    46         if(toClass == Date.class){
    47             if(values != null && values.length > 0){
    48                 String value = values[0];
    49                 try {
    50                     return getDateFormat().parseObject(value);
    51                 } catch (ParseException e) {
    52                     e.printStackTrace();
    53                 }
    54             }
    55         }
    56         
    57         //若没有转换成功, 则返回 values
    58         return values;
    59     }
    60 
    61     @Override
    62     public String convertToString(Map context, Object o) {
    63         
    64         System.out.println("convertToString...");
    65         
    66         if(o instanceof Date){
    67             Date date = (Date) o;
    68             return getDateFormat().format(date);
    69         }
    70         
    71         //若转换失败返回 null
    72         return null;
    73     }
    74 
    75 }    

    注意:关于两种配置方法情况下类型转换器创建时机不同引出的问题

    在基于字段配置的方式下,类型转换器的创建时机是在第一次使用该类型转换器的时候,因此对于dateFormat的初始化工作可以在其构造方法中完成,而在基于类型的配置方式下,类型转换器是在Struts2应用被加载时创建的,由于这时ServletContext对象还未被装载到ServletActionContext中,因此获取到的servletContext对象为null,就不能在类型转换器的构造方法中对dateFormat进行初始化,因此要在使用时判断dateFormat是否为null,然后在执行操作。

    基于类型配置方式的配置文件名称为:xwork-conversion.properties配置内容如下:

    java.util.Date=com.atguigu.struts2.app.converters.DateConverter

    三、关于示例的说明

    以上示例中对于字符串与java.util.Date类型之间的转换,在教程中所演示时无论在页面输入日期格式为“yyyy-MM-dd HH:mm:ss”,还是"yyyy/MM/dd HH:mm:ss",不使用类型转换器Struts2框架都无法正常进行转换,而自己在进行测试的时候,只要按照中文语言环境下的格式输入日期“yyyy-MM-dd”或"yyyy-MM-dd HH:mm:ss"都可以正常执行,而不需要使用类型转换器。

    在网上查找后网友给出的相关解释及解决方法如下:

    1)Struts2中转换Date类型的问题:http://polaris.blog.51cto.com/1146394/315403/

    2)网友给出另一个解决方法在struts.xml中定义参数:<constant name="struts.locale" value="zh_CN" />

    注:该Struts2学习教程来自尚硅谷-佟刚-Struts2教程,感谢尚硅谷及佟刚老师的分享。

     

  • 相关阅读:
    设计模式系列之中介者模式(Mediator Pattern)——协调多个对象之间的交互
    设计模式系列之外观模式(Facade Pattern)——提供统一的入口
    设计模式系列之装饰模式(Decorator Pattern)——扩展系统功能
    设计模式系列之组合模式(Composite Pattern)——树形结构的处理
    设计模式系列之工厂模式三兄弟(Factory Pattern)
    设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建
    设计模式系列之原型模式(Prototype Pattern)——对象的克隆
    动态追踪技术之SystemTap
    一次内核 crash 的排查记录
    LLVM Coding Standards
  • 原文地址:https://www.cnblogs.com/KnightKitt/p/3924576.html
Copyright © 2011-2022 走看看