在做项目中,经常会用到将带有数据库表格式的XML数据,放入对应的实体中,再保存进数据库。现在的程序都是从老人手里接下来的,代码也是最笨的set属性,每次增加一个字段,就得再加一个set方法。于是想是否可以通过BeanUtils解决掉这个大麻烦。以下是在测试BeanUtils时的一些例子,供参考。
BeanUtils需要用到两个jar包commons-logging.jar,commons-beanutils.jar.点击下载。
setProperty
首先准备一个实体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。同理可以对其它类型进行转换。
copyProperties
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,我们的程序会做不同的处理。
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);