对于每一个客户请求,Struts的ActionServlet只负责把请求转发给相应模块的的RequestProcessor对象去处理。
读了Struts的源码,发现:
如果请求中附有From表单信息,则RequestProcessor的processActionForm方法负责将客户端传过来的表单信息封装成相应的ActionForm对象。
processActionForm方法则执行了如下语句:
ActionForm instance =
RequestUtils.createActionForm(request, mapping, moduleConfig,
servlet);
在RequestUtils中,Struts从配置文件中获取了这个ActionForm类的各个成员变量的转换map,这个map标识了各个成员变量从String类型转换到何种类型。这个map命名为properties后,Struts通过BeanUtils.populate(bean, properties)方法将类型转换的任务委托给了comments-beanutils包。
在comments-beanutils包中,BeanUtils类把转换任务下交给BeanUtilsBean:
BeanUtilsBean.getInstance().populate(bean, properties);
BeanUtilsBean根据map中的name-value值,bean中的各个成员变量进行setProperty,setProperty方法主要是根据comments-beanutils包中已经存在的Convert类,将String类型的表单输入转换成相应的成员变量类型,从而实现对bean中的属性进行赋值。
由于comments-beanutils包中自带的Convert类不能解决所有的问题。例如,这个包提供了从String到java.sql.Date的转换。但是没有提供从String到java.util.Date的转换。
所以,有时候,我们需要自定义一个Convert类,然后注册给ConvertUtils,从而实现让Struts转化String为自定义的类。
因为要在系统启动时就注册自定义的Convert类,所以常用的方法有,自定义一个自动load的Servlet,在它的init方法中注册Convert类。另一种方法是,自定一个ActionServlet,在它的init方法中注册Convert类。
给出第二种方法的一个实现:
首先,定义一个Convert:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.Converter;
public class DateConverter implements Converter {
public Object convert(Class type, Object value) {
String src = (String)value;
Date dest = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
dest = sdf.parse(src);
} catch (ParseException e) {
}
return dest;
}
}
自定义ActionServlet,注册DateConvert:
import java.util.Date;
import javax.servlet.ServletException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.struts.action.ActionServlet;
public class CustomerActionServlet extends ActionServlet {
public void init() throws ServletException {
ConvertUtils.register(new DateConverter(), Date.class);
super.init();
}
}
最后配置这个ActionServlet为使用的Servlet即可。