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、设置、访问Bean的属性

1.1)javabean一般有以下几个特性:

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方法,这样的属性一般是只读属性;

1.2)实战

可以通过BeanUtils和PropertyUtils设置、获取Bean的属性。

1)PropertyUtils设置、获取属性:

基本数据类型:

PropertyUtils.getSimpleProperty(Object, String)PropertyUtils.setSimpleProperty(Object, String, Object)索引类型:

PropertyUtils.getIndexedProperty(Object, String)

PropertyUtils.getIndexedProperty(Object, String, int)PropertyUtils.setIndexedProperty(Object, String, Object)PropertyUtils.setIndexedProperty(Object, String, int, Object)Map类型:

PropertyUtils.getMappedProperty(Object, String)

PropertyUtils.getMappedProperty(Object, String, String)PropertyUtils.setMappedProperty(Object, String, Object)PropertyUtils.setMappedProperty(Object, String, String, Object)嵌套类型:

PropertyUtils.getNestedProperty(Object, String)PropertyUtils.setNestedProperty(Object, String, Object)通用类型:

PropertyUtils.getProperty(Object, String)PropertyUtils.setProperty(Object, String, Object)

示例:

//定义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只有以下两个方法来设置、获取属性

BeanUtils.getProperty(Object, String)BeanUtils.setProperty(Object, String, Object)

 示例:

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);

}

2、拷贝Bean的属性

2.1)BeanUtils有一下两个方法:

populate:把Map里的键值对值拷贝到bean的属性值中;copyProperties:拷贝一个bean的属性到另外一个bean中,注意是浅拷贝

注意: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)

说明:

对于Integer、Float、Boolean类型,如果是null,则转成bean的属性后会变成默认值(0,0.1,false)对于Date类型,如果是null或者其他类型,转成bean的时候会报错,需要使用ConvertUtils进行类型转换(见下面)支持类型转换:比如Integer和String之间

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)

}

说明:

对于Integer、Float、Boolean、Date类型,如果是null,拷贝后也是null支持类型转换:两个bean只要属性名一样,类型可转换即可拷贝。比如Integer、Float、Boolean类型转成String

2.2)PropertyUtils进行属性拷贝:

1)和BeanUtils区别:

PropertyUtils只支持两个Bean之间的属性拷贝,不支持Map到Bean的PropertyUtils在两个Bean之间进行属性拷贝时,必须要保证名字和类型都一样才行,否则会报错。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)说明:

PropertyUtils不支持类型转换。对于null值,PropertyUtils拷贝后也是null

3、ConvertUtils自定义类型转换

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,如果存在时间类型,需要自定义转换器。

精彩内容

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。