美文网首页springboot
工具类|将Entity对象转为Vo/Bo对象,并指定字段绑定

工具类|将Entity对象转为Vo/Bo对象,并指定字段绑定

作者: 你家门口的两朵云 | 来源:发表于2021-08-26 10:41 被阅读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);
        }
    }
    
    

    相关文章

      网友评论

        本文标题:工具类|将Entity对象转为Vo/Bo对象,并指定字段绑定

        本文链接:https://www.haomeiwen.com/subject/vlgyiltx.html