在做项目中,经常会用到将带有数据库表格式的XML数据,放入对应的实体中,再保存进数据库。现在的程序都是从老人手里接下来的,代码也是最笨的set属性,每次增加一个字段,就得再加一个set方法。于是想是否可以通过BeanUtils解决掉这个大麻烦。以下是在测试BeanUtils时的一些例子,供参考。
BeanUtils需要用到两个jar包commons-logging.jar,commons-beanutils.jar.点击下载。
首先准备一个实体User.java
package com.entity;
import java.util.Date;
public class User {
private int id;
private String name;
private int age;
private Date birthday;
private boolean isManager;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public boolean getIsManager() {
return isManager;
}
public void setIsManager(boolean isManager) {
this.isManager = isManager;
}
}
准备测试数据,由于我要模拟xml取数据,得到的值都是String,所以使用Map,一般情况下使用Map
Map<String, String> mapField = new HashMap<String, String>();
mapField.put("id", "1");
mapField.put("name", "aa");
mapField.put("age", "20");
mapField.put("birthday", "2012-11-13 01:00:00");
mapField.put("isManager", "Y");
使用方法很简单
for(String key : mapField.keySet()){
BeanUtils.setProperty(user, key, mapField.get(key));
}
但是直接使用上面的方法会报错,注意到我们的实体中有个日期类型,但是取到的数据是String,所以直接使用setProperty会报错: java.lang.IllegalArgumentException: argument type mismatch
我们需要告诉BeanUtils,对Date类型的处理方法,使用Converter接口来处理,在实现Converter接口时,需要重写convert方法。最后使用ConvertUtils.register注册下这个实例。还是直接看代码吧:
package com.beanutils;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import com.entity.User;
import com.utils.converter.DateConverter;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Map<String, String> mapField = new HashMap<String, String>();
mapField.put("id", "1");
mapField.put("name", "aa");
mapField.put("age", "20");
mapField.put("birthday", "2012-11-13 01:00:00");
mapField.put("isManager", "Y");
User user = new User();
Converter convertorBool = new Converter() {
@Override
public Boolean convert(Class clazz, Object arg1) {
Boolean bool = false;
if(arg1.equals("Y")){
bool = true;
}
return bool;
}
};
Converter convertorDate = new Converter() {
@Override
public Date convert(Class clazz, Object arg1) {
if (arg1 == null) {
return null;
}
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dt = null;
try {
dt = sdf.parse((String) arg1);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
return dt;
}
};
ConvertUtils.register(convertorDate, Date.class);
ConvertUtils.register(convertorBool, Boolean.class);
for(String key : mapField.keySet()){
try {
BeanUtils.setProperty(user, key, mapField.get(key));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
System.out.println(user.getId());
System.out.println(user.getName());
System.out.println(user.getAge());
System.out.println(user.getBirthday());
System.out.println(user.getIsManager());
}
}
上面给出了对Date和Boolean的数据的转换,当取到的值为Y时,就对Boolean类型赋true。同理可以对其它类型进行转换。
BeanUtils.copyProperties(dest, orig)是对实体属性的拷贝,为了做测试,我们新建个UserNew.java:
package com.entity;
import java.util.Date;
public class UserNew {
private int id;
private String name;
private int age;
private Date birthday;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
注意,它跟User.java并不完全相同,测试的代码也很简单,只需在Main方法的最后加入下面的代码:
UserNew userNew = new UserNew();
try {
BeanUtils.copyProperties(userNew, user);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(userNew.getId());
System.out.println(userNew.getName());
System.out.println(userNew.getAge());
System.out.println(userNew.getBirthday());
System.out.println(userNew.getAddress());
但是在执行的时候会报异常,但是报异常前会有一些输出: 1 aa 20 Tue Nov 13 01:00:00 CST 2012 true Exception in thread “main” java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String ---------------- 仔细分析的话,可以看出是在copyProperties时,会将user.birthday拷贝到userNew.birthday,但是会用到convertorDate对象来转换,注意在convertorDate对应的类里,会将参数,先强制转换为String,再按yyyy-MM-dd HH:mm:ss格式转为日期,但是注意到user.birthday强制转换为String时,是Tue Nov 13 01:00:00 CST 2012,这点可从打印出的字符串可以看出来,这要转换成yyyy-MM-dd HH:mm:ss格式当然会报错。
为了解决上面的问题,同时让代码更清晰,我们新建一个类DateConverter,来实现Converter接口,放到单独的文件类,同时对传入的参数做判断,它是String或Boolean,我们的程序会做不同的处理。
package com.utils.converter ; import java.text.ParseException ; import java.text.SimpleDateFormat ; import java.util.Date ; import org.apache.commons.beanutils.Converter ; public class DateConverter implements Converter { private String format ; private SimpleDateFormat simpleDateFormat ; public DateConverter ( ) { format = "yyyy-MM-dd HH:mm:ss" ; } public DateConverter ( String format ) { this. format = format ; } @SuppressWarnings ( "rawtypes" ) @Override public Object convert ( Class arg0, Object arg1 ) { if (arg1 == null ) { return null ; } simpleDateFormat = new SimpleDateFormat (format ) ; String str = "" ; if (arg1 instanceof String ) { str = ( String ) arg1 ; } else if (arg1 instanceof Date ) { str = simpleDateFormat. format (arg1 ) ; } Date date = convertToDate (str ) ; return date ; } public Date convertToDate ( String str ) { Date dt = null ; try { simpleDateFormat = new SimpleDateFormat (format ) ; dt = simpleDateFormat. parse (str ) ; } catch ( ParseException e ) { e. printStackTrace ( ) ; } return dt ; } }
Main函数的调用就变得很简单了,以后在其它用到BeanUtils的地方都可以直接用如下代码注册。对boolean等其它类型的转换,都可以利用Converter接口来实现。 ConvertUtils.register(new DateConverter(), Date.class);