上两篇博客中我们介绍了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;
}
}
所有编写完成,完美实现。
总结,首先再好的框架都是编程人员用代码,我们要敢去读,其次再好的代码也有可以完善的部分。我们要有探究的精神,敢于发现他的问题。最后,也应该学会取舍,抓住重点,不要奢望一次性的把所有的东西都了解找我,学习就是个过程,需要一点一点,一次一次的来。