如何处理ActionForm里Date型属性 即简单使用org.apache.commons.beanutils.Converter接口
在使用structs框架用到ActionForm时,如果在ActionForm中定义一个成员变量是Date类型,那么就需要进行类型转换注册了。前端的请求都是String类型过来的,如图:
而后端的ActionForm里我定义的成员变量是Date类型,如下:
public class DetailInfoActionForm extends ActionForm {
private String empId;
private String name;
private String gender;
private Integer age;
private String place;//籍贯
private Date entryTime;//入职时间
private String hobbies;//兴趣爱好
private String detailOrg;//详细组织
如果不做任何处理提交表单就报错了,报:
严重: Servlet.service() for servlet action threw exception
Caused by: java.lang.IllegalArgumentException: Cannot invoke detailinfo.DetailInfoActionForm.setEntryTime - argument type mismatch
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1022)
at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:467)
从错误中我们可以清晰的知道 参数非法 参数类型不匹配,所以我们必须做处理,接下来看看如何处理。
第一步 创建一个类 实现转换接口org.apache.commons.beanutils.Converter 这个接口很牛 有兴趣的去了解下 很多框架都用到它。它的作用就是利用类的反射机制 实现类里成员属性的添加转换等等(个人理解)
package util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.beanutils.Converter;
public class DateConverter implements Converter{
/**
* 日期格式化对象
*/
private static SimpleDateFormat sdf = new SimpleDateFormat();
/**
* 模式集合
*/
private static Set<String> patterns = new HashSet<String>();
/**
* 把一些要转换的字符串样式加入到静态成员patterns里
*/
static{
DateConverter.patterns.add("");
DateConverter.patterns.add("yy年MM月dd日");
DateConverter.patterns.add("yyyy年MM月dd日");
DateConverter.patterns.add("yyyy-MM-dd");
DateConverter.patterns.add("yyyy-MM-dd HH:mm:ss");
DateConverter.patterns.add("yyyy-MM-dd HH:mm");
DateConverter.patterns.add("yyyy/MM/dd HH:mm:ss");
}
/**
* 必须实现的接口方法 逻辑处理
* type想要处理的类型
* value前台传到form里的值
*/
public Object convert(Class type, Object value) {//有意思的是 这里的type参数 方法中并未使用,我想是到时注册时会进行一个调用吧(猜测)
if(value == null){
return null;
}else if(value instanceof String){
Object dateObj = null;
Iterator<String> it = patterns.iterator();
while(it.hasNext()){
try {//分别按不同的格式类型去解析字符串 解析成功的话就break这个循环
String pattern = it.next();
sdf.applyPattern(pattern);
dateObj = sdf.parse((String) value);
break;
} catch (ParseException e) {
// TODO: handle exception
}
}
return dateObj;
} else {
return null;
}
}
}
第二步 在ActionForm类里使用org.apache.commons.beanutils.ConvertUtils 这个类进行注册(就是调用一个register(Converter,Class)方法)
通过以上两步 就大功高成了!
这里关键点就在于需要使用ConvertUtils这个阿帕奇公司编写的转换工具类里的一个注册方法,这个方法需要的两个参数分别是
实现Converter接口的一个类和想要转成的一个类型,这里我们需要日期就是Date.class类型。
总之这样一弄就好了 具体为什么这样一写就好 肯定涉及到了类的反射机制等等比较深奥的内容,有兴趣的朋友可以去看源码。
我猜测肯定就是这个方法里
第一要获得当前ActionForm类 然后想办法遍历它的属性 找到要处理的Date类型属性 只要是这种类型的属性就会去从 表单对应的属性名进行匹配处理。思路肯定就是这种思路。