首页 > 代码库 > 从源代码剖析Struts2中用户自定义配置转换器的两种方式——基于字段的配置转换器和基于类型的配置转换器(解决了实际系统中,因没有区分这两种工作方式的生命周期而引起的异常错误问题)

从源代码剖析Struts2中用户自定义配置转换器的两种方式——基于字段的配置转换器和基于类型的配置转换器(解决了实际系统中,因没有区分这两种工作方式的生命周期而引起的异常错误问题)

自定义类型转换器必须实现ongl.TypeConverter接口或对这个接口的某种具体实现做扩展

<<interface>>com.opensymphony.xwork2.conversion.TypeConverter
 à com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter
 à org.apache.struts2.util.StrutsTypeConverter

接口及类进行解析

TypeConverter(接口)

Interface for accessing the type conversion facilities within a context. This interface was copied from OGNL‘s TypeConverter

 

DefaultTypeConverter

public class DefaultTypeConverter implements TypeConverter

Default type conversion. Converts among numeric types and also strings. Contains the basic type mapping code from OGNL.

 

StrutsTypeConverter

public abstract class StrutsTypeConverter extends DefaultTypeConverter

Base class for type converters used in Struts. This class provides two abstract methods that are used to convert both to and from strings -- the critical functionality that is core to Struts‘s type coversion system.

 

下面是源代码中上面各接口及类相关的方法及属性轮廓图:


源问题: 如何自定义类型转换器 ?  

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

         2、如何定义类型转换器:

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

         II.配置类型转换器:

 

解决源问题的方法:配置类型转换器两种方式

         ①. 基于字段的配置类型转换器:

                   >在字段所在的 Model(可能是 Action, 可能是一个 JavaBean) 的包下, 新建一个 ModelClassName-conversion.properties 文件

                   >在该文件中输入键值对: fieldName=类型转换器的全类名.

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

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


         ②. 基于类型的配置类型转换器:

                   >在 src 下新建 xwork-conversion.properties

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

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


细节注意:.properties配置文件的位置(该文件存放的位置)


现在看看文件的结构信息:


ConversionAction.java文件

package com.atguigu.struts2.app;

 

import com.atguigu.struts2.model.Customer;

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

 

public class ConversionAction extends ActionSupportimplements ModelDriven<Customer>{

 

    private static final long serialVersionUID = 1L;

   

    public Stringexecute(){

       System.out.println("model: " +model);

       return"success";

    }

   

    private Customermodel;

 

    @Override

    public Customer getModel() {

       model = new Customer();

       returnmodel;

    }

   

}

 

 

DateConverter.java文件

package com.atguigu.struts2.app.converters;

 

import java.text.DateFormat;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Map;

 

import javax.servlet.ServletContext;

 

import org.apache.struts2.ServletActionContext;

import org.apache.struts2.util.StrutsTypeConverter;

 

public class DateConverter extends StrutsTypeConverter {

 

    private DateFormatdateFormat;

   

    public DateConverter() {

       System.out.println("DateConverter‘s constructor...");

      

       /**

       //应用加载时机不同而产生的异常(NullException

       //获取当前 WEB应用的初始化参数 pattern(该参数在WEB-INF下的web.xml文件中)

       //这种方法使用/struts2-6/Customer-conversion.properties配置文件

       //Customer-conversion.properties配置文件的内容:

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

       ServletContext servletContext = ServletActionContext.getServletContext();

       System.out.println(servletContext);

       String pattern = servletContext.getInitParameter("pattern");

       dateFormat = new SimpleDateFormat(pattern);

        *

        */

      

    }

   

    /**

     * 解决上面的问题,而重写的一个方法

     * @return

     */

    public DateFormat getDateFormat(){

       if(dateFormat ==null){

           //获取当前 WEB应用的初始化参数 pattern(该参数在WEB-INF下的web.xml文件中)

           //第一次用的时候获取,并加载相关的信息

           //这种方法是使用/struts2-6/src/xwork-conversion.properties配置文件

           //xwork-conversion.properties配置文件的内容:

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

           ServletContext servletContext = ServletActionContext.getServletContext();

           System.out.println(servletContext);

           String pattern = servletContext.getInitParameter("pattern");

           dateFormat = new SimpleDateFormat(pattern);

       }

      

       returndateFormat;

    }

   

    @Override

    public Object convertFromString(Map context, String[] values,Class toClass) {

      

       System.out.println("convertFromString...");

      

       if(toClass == Date.class){

           if(values !=null && values.length > 0){

              String value = http://www.mamicode.com/values[0];

              try {

                  // return dateFormat.parseObject(value);

                  return getDateFormat().parseObject(value);

              } catch (ParseException e) {

                  e.printStackTrace();

              }

           }

       }

      

       //若没有转换成功,则返回 values

       return values;

    }

 

    @Override

    public String convertToString(Map context, Object o) {

      

       System.out.println("convertToString...");

      

       if(o instanceof Date){

           Date date = (Date) o;

           //return dateFormat.format(date);

           return getDateFormat().format(date);

       }

      

       //若转换失败返回 null

       return null;

    }

 

}

 

 

显示页面的信息:

Index.jsp

<s:formaction="testConversion"theme="simple">

       Age: <s:textfieldname="age"label="Age"></s:textfield>

       ${fieldErrors.age[0] }

       ^<s:fielderrorfieldName="age"></s:fielderror>

       <br><br>

      

       Birth: <s:textfieldname="birth"></s:textfield>

       <s:fielderrorfieldName="birth"></s:fielderror>

       <br><br>

      

       <s:submit></s:submit>

    </s:form>

 

Struts.xml的文件的信息:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstruts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

 

<struts>

    <packagename="default"namespace="/"extends="struts-default">

       <actionname="testConversion"class="com.atguigu.struts2.app.ConversionAction">

           <result>/success.jsp</result>

           <resultname="input">/index.jsp</result>

       </action>

      

       <actionname="testComplextProperty"class="com.atguigu.struts2.app.TestComplextPropertyAction">

           <result>/success.jsp</result>

       </action>

      

       <actionname="testConversion2"class="com.atguigu.struts2.app.TestCollectionAction">

           <result>/success.jsp</result>

       </action>

    </package>

</struts>

<debug></debug>信息:


提交之后跳转到如下页面信息如下:


从源代码剖析Struts2中用户自定义配置转换器的两种方式——基于字段的配置转换器和基于类型的配置转换器(解决了实际系统中,因没有区分这两种工作方式的生命周期而引起的异常错误问题)