工具类|将Entity对象转为Vo/Bo对象,并指定字段绑定
2021-08-26 本文已影响0人
你家门口的两朵云
实体类:People和Student,Student的三个字段和People意义一样,但是字段名不完全一样,要实现对象拷贝可使用如下工具类,用到了反射。
People.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
private Integer id;
private String name;
private Integer age;
private String sex;
private String classNum;
private String health;
private String height;
private String weight;
}
Student.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Integer stuId;
private String stuName;
private Integer age;
}
CommonBeanUtils.java
package cn.yto.hbd.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.*;
import org.springframework.util.*;
import javax.xml.datatype.XMLGregorianCalendar;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.*;
/**
* @author: 闵渭凯 gitee:https://gitee.com/mwk719/microservice_practice/blob/master/microservice-tool
* @ReWroteBy: Tara.Li(李春侣)
* @date: 2021-08-25 10:41:34
* @Description: Bean对象转化Vo对象工具类
*/
@Slf4j
public abstract class CommonBeanUtils extends org.springframework.beans.BeanUtils {
/**
* 对象赋值:将source对象与target对象按照匹配的字段一对一复制;
*
* @param source 源Entity
* @param target 目标Vo对象
* @throws BeansException
*/
public static void copyProps(Object source, Object target) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
for (PropertyDescriptor targetPd : targetPds) {
if (targetPd.getWriteMethod() != null) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null && sourcePd.getReadMethod() != null) {
try {
Method readMethod = sourcePd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
// 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等
if (value != null) {
Method writeMethod = targetPd.getWriteMethod();
Type targetParameterType = writeMethod.getGenericParameterTypes()[0];
// 特殊类型不再执行copy XMLGregorianCalendar
if (!(targetParameterType.equals(XMLGregorianCalendar.class))) {
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
}
}
} catch (Throwable ex) {
log.error(ex.getMessage());
throw new FatalBeanException("Could not copy properties from source to target", ex);
}
}
}
}
}
/**
* 对象赋值:将source对象与target按照匹配的字段一一复制;
*
* @param source 源Entity
* @param target 目标Vo对象
* @param props 对应字段,0或多个
* @throws BeansException
*/
public static void copyProps(Object source, Object target, final String... props) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
for (PropertyDescriptor targetPd : targetPds) {
if (targetPd.getWriteMethod() != null) {
String prop_1;
String prop_2;
String targetPdNameTemp = "";
for (int i = 0; i < props.length; i++) {
String[] params = props[i].split("=");
prop_1 = params[0];
prop_2 = params[1];
if (Objects.equals(targetPd.getName(), prop_1)) {
targetPdNameTemp = prop_2;
break;
}
if (Objects.equals(targetPd.getName(), prop_2)) {
targetPdNameTemp = prop_1;
break;
}
}
//1.将字段转换实现字段绑定;
PropertyDescriptor sourcePd;
//指定了的字段绑定的按绑定字段赋值
if (!"".equals(targetPdNameTemp) && null != targetPdNameTemp) {
sourcePd = getPropertyDescriptor(source.getClass(), targetPdNameTemp);
} else {
//没有指定字段的自动匹配字段名;
sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
}
if (sourcePd != null && sourcePd.getReadMethod() != null) {
try {
Method readMethod = sourcePd.getReadMethod();
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
// 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等
if (value != null) {
Method writeMethod = targetPd.getWriteMethod();
Type targetParameterType = writeMethod.getGenericParameterTypes()[0];
// 特殊类型不再执行copy XMLGregorianCalendar
if (!(targetParameterType.equals(XMLGregorianCalendar.class))) {
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
}
}
} catch (Throwable ex) {
log.error(ex.getMessage());
throw new FatalBeanException("Could not copy properties from source to target", ex);
}
}
}
}
}
/**
* 集合对象转化赋值:如List<People> 转为List<Student>(实体Student的字段是People字段的子集)
*
* @param sources 源集合对象
* @param voClass vo类型
* @param <T>
* @return
*/
public static <T> List<T> copyListProps(List<? extends Object> sources, final Class<T> voClass) {
Assert.isTrue(!CollectionUtils.isEmpty(sources), "Source must not be null");
List<T> targets = new ArrayList<>();
sources.forEach(source -> {
try {
T target = voClass.newInstance();
copyProperties(source, target);
targets.add(target);
} catch (InstantiationException | IllegalAccessException e) {
log.error(e.getMessage());
}
});
return targets;
}
/**
* 集合对象转化赋值:如List<People> 转为List<Student>(实体Student的字段是People字段的子集)
*
* @param sources 源Entity集合对象
* @param voClass vo类型.class
* @param <T>
* @return
*/
public static <T> List<T> copyListProps(List<? extends Object> sources, final Class<T> voClass, final String... props) {
Assert.isTrue(!CollectionUtils.isEmpty(sources), "Source must not be null");
List<T> targets = new ArrayList<>();
sources.forEach(source -> {
try {
T target = voClass.newInstance();
//调用带参数绑定的拷贝方法;
copyProps(source, target, props);
targets.add(target);
} catch (InstantiationException | IllegalAccessException e) {
log.error(e.getMessage());
}
});
return targets;
}
}
测试类:
package cn.yto.hbd.utils;
public class Test0 {
public static void main(String[] args) {
People people = new People();
Student student = new Student();
people.setId(4);
people.setAge(10);
people.setName("张三 ");
people.setClassNum("3");
people.setHealth("健康000");
people.setHeight("180cm");
people.setWeight("60kg");
people.setSex("男");
CommonBeanUtils.copyProps(people,student,"stuId=id","name=stuName");
System.out.println(people);
System.out.println(student);
}
}
运行结果:
运行结果
(简略略)下面这个工具类也可实现,是我好基友写的,原理通俗易懂
package cn.yto.hbd.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class BeanConvertUtils {
/**
* 普通转换
* @param source 源
* @param targetClass
* @param <T>
* @return
*/
public static <T> T copy(Object source,Class<T> targetClass){
return copy(source ,targetClass,null);
}
/**
* 普通转换
* @param sourceObj 源
* @param targetObj 目标
* @param <T>
* @return
*/
public static <T> T copy(Object sourceObj,T targetObj){
return copy(sourceObj ,targetObj,null);
}
/**
* 普通转换
* @param source 源
* @param targetClass
* @param keyMap 源字段=目标字段
* @return
*/
public static <T> T copy(Object source,Class<T> targetClass,String ...keyMap){
T targetObj= null;
try {
targetObj = targetClass.getConstructor(null).newInstance(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
return copy(source,targetObj,keyMap);
}
/**
* 普通转换
* @param sourceObj 源
* @param targetObj 目标
* @param keyMap 源字段=目标字段
* @return
*/
public static <T> T copy(Object sourceObj,T targetObj,String ...keyMap){
Class<?> sourceClass = sourceObj.getClass();
Class<?> targetClass = targetObj.getClass();
Map<String, String> keyMaps = new HashMap<>();
if (keyMap!=null&&keyMap.length>0){
for (String keyItem : keyMap) {
String[] split = keyItem.split("=");
keyMaps.put(split[0],split[1]);
}
}
Field[] sourceFieldFields = sourceObj.getClass().getDeclaredFields();
for (Field sourceField : sourceFieldFields) {
String sourceFieldName = sourceField.getName();
String targetFieldName=keyMaps.getOrDefault(sourceFieldName,sourceFieldName);
String sourceMethodName = getGetMethodName(sourceFieldName);
String targetMethodName = getSetMethodName(targetFieldName);
try {
Method sourceGetMethod = sourceClass.getDeclaredMethod(sourceMethodName);
Method targetSetField = targetClass.getDeclaredMethod(targetMethodName,sourceField.getType());
Object value = sourceGetMethod.invoke(sourceObj);
targetSetField.invoke(targetObj,value);
} catch (Exception e) {
//找不到字段
}
}
return targetObj;
}
/**
* 首字母大写
* @param str
* @return
*/
private static String strFirstUpper(String str){
return str.substring(0,1).toUpperCase()+str.substring(1);
}
/**
* 获取get方法名
* @param fieldName
* @return
*/
private static String getGetMethodName(String fieldName){
return "get"+strFirstUpper(fieldName);
}
private static String getSetMethodName(String fieldName){
return "set"+strFirstUpper(fieldName);
}
}