beanutils,顾名思义,是java bean的一个工具类,可以帮助我们方便的读取(get)和设置(set)bean属性值、动态定义和访问bean属性;细心的话,会发现其实JDK已经提供了一个java.beans包,同样可以实现以上功能,只不过使用起来比较麻烦,所以诞生了apache commons beanutils;看源码就知道,其实apache commons beanutils就是基于jdk的java.beans包实现的。
maven:
commons-chain
commons-chain
1.2
commons-chain包主要有以下三个工具类:BeanUtils、PropertyUtils、ConvertUtils
1)类必须是public访问权限,且需要有一个public的无参构造方法,之所以这样主要是方便利用Java的反射动态创建对象实例:
Class beanClass = Class.forName(className);
Object beanInstance = beanClass.newInstance();
2)由于javabean的构造方法是无参的,所以我们的bean的行为配置(即设置bean的属性值)不能在构造方法完成,必须通过set方法来设置属性值。这里的setter方法会按一定的约定来命名,如setHireDate、setName。。。
3)读取和设置bean属性值的命名约定,即getter方法和setter方法,不过这里需要特别注意boolean类型的约定,如下示例:
private String firstName;
private String lastName;
private Date hireDate;
private boolean isManager;
public String getFirstName();
public void setFirstName(String firstName);
public String getLastName();
public void setLastName(String lastName);
public Date getHireDate();
public void setHireDate(Date hireDate);
public boolean isManager();
public void setManager(boolean manager);
4)并不是必须为每个属性提供setter和getter方法,我们可以只定义一个属性的getter方法而不定义setter方法,这样的属性一般是只读属性;
可以通过BeanUtils和PropertyUtils设置、获取Bean的属性。
1)PropertyUtils设置、获取属性:
示例:
//定义bean
@Data
@ToString
public class Course {
private String name;
private List codes;
private Map enrolledStudent = new HashMap<>();
}
@Data
@ToString
public class Student {
private String name;
}
//测试
Course course = new Course(); //该类必须是public的、且有默认构造方法
String name = "Computer Science";
List codes = Arrays.asList("CS", "CS01");
//Simple Property
PropertyUtils.setSimpleProperty(course, "name", name);
PropertyUtils.setSimpleProperty(course, "codes", codes);
System.out.println(course);
String nameV = (String)PropertyUtils.getSimpleProperty(course, "name");
System.out.println(nameV);
//Indexed Property
PropertyUtils.setIndexedProperty(course, "codes[1]", "CS02");
PropertyUtils.setIndexedProperty(course, "codes", 1, "CS03");
System.out.println(course);
String indexedProperty = (String)PropertyUtils.getIndexedProperty(course, "codes", 1);
String indexedProperty2 = (String)PropertyUtils.getIndexedProperty(course, "codes[1]");
System.out.println(indexedProperty + "," + indexedProperty2);
Student student = new Student();
String studentName = "Joe";
student.setName(studentName);
//Mapped Property
PropertyUtils.setMappedProperty(course, "enrolledStudent(ST-1)", student);
PropertyUtils.setMappedProperty(course, "enrolledStudent", "ST-1", student);
System.out.println(course);
Student mappedProperty = (Student)PropertyUtils.getMappedProperty(course, "enrolledStudent", "ST-1");
Student mappedProperty2 = (Student)PropertyUtils.getMappedProperty(course, "enrolledStudent(ST-1)");
System.out.println(mappedProperty + "," + mappedProperty2);
//Nested Property
PropertyUtils.setNestedProperty(course, "enrolledStudent(ST-1).name", "Joe_1");
String nameValue = (String) PropertyUtils.getNestedProperty(course, "enrolledStudent(ST-1).name");
//等价于 String name = course.getEnrolledStudent("ST-1").getName();
System.out.println(nameValue);
以上还可以使用下面的方式:
private static void test1_1() throws Exception {
Course course = new Course();
String name = "Computer Science";
List codes = Arrays.asList("CS", "CS01");
//Simple Property
PropertyUtils.setProperty(course, "name", name);
PropertyUtils.setProperty(course, "codes", codes);
System.out.println(course);
String nameV = (String)PropertyUtils.getProperty(course, "name");
System.out.println(nameV);
//Indexed Property
PropertyUtils.setProperty(course, "codes[1]", "CS02");
System.out.println(course);
Student student = new Student();
String studentName = "Joe";
student.setName(studentName);
//Mapped Property
PropertyUtils.setProperty(course, "enrolledStudent(ST-1)", student);
System.out.println(course);
//Nested Property
PropertyUtils.setProperty(course, "enrolledStudent(ST-1).name", "Joe_1");
String nameValue = (String) PropertyUtils.getProperty(course, "enrolledStudent(ST-1).name");
System.out.println(nameValue);
}
2)BeanUtils设置、获取属性:
BeanUtils只有以下两个方法来设置、获取属性
示例:
private static void test1_2() throws Exception {
Course course = new Course();
String name = "Computer Science";
List codes = Arrays.asList("CS", "CS01");
//Simple Property
BeanUtils.setProperty(course, "name", name);
BeanUtils.setProperty(course, "codes", codes);
System.out.println(course);
String nameV = (String)BeanUtils.getProperty(course, "name");
System.out.println(nameV);
//Indexed Property
BeanUtils.setProperty(course, "codes[1]", "CS02");
System.out.println(course);
Student student = new Student();
String studentName = "Joe";
student.setName(studentName);
//Mapped Property
BeanUtils.setProperty(course, "enrolledStudent(ST-1)", student);
System.out.println(course);
//Nested Property
BeanUtils.setProperty(course, "enrolledStudent(ST-1).name", "Joe_1");
String nameValue = (String) BeanUtils.getProperty(course, "enrolledStudent(ST-1).name");
System.out.println(nameValue);
}
注意:populate和copyProperties的区别,对于Integer、Float、Boolean类型前者(populate)对于null值,在拷贝到Bean的属性后会变成默认值。
1)populate:
//bean定义
import java.util.Date;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Employee {
private Integer id;
private String name;
private Boolean isGood;
private Float score;
private Date createTime;
public Employee(Integer id, String name, Boolean isGood, Float score, Date createTime) {
this.id = id;
this.name = name;
this.isGood = isGood;
this.score = score;
this.createTime = createTime;
}
}
//测试
Map map = new HashMap<>(2);
map.put("id", null);
map.put("name", "employee1");
map.put("isGood", null);
map.put("createTime", new Date()); //如果是null,会报错
map.put("add", "add1");
// map > obj
Employee e = new Employee();
BeanUtils.populate(e, map);
System.out.println(e); //Employee(id=0, name=employee1, isGood=false, createTime=Tue Aug 15 10:42:14 CST 2023)
//支持类型转换
Map map = new HashMap<>(5);
map.put("id", "123");
map.put("name", 1.9);
map.put("isGood", "2");
map.put("score", null);
map.put("createTime", new Date());
map.put("add", "add1");
// map > obj
Employee e = new Employee();
BeanUtils.populate(e, map);
System.out.println(e); //Employee(id=123, name=1.9, isGood=false, score=1.0, createTime=Tue Aug 15 12:34:41 CST 2023)
说明:
2)copyProperties:
有另外一个对象(类型和Employee不同)
@Data
public class Employee2 {
private Integer id;
private String name;
private String isGood;
private String score;
private String createTime;
private Float f1;
}
测试
private static void test2_1() throws Exception {
Employee ee = new Employee(null, "employee2", null, null, null);
Employee2 e1 = new Employee2();
BeanUtils.copyProperties(e1, ee);
System.out.println(e1); //Employee2(id=null, name=employee2, isGood=null, score=null, createTime=null, f1=null)
Employee ee2 = new Employee(1, "employee2", true, 4.3f, new Date());
Employee2 e2 = new Employee2();
BeanUtils.copyProperties(e2, ee2);
System.out.println(e2); //Employee2(id=1, name=employee2, isGood=true, score=4.3, createTime=Tue Aug 15 11:45:06 CST 2023, f1=null)
}
说明:
1)和BeanUtils区别:
Employee ee = new Employee(null, "employee2", null, null, null);
Employee2 e1 = new Employee2();
PropertyUtils.copyProperties(e1, ee);
System.out.println(e1); //Employee2(id=null, name=employee2, isGood=null, score=null, createTime=null, f1=null)
Employee ee2 = new Employee(1, "employee2", true, 4.3f, new Date());
Employee2 e2 = new Employee2();
PropertyUtils.copyProperties(e2, ee2);
System.out.println(e2); //报错
报错信息:
2)说明:
1)DateConverter:
DateConverter继承DateTimeConverter,是beanutils包中自带的时间类型转换,包含了:
示例
DateConverter converter = new DateConverter();
converter.setPattern("yyyy-MM-dd");
ConvertUtils.register(converter, java.util.Date.class);
Map map = new HashMap<>(5);
map.put("id", 1);
map.put("name", "testConvertUtils");
map.put("isGood", false); //可以是Integer或String,1或"1" true 其他表示false,null表示false
map.put("score", 1.1f);
map.put("createTime", "2023-08-15");
map.put("add", "add1");
// map > obj
Employee e = new Employee();
BeanUtils.populate(e, map);
System.out.println(e); //Employee(id=1, name=testConvertUtils, isGood=false, score=1.1, createTime=Tue Aug 15 00:00:00 CST 2023)
2)自定义:
ConvertUtils.register(new Converter() {
public Object convert(Class type, Object value) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
return simpleDateFormat.parse(value.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}, Date.class);
Employee e1 = new Employee();
BeanUtils.setProperty(e1, "createTime", "2022-09-09");
System.out.println(e1.getCreateTime()); //Fri Sep 09 00:00:00 CST 2022
说明:对于setProperty,如果存在时间类型,需要自定义转换器。