Struts1—从BeanUtils看struts的实现原理3(自定义BeanUtils的转换器)

    上两篇博客中我们介绍了BeanUtils的基本使用方法,以及在Struts中的运用,但是我们遗憾的发现BeanUtils中提供的类型装换中没有   util.Date  这个我们经常使用的类型。我们如何让其支持这种数据类型,以及我们自定义的数据类型呢。

    解决这个问题我们需要自定义转换器,下面我带着大家来完成这个过程,通过这个过程进一步的了解Struts的运行流程。

    一、我们需要搭建Struts的运行环境,这个所有使用Struts矿建的项目必须要进行的工作,是最基本的工作,这里我就不带着大家做了,不会的直接问度娘吧。这里我默认你已经搭建好了开发环境,只是需要使用BeanUtils来帮助你完成 util.Date  数据类型的装换。

    二、我们需要了解,其他的类型是如何被使用。这里我们就用到了ActionServlet这个Struts给我们提供好的核心的Servlet类。首先这个类是一个Servlet,从他的后缀名中就可以看到,加入Struts1的源码,并找到ActonServlet的init(初始化)方法,我们会发现如下代码:
            initInternal();
            initOther();
            initServlet();  
    其中的intOther()函数我们打开看会发现如下代码:

    protected void initOther() throws ServletException {
        String value = null;
        value = getServletConfig().getInitParameter("config");
        if (value != null) {
            config = value;
        }
        // Backwards compatibility for form beans of Java wrapper classes
        // Set to true for strict Struts 1.0 compatibility
        value = getServletConfig().getInitParameter("convertNull");
        if ("true".equalsIgnoreCase(value)
            || "yes".equalsIgnoreCase(value)
            || "on".equalsIgnoreCase(value)
            || "y".equalsIgnoreCase(value)
            || "1".equalsIgnoreCase(value)) {
            convertNull = true;
        }
        if (convertNull) {
            ConvertUtils.deregister();
            ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
            ConvertUtils.register(new BigIntegerConverter(null), BigInteger.class);
            ConvertUtils.register(new BooleanConverter(null), Boolean.class);
            ConvertUtils.register(new ByteConverter(null), Byte.class);
            ConvertUtils.register(new CharacterConverter(null), Character.class);
            ConvertUtils.register(new DoubleConverter(null), Double.class);
            ConvertUtils.register(new FloatConverter(null), Float.class);
            ConvertUtils.register(new IntegerConverter(null), Integer.class);
            ConvertUtils.register(new LongConverter(null), Long.class);
            ConvertUtils.register(new ShortConverter(null), Short.class);
        }
    }  

    我们大概分析一下,这些代码:
    从web.xml中加载ActionServlet的初始化参数,包括config/ convertNull

protected String config = "/WEB-INF/struts-config.xml"; //  initOther();
protected boolean convertNull = false; //  initOther();
 
// 得到web.xml中"config"参数
String value;
value = getServletConfig().getInitParameter("config");
if (value != null) {
    config = value;
}

    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>   <!-- 得到"config"参数-->
            <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
        <init-param>
            <param-name>convertNull</param-name>   <!-- 得到"convertNull"参数-->
            <param-value>true</param-value>
        </init-param>
        .......
    </servlet>  

// 获得convertNull的值(true/yes/on/y/1)
getServletConfig().getInitParameter("convertNull");
如果这个参数的值为 true (true/yes/on/y/1) , 数值型(BigDecimal/BigInteger/Boolean/Byte/Character/Double/Float/Integer/Long/Short)的Java 包装类(比如java.lang.Integer)的初始值为null,而非0。缺省值[false]
 
使其初始值为null的方法如下:
// 将所有的转换器注销掉
ConvertUtils.deregister();
// 为指定类型clazz注册转换器converter
ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
ConvertUtils.register(new BigIntegerConverter(null),BigInteger.class);
.......



注: ConvertUtils 用法如下
     deregister () 和 register(java.lang.Class clazz)
     注销转换器,前者将所有的转换器注销掉,并重新注册默认的转换器。
     后者是静态方法为指定类型的数据注册转换器
     如果clazz已经存在一个对应的转换器,那么converter覆盖原来的转换器。


    这些转换器的内部是如何实现的我们在” Struts1——从BeanUtils看struts的实现原理1 “中已经有所介绍,这里就不在累述。我们要做的工作其实就是编写自己的类型转换器,并将其注册。而ConvertUtils.register是静态方法我们可以直接调用。这里好像都没有问题了。但是我们何时注册呢,这个问题我们还是看看Struts是如何实现的。我们之前也说过ActionServlet其实就是一个Servlet,它何时被实例化,他的init方法也就何时调用,我们在他的源文件中加入断点调试会发现他在Tomcat启动的时候就会调用,我们完全可以照猫画虎,自己写一个Servlet,经过简单的配置就可以实现。

Servlet代码:

package com.tgb.struts;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.commons.beanutils.ConvertUtils;

public class UtilDateConverterInitWithServlet extends HttpServlet {

	private static final long serialVersionUID = 156689510501572829L;

	@Override
	public void init() throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("UtilDateConverterInitWithServlet.init()");
		ConvertUtils.register(new UtilDateConverter(), java.util.Date.class);
		super.init();
	}

}


Servlet配置文件:

      <servlet-name>UtilDateConverterInitWithServlet</servlet-name>
      <servlet-class>com.tgb.struts.UtilDateConverterInitWithServlet</servlet-class>
      <load-on-startup>10</load-on-startup>


自定义类型转换器:


package com.tgb.struts;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.Converter;
public class UtilDateConverter implements Converter {
    @SuppressWarnings("rawtypes")
    @Override
    public Object convert(Class type, Object value) {
        if (value instanceof Date) {
            return (value);
     }
     Date date = null;
     if (value instanceof String) {
         try {
             date = new SimpleDateFormat("yyyy-MM-dd").parse((String)value);
        } catch (ParseException e) {            
            e.printStackTrace();
        }
     } 
    return date;
    }
}


    所有编写完成,完美实现。

    总结,首先再好的框架都是编程人员用代码,我们要敢去读,其次再好的代码也有可以完善的部分。我们要有探究的精神,敢于发现他的问题。最后,也应该学会取舍,抓住重点,不要奢望一次性的把所有的东西都了解找我,学习就是个过程,需要一点一点,一次一次的来。

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值