Apache BeanUtils tool introduction

beanutils, as the name suggests, is a tool class for java beans, which can help us easily read (get) and set (set) bean property values, dynamically define and access bean properties; if you are careful, you will find that JDK has provided a java The .beans package can also achieve the above functions, but it is more troublesome to use, so apache commons beanutils was born; you can see from the source code that in fact, apache commons beanutils is implemented based on the java.beans package of jdk.

maven:

<dependency>
        <groupId>commons-chain</groupId>
        <artifactId>commons-chain</artifactId>
        <version>1.2</version>
</dependency>

The commons-chain package mainly has the following three tool classes: BeanUtils, PropertyUtils, ConvertUtils

1. Set and access Bean properties

1.1) Javabeans generally have the following characteristics:

1) The class must have public access rights, and it needs to have a public no-argument construction method . The reason for this is mainly to facilitate the use of Java reflection to dynamically create object instances:

Class beanClass = Class.forName(className);

Object beanInstance = beanClass.newInstance();

2) Since the construction method of javabean has no parameters, the behavior configuration of our bean (that is, setting the property value of the bean) cannot be completed in the construction method, and the property value must be set through the set method. The setter method here will be named according to a certain convention, such as setHireDate, setName. . .

3) The naming convention for reading and setting bean property values, that is, the getter method and the setter method, but here you need to pay special attention to the boolean type convention, as shown in the following example:

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) It is not necessary to provide setter and getter methods for each attribute. We can only define a getter method for an attribute without defining a setter method. Such attributes are generally read-only attributes;

1.2) Actual combat

Bean properties can be set and obtained through BeanUtils and PropertyUtils.

1) PropertyUtils set and get properties:

  • Basic data types:
    • PropertyUtils.getSimpleProperty(Object, String)
    • PropertyUtils.setSimpleProperty(Object, String, Object)
  • Index type:
    • PropertyUtils.getIndexedProperty(Object, String)
    • PropertyUtils.getIndexedProperty(Object, String, int)
    • PropertyUtils.setIndexedProperty(Object, String, Object)
    • PropertyUtils.setIndexedProperty(Object, String, int, Object)
  • Map type:
    • PropertyUtils.getMappedProperty(Object, String)
    • PropertyUtils.getMappedProperty(Object, String, String)
    • PropertyUtils.setMappedProperty(Object, String, Object)
    • PropertyUtils.setMappedProperty(Object, String, String, Object)
  • nested type:
    • PropertyUtils.getNestedProperty(Object, String)
    • PropertyUtils.setNestedProperty(Object, String, Object)
  • Generic type:
    • PropertyUtils.getProperty(Object, String)
    • PropertyUtils.setProperty(Object, String, Object)

Example:

//定义bean
@Data
@ToString
public class Course {
	private String name;
    private List<String> codes;
    private Map<String, Student> enrolledStudent = new HashMap<>();
}
@Data
@ToString
public class Student {
	private String name;
}

//测试
Course course = new Course(); //该类必须是public的、且有默认构造方法

String name = "Computer Science";
List<String> 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);

The above can also be used in the following way:

private static void test1_1() throws Exception {
        Course course = new Course();
        
        String name = "Computer Science";
        List<String> 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 set and get properties:

BeanUtils has only the following two methods to set and get properties

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

 Example:

private static void test1_2() throws Exception {
        Course course = new Course();
        
        String name = "Computer Science";
        List<String> 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. Copy the properties of the Bean

2.1) BeanUtils has the following two methods:

  • populate: copy the key-value pair value in the Map to the property value of the bean;
  • copyProperties: Copy the properties of one bean to another bean, pay attention to the shallow copy

Note: The difference between populate and copyProperties is that for Integer, Float, and Boolean types, the former (populate) for null values ​​will become the default value after being copied to the properties of the 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<String, Object> 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<String, Object> 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)

illustrate:

  • For Integer, Float, and Boolean types, if it is null, it will become the default value (0, 0.1, false) after being converted into the property of the bean
  • For the Date type, if it is null or other types, an error will be reported when it is converted into a bean, and ConvertUtils needs to be used for type conversion (see below)
  • Support type conversion: such as between Integer and String

2)copyProperties:

There is another object (different type from Employee)

@Data
public class Employee2 {
	private Integer id;
	private String name;
	private String isGood;
	private String score;
	private String createTime;
	private Float f1;
}

test

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

illustrate:

  • For Integer, Float, Boolean, and Date types, if it is null, it will also be null after copying
  • Support type conversion: as long as two beans have the same property name, the type can be converted and copied. For example, convert Integer, Float, and Boolean types to String

2.2) PropertyUtils for property copy:

1) Differences from BeanUtils:

  • PropertyUtils only supports copying of properties between two beans, not Map to Bean
  • When PropertyUtils copies properties between two beans, it must ensure that the names and types are the same , otherwise an error will be reported. When BeanUtils copies properties, the names are the same and the types can be converted.

 

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); //报错

Error message:

 

2) Description:

  • PropertyUtils does not support type conversion.
  • For null values, PropertyUtils is also null after copying

3. ConvertUtils custom type conversion

1)DateConverter:

DateConverter inherits DateTimeConverter, which is the time type conversion that comes with the beanutils package, including:

example

DateConverter converter = new DateConverter();
converter.setPattern("yyyy-MM-dd");
ConvertUtils.register(converter, java.util.Date.class);

Map<String, Object> 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) Customize: 

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

Note: For setProperty, if there is a time type, a custom converter is required.

Guess you like

Origin blog.csdn.net/liuxiao723846/article/details/132422611