beanutils, como o nome sugere, é uma classe de ferramenta para java beans, que pode nos ajudar a ler (obter) e definir (definir) facilmente valores de propriedades de bean, definir dinamicamente e acessar propriedades de bean; se você for cuidadoso, descobrirá que JDK forneceu um pacote java .beans também pode realizar as funções acima, mas é mais problemático de usar, então o apache commons beanutils nasceu; você pode ver no código-fonte que, na verdade, o apache commons beanutils é implementado com base no java Pacote .beans do jdk.
especialista:
<dependency>
<groupId>commons-chain</groupId>
<artifactId>commons-chain</artifactId>
<version>1.2</version>
</dependency>
O pacote commons-chain possui principalmente as seguintes três classes de ferramentas: BeanUtils, PropertyUtils, ConvertUtils
1. Defina e acesse as propriedades do Bean
1.1) Javabeans geralmente possuem as seguintes características:
1) A classe deve ter direitos de acesso público e um método de construção público sem argumentos . A razão para isso é principalmente para facilitar o uso da reflexão Java para criar instâncias de objetos dinamicamente:
Classe beanClass = Class.forName(className);
Objeto beanInstance = beanClass.newInstance();
2) Como o método de construção do javabean não possui parâmetros, a configuração do comportamento do nosso bean (ou seja, definir o valor da propriedade do bean) não pode ser concluída no método de construção, e o valor da propriedade deve ser definido através do método set. O método setter aqui será nomeado de acordo com uma determinada convenção, como setHireDate, setName. . .
3) A convenção de nomenclatura para leitura e definição de valores de propriedades do bean, ou seja, o método getter e o método setter, mas aqui você precisa prestar atenção especial à convenção do tipo booleano, conforme mostrado no exemplo a seguir:
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) Não é necessário fornecer métodos setter e getter para cada atributo. Só podemos definir um método getter para um atributo sem definir um método setter. Tais atributos são geralmente atributos somente leitura;
1.2) Combate real
As propriedades do bean podem ser definidas e obtidas por meio de BeanUtils e PropertyUtils.
1) PropertyUtils define e obtém propriedades:
- Tipos de dados básicos:
- PropertyUtils.getSimpleProperty(Objeto, String)
- PropertyUtils.setSimpleProperty(Objeto, String, Objeto)
- Tipo de índice:
- PropertyUtils.getIndexedProperty (Objeto, String)
-
- PropertyUtils.getIndexedProperty(Objeto, String, int)
- PropertyUtils.setIndexedProperty (Objeto, String, Objeto)
- PropertyUtils.setIndexedProperty(Objeto, String, int, Objeto)
- Tipo de mapa:
- PropertyUtils.getMappedProperty (Objeto, String)
-
- PropertyUtils.getMappedProperty(Objeto, String, String)
- PropertyUtils.setMappedProperty(Objeto, String, Objeto)
- PropertyUtils.setMappedProperty(Objeto, String, String, Objeto)
- tipo aninhado:
- PropertyUtils.getNestedProperty(Objeto, String)
- PropertyUtils.setNestedProperty(Objeto, String, Objeto)
- Tipo genérico:
- PropertyUtils.getProperty (Objeto, String)
- PropertyUtils.setProperty(Objeto, String, Objeto)
Exemplo:
//定义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);
O acima também pode ser usado da seguinte maneira:
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 define e obtém propriedades:
BeanUtils possui apenas os dois métodos a seguir para definir e obter propriedades
- BeanUtils.getProperty (Objeto, String)
- BeanUtils.setProperty (Objeto, String, Objeto)
Exemplo:
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. Copie as propriedades do Bean
2.1) BeanUtils possui os dois métodos a seguir:
- populate: copia o valor do par chave-valor no Mapa para o valor da propriedade do bean;
- copyProperties: Copie as propriedades de um bean para outro bean, preste atenção na cópia superficial
Nota: A diferença entre populate e copyProperties é que para os tipos Integer, Float e Boolean, o primeiro (populate) para valores nulos se tornará o valor padrão após ser copiado para as propriedades do Bean.
1)preencher:
//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)
ilustrar:
- Para os tipos Integer, Float e Boolean, se for nulo, se tornará o valor padrão (0, 0,1, false) após ser convertido na propriedade do bean
- Para o tipo Date, se for null ou outros tipos, um erro será relatado quando for convertido em um bean, e ConvertUtils precisa ser usado para conversão de tipo (veja abaixo)
- Conversão de tipo de suporte: como entre Inteiro e String
2)copiarPropriedades:
Existe outro objeto (tipo diferente de Funcionário)
@Data
public class Employee2 {
private Integer id;
private String name;
private String isGood;
private String score;
private String createTime;
private Float f1;
}
teste
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)
}
ilustrar:
- Para os tipos Integer, Float, Boolean e Date, se for nulo, também será nulo após a cópia
- Suporte à conversão de tipo: desde que dois beans tenham o mesmo nome de propriedade, o tipo pode ser convertido e copiado. Por exemplo, converta os tipos Integer, Float e Boolean em String
2.2) PropertyUtils para cópia de propriedade:
1) Diferenças do BeanUtils:
- PropertyUtils suporta apenas cópia de propriedades entre dois beans, não Map to Bean
- Quando PropertyUtils copia propriedades entre dois beans, ele deve garantir que os nomes e tipos sejam iguais , caso contrário, um erro será relatado. Quando BeanUtils copia propriedades, os nomes são os mesmos e os tipos podem ser convertidos.
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); //报错
Mensagem de erro:
2) Descrição:
- PropertyUtils não oferece suporte à conversão de tipo.
- Para valores nulos, PropertyUtils também é nulo após a cópia
3. Conversão de tipo personalizado ConvertUtils
1)Conversor de data:
DateConverter herda DateTimeConverter, que é a conversão do tipo de hora que vem com o pacote beanutils, incluindo:
exemplo
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) Personalizar:
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
Nota: Para setProperty, se houver um tipo de hora, será necessário um conversor personalizado.