工具类|将Entity对象转为Vo/Bo对象,并指定字段绑定
实体类: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.*;/*** @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 XMLGregorianCalendarif (!(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 XMLGregorianCalendarif (!(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);}
}