springboot

工具类|将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);
    }
}

上一篇下一篇

猜你喜欢

热点阅读