zoukankan      html  css  js  c++  java
  • 不同对象中 类型与属性名的属性 进行数据转换

      1 package com.xnky.pams.common.utils;
      2 
      3 import org.slf4j.Logger;
      4 import org.slf4j.LoggerFactory;
      5 
      6 import java.lang.reflect.Field;
      7 import java.lang.reflect.Method;
      8 import java.lang.reflect.ParameterizedType;
      9 import java.lang.reflect.Type;
     10 import java.math.BigDecimal;
     11 import java.util.ArrayList;
     12 import java.util.Collection;
     13 import java.util.Date;
     14 import java.util.HashMap;
     15 import java.util.HashSet;
     16 import java.util.List;
     17 import java.util.Map;
     18 import java.util.Set;
     19 import java.util.concurrent.ConcurrentHashMap;
     20 
     21 
     22 /**
     23  * 把对象A中属性的值传给对象B相同类型的属性。
     24  *
     25  * @author Feng Yongkang, 2019/8/6
     26  * @version v1.0
     27  */
     28 public class PojoConvertUtil {
     29     private static Logger logger = LoggerFactory.getLogger(PojoConvertUtil.class);
     30     /**
     31      * 变量缓存.
     32      */
     33     private static final Map<String, Map<String, Field>> CACHE_FIELDS = new ConcurrentHashMap<>();
     34     private static final Set<Class> BASIC_CLASS = new HashSet<>();
     35 
     36     static {
     37         BASIC_CLASS.add(Integer.class);
     38         BASIC_CLASS.add(Character.class);
     39         BASIC_CLASS.add(Byte.class);
     40         BASIC_CLASS.add(Float.class);
     41         BASIC_CLASS.add(Double.class);
     42         BASIC_CLASS.add(Boolean.class);
     43         BASIC_CLASS.add(Long.class);
     44         BASIC_CLASS.add(Short.class);
     45         BASIC_CLASS.add(String.class);
     46         BASIC_CLASS.add(BigDecimal.class);
     47     }
     48 
     49     private PojoConvertUtil() {
     50     }
     51 
     52     /**
     53      * 将具有相同属性的类型进行转换.
     54      *
     55      * @param orig        原始对象
     56      * @param targetClass 目标对象
     57      * @param <T>         泛型
     58      * @return 泛型
     59      */
     60     public static <T> T convertPojo(Object orig, Class<T> targetClass) {
     61         try {
     62             T target = targetClass.newInstance();
     63             /** 获取源对象的所有变量 */
     64             Field[] fields = orig.getClass().getDeclaredFields();
     65             for (Field field : fields) {
     66                 if (isStatic(field)) {
     67                     continue;
     68                 }
     69                 /** 获取目标对象与原对象相同的字段 */
     70                 Field targetField = getTargetField(targetClass, field.getName());
     71                 if (targetField == null) {
     72                     continue;
     73                 }
     74                 /*获取原对象中字段的值*/
     75                 Object value = getFiledValue(field, orig);
     76                 if (value == null) {
     77                     continue;
     78                 }
     79                 Class type1 = field.getType();
     80                 Class type2 = targetField.getType();
     81                 //两个类型是否相同
     82                 boolean sameType = type1.equals(type2);
     83                 if (isBasicType(type1)) {
     84                     if (sameType) {
     85                         setFieldValue(targetField, target, value);
     86                     }
     87                 } else if (value instanceof Map && Map.class.isAssignableFrom(type2)) {//对map
     88                     setMap((Map) value, field, targetField, target);
     89                 } else if (value instanceof Set && Set.class.isAssignableFrom(type2)) {//对set
     90                     setCollection((Collection) value, field, targetField, target);
     91                 } else if (value instanceof List && List.class.isAssignableFrom(type2)) {//对list
     92                     setCollection((Collection) value, field, targetField, target);
     93                 } else if (value instanceof Enum && Enum.class.isAssignableFrom(type2)) {//对enum
     94                     setEnum((Enum) value, field, targetField, target);
     95                 } else if (value instanceof java.util.Date
     96                         && java.util.Date.class.isAssignableFrom(type2)) {//对日期类型,不处理如joda包之类的扩展时间,不处理calendar
     97                     setDate((Date) value, targetField, type2, target, sameType);
     98                 }
     99             }
    100             return target;
    101         } catch (Throwable t) {
    102             logger.error("转换失败:" + t.getMessage());
    103             throw new RuntimeException(t.getMessage());
    104         }
    105     }
    106 
    107     /**
    108      * 获取字段值.
    109      *
    110      * @param field
    111      * @param obj
    112      * @return
    113      */
    114     private static Object getFiledValue(Field field, Object obj) throws IllegalAccessException {
    115         //获取原有的访问权限
    116         boolean access = field.isAccessible();
    117         try {
    118             //设置可访问的权限
    119             field.setAccessible(true);
    120             return field.get(obj);
    121         } finally {
    122             //恢复访问权限
    123             field.setAccessible(access);
    124         }
    125     }
    126 
    127     /**
    128      * 设置属性值.
    129      * 之所以这里用对象 对象的方法  和要传入的值 ,前两者都是一个对象里面的内容,对于这个方法来说,对象类型是不确定的。
    130      *
    131      * @param field
    132      * @param obj
    133      * @param value
    134      * @throws IllegalAccessException
    135      */
    136     private static void setFieldValue(Field field, Object obj, Object value) throws IllegalAccessException {
    137         //获取原有的访问权限
    138         boolean access = field.isAccessible();
    139         try {
    140             //设置可访问的权限
    141             field.setAccessible(true);
    142             field.set(obj, value);
    143         } finally {
    144             //恢复访问权限
    145             field.setAccessible(access);
    146         }
    147     }
    148 
    149     /**
    150      * 转换list.
    151      *
    152      * @param orig        原始list
    153      * @param targetClass 目标list
    154      * @param <T>         泛型
    155      * @return 泛型
    156      */
    157     public static <T> List<T> convertPojos(List orig, Class<T> targetClass) {
    158         List<T> list = new ArrayList<>(orig.size());
    159         for (Object object : orig) {
    160             list.add(convertPojo(object, targetClass));
    161         }
    162         return list;
    163     }
    164 
    165     /**
    166      * 设置Map.
    167      *
    168      * @param value        要转换的数据
    169      * @param origField    原对象的字段
    170      * @param targetField  目标对象的字段
    171      * @param targetObject 目标对象
    172      * @param <T>          泛型
    173      */
    174     private static <T> void setMap(Map value, Field origField, Field targetField
    175             , T targetObject) throws IllegalAccessException, InstantiationException {
    176         Type origType = origField.getGenericType();
    177         Type targetType = targetField.getGenericType();
    178         if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型
    179             ParameterizedType origParameterizedType = (ParameterizedType) origType;
    180             Type[] origTypes = origParameterizedType.getActualTypeArguments();
    181             ParameterizedType targetParameterizedType = (ParameterizedType) targetType;
    182             Type[] targetTypes = targetParameterizedType.getActualTypeArguments();
    183             if (origTypes != null && origTypes.length == 2 && targetTypes != null && targetTypes.length == 2) {
    184                 Class clazz = (Class) origTypes[1];
    185                 if (!isBasicType(clazz) && !clazz.equals(targetTypes[1])) {//如果不是基本类型并且泛型不一致,则需要继续转换
    186                     Set<Map.Entry> entries = value.entrySet();
    187                     Map targetMap = value.getClass().newInstance();
    188                     for (Map.Entry entry : entries) {
    189                         targetMap.put(entry.getKey(), convertPojo(entry.getValue(), (Class) targetTypes[1]));
    190                     }
    191                     setFieldValue(targetField, targetObject, targetMap);
    192                     return;
    193                 }
    194             }
    195         }
    196         setFieldValue(targetField, targetObject, value);
    197     }
    198 
    199     /**
    200      * 设置集合.
    201      *
    202      * @param value
    203      * @param origField
    204      * @param targetField
    205      * @param targetObject
    206      * @param <T>
    207      * @throws IllegalAccessException
    208      * @throws InstantiationException
    209      */
    210     private static <T> void setCollection(Collection value, Field origField, Field targetField
    211             , T targetObject) throws IllegalAccessException, InstantiationException {
    212         Type origType = origField.getGenericType();
    213         Type targetType = targetField.getGenericType();
    214         if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型
    215             ParameterizedType origParameterizedType = (ParameterizedType) origType;
    216             Type[] origTypes = origParameterizedType.getActualTypeArguments();
    217             ParameterizedType targetParameterizedType = (ParameterizedType) targetType;
    218             Type[] targetTypes = targetParameterizedType.getActualTypeArguments();
    219             //正常泛型,查看第二个泛型是否不为基本类型
    220             if (origTypes != null && origTypes.length == 1 && targetTypes != null && targetTypes.length == 1) {
    221                 Class clazz = (Class) origTypes[0];
    222                 if (!isBasicType(clazz) && !clazz.equals(targetTypes[0])) {//如果不是基本类型并且泛型不一致,则需要继续转换
    223                     Collection collection = value.getClass().newInstance();
    224                     for (Object obj : value) {
    225                         collection.add(convertPojo(obj, (Class) targetTypes[0]));
    226                     }
    227                     setFieldValue(targetField, targetObject, collection);
    228                     return;
    229                 }
    230             }
    231         }
    232         setFieldValue(targetField, targetObject, value);
    233     }
    234 
    235     /**
    236      * 设置枚举类型.
    237      *
    238      * @param value
    239      * @param origField
    240      * @param targetField
    241      * @param targetObject
    242      * @param <T>
    243      */
    244     private static <T> void setEnum(Enum value, Field origField, Field targetField, T targetObject) throws Exception {
    245         if (origField.equals(targetField)) {
    246             setFieldValue(targetField, targetObject, value);
    247         } else {
    248             //枚举类型都具有一个static修饰的valueOf方法
    249             Method method = targetField.getType().getMethod("valueOf", String.class);
    250             setFieldValue(targetField, targetObject, method.invoke(null, value.toString()));
    251         }
    252     }
    253 
    254     /**
    255      * 设置日期类型.
    256      *
    257      * @param value
    258      * @param targetField
    259      * @param targetFieldType
    260      * @param targetObject
    261      * @param <T>
    262      */
    263     private static <T> void setDate(Date value, Field targetField, Class targetFieldType
    264             , T targetObject, boolean sameType) throws IllegalAccessException {
    265         Date date = null;
    266         if (sameType) {
    267             date = value;
    268         } else if (targetFieldType.equals(java.sql.Date.class)) {
    269             date = new java.sql.Date(value.getTime());
    270         } else if (targetFieldType.equals(java.util.Date.class)) {
    271             date = new Date(value.getTime());
    272         } else if (targetFieldType.equals(java.sql.Timestamp.class)) {
    273             date = new java.sql.Timestamp(value.getTime());
    274         }
    275         setFieldValue(targetField, targetObject, date);
    276     }
    277 
    278     /**
    279      * 获取适配方法.
    280      * 把目标类全部字段放到map中,并把这把map放入CACHE_FIELDS。
    281      *
    282      * @param clazz     类型
    283      * @param fieldName 字段名
    284      * @return 目标类型中与原对象属性名一致的字段
    285      */
    286     public static Field getTargetField(Class clazz, String fieldName) {
    287         String classKey = clazz.getName();
    288         //如果下次再来查找同一个类的所有字段,可以在CACHE_FIELDS找之前存过的包含该类型多有字段的map
    289         Map<String, Field> fieldMap = CACHE_FIELDS.get(classKey);
    290         if (fieldMap == null) {
    291             fieldMap = new HashMap<>();
    292             Field[] fields = clazz.getDeclaredFields();
    293             for (Field field : fields) {
    294                 if (isStatic(field)) {
    295                     continue;
    296                 }
    297                 fieldMap.put(field.getName(), field);
    298             }
    299             CACHE_FIELDS.put(classKey, fieldMap);
    300         }
    301         return fieldMap.get(fieldName);
    302     }
    303 
    304     /**
    305      * 判断是否为基础类型.
    306      *
    307      * @param clazz 类型
    308      * @return true是  false 否
    309      */
    310     public static boolean isBasicType(Class clazz) {
    311         return clazz.isPrimitive() || BASIC_CLASS.contains(clazz);
    312     }
    313 
    314     /**
    315      * 判断变量是否有静态修饰符static.
    316      *
    317      * @param field 要判断的字段
    318      * @return 是否有静态修饰
    319      */
    320     public static boolean isStatic(Field field) {
    321         return (8 & field.getModifiers()) == 8;
    322     }
    323 }
    /*
    * Copyright (c) Travelsky Corp.
    * All Rights Reserved.
    */
    package com.xnky.pams.common.utils;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;


    /**
    * PojoConvertUtil.
    * 把对象A中属性的值传给对象B相同类型的属性。
    *
    * @author Feng Yongkang, 2019/8/6
    * @version v1.0
    */
    public class PojoConvertUtil {
    private static Logger logger = LoggerFactory.getLogger(PojoConvertUtil.class);
    /**
    * 变量缓存.
    */
    private static final Map<String, Map<String, Field>> CACHE_FIELDS = new ConcurrentHashMap<>();
    private static final Set<Class> BASIC_CLASS = new HashSet<>();

    static {
    BASIC_CLASS.add(Integer.class);
    BASIC_CLASS.add(Character.class);
    BASIC_CLASS.add(Byte.class);
    BASIC_CLASS.add(Float.class);
    BASIC_CLASS.add(Double.class);
    BASIC_CLASS.add(Boolean.class);
    BASIC_CLASS.add(Long.class);
    BASIC_CLASS.add(Short.class);
    BASIC_CLASS.add(String.class);
    BASIC_CLASS.add(BigDecimal.class);
    }

    private PojoConvertUtil() {
    }

    /**
    * 将具有相同属性的类型进行转换.
    *
    * @param orig 原始对象
    * @param targetClass 目标对象
    * @param <T> 泛型
    * @return 泛型
    */
    public static <T> T convertPojo(Object orig, Class<T> targetClass) {
    try {
    T target = targetClass.newInstance();
    /** 获取源对象的所有变量 */
    Field[] fields = orig.getClass().getDeclaredFields();
    for (Field field : fields) {
    if (isStatic(field)) {
    continue;
    }
    /** 获取目标对象与原对象相同的字段 */
    Field targetField = getTargetField(targetClass, field.getName());
    if (targetField == null) {
    continue;
    }
    /*获取原对象中字段的值*/
    Object value = getFiledValue(field, orig);
    if (value == null) {
    continue;
    }
    Class type1 = field.getType();
    Class type2 = targetField.getType();
    //两个类型是否相同
    boolean sameType = type1.equals(type2);
    if (isBasicType(type1)) {
    if (sameType) {
    setFieldValue(targetField, target, value);
    }
    } else if (value instanceof Map && Map.class.isAssignableFrom(type2)) {//map
    setMap((Map) value, field, targetField, target);
    } else if (value instanceof Set && Set.class.isAssignableFrom(type2)) {//set
    setCollection((Collection) value, field, targetField, target);
    } else if (value instanceof List && List.class.isAssignableFrom(type2)) {//list
    setCollection((Collection) value, field, targetField, target);
    } else if (value instanceof Enum && Enum.class.isAssignableFrom(type2)) {//enum
    setEnum((Enum) value, field, targetField, target);
    } else if (value instanceof java.util.Date
    && java.util.Date.class.isAssignableFrom(type2)) {//对日期类型,不处理如joda包之类的扩展时间,不处理calendar
    setDate((Date) value, targetField, type2, target, sameType);
    }
    }
    return target;
    } catch (Throwable t) {
    logger.error("转换失败:" + t.getMessage());
    throw new RuntimeException(t.getMessage());
    }
    }

    /**
    * 获取字段值.
    *
    * @param field
    * @param obj
    * @return
    */
    private static Object getFiledValue(Field field, Object obj) throws IllegalAccessException {
    //获取原有的访问权限
    boolean access = field.isAccessible();
    try {
    //设置可访问的权限
    field.setAccessible(true);
    return field.get(obj);
    } finally {
    //恢复访问权限
    field.setAccessible(access);
    }
    }

    /**
    * 设置属性值.
    * 之所以这里用对象 对象的方法 和要传入的值 ,前两者都是一个对象里面的内容,对于这个方法来说,对象类型是不确定的。
    *
    * @param field
    * @param obj
    * @param value
    * @throws IllegalAccessException
    */
    private static void setFieldValue(Field field, Object obj, Object value) throws IllegalAccessException {
    //获取原有的访问权限
    boolean access = field.isAccessible();
    try {
    //设置可访问的权限
    field.setAccessible(true);
    field.set(obj, value);
    } finally {
    //恢复访问权限
    field.setAccessible(access);
    }
    }

    /**
    * 转换list.
    *
    * @param orig 原始list
    * @param targetClass 目标list
    * @param <T> 泛型
    * @return 泛型
    */
    public static <T> List<T> convertPojos(List orig, Class<T> targetClass) {
    List<T> list = new ArrayList<>(orig.size());
    for (Object object : orig) {
    list.add(convertPojo(object, targetClass));
    }
    return list;
    }

    /**
    * 设置Map.
    *
    * @param value 要转换的数据
    * @param origField 原对象的字段
    * @param targetField 目标对象的字段
    * @param targetObject 目标对象
    * @param <T> 泛型
    */
    private static <T> void setMap(Map value, Field origField, Field targetField
    , T targetObject) throws IllegalAccessException, InstantiationException {
    Type origType = origField.getGenericType();
    Type targetType = targetField.getGenericType();
    if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型
    ParameterizedType origParameterizedType = (ParameterizedType) origType;
    Type[] origTypes = origParameterizedType.getActualTypeArguments();
    ParameterizedType targetParameterizedType = (ParameterizedType) targetType;
    Type[] targetTypes = targetParameterizedType.getActualTypeArguments();
    if (origTypes != null && origTypes.length == 2 && targetTypes != null && targetTypes.length == 2) {
    Class clazz = (Class) origTypes[1];
    if (!isBasicType(clazz) && !clazz.equals(targetTypes[1])) {//如果不是基本类型并且泛型不一致,则需要继续转换
    Set<Map.Entry> entries = value.entrySet();
    Map targetMap = value.getClass().newInstance();
    for (Map.Entry entry : entries) {
    targetMap.put(entry.getKey(), convertPojo(entry.getValue(), (Class) targetTypes[1]));
    }
    setFieldValue(targetField, targetObject, targetMap);
    return;
    }
    }
    }
    setFieldValue(targetField, targetObject, value);
    }

    /**
    * 设置集合.
    *
    * @param value
    * @param origField
    * @param targetField
    * @param targetObject
    * @param <T>
    * @throws IllegalAccessException
    * @throws InstantiationException
    */
    private static <T> void setCollection(Collection value, Field origField, Field targetField
    , T targetObject) throws IllegalAccessException, InstantiationException {
    Type origType = origField.getGenericType();
    Type targetType = targetField.getGenericType();
    if (origType instanceof ParameterizedType && targetType instanceof ParameterizedType) {//泛型类型
    ParameterizedType origParameterizedType = (ParameterizedType) origType;
    Type[] origTypes = origParameterizedType.getActualTypeArguments();
    ParameterizedType targetParameterizedType = (ParameterizedType) targetType;
    Type[] targetTypes = targetParameterizedType.getActualTypeArguments();
    //正常泛型,查看第二个泛型是否不为基本类型
    if (origTypes != null && origTypes.length == 1 && targetTypes != null && targetTypes.length == 1) {
    Class clazz = (Class) origTypes[0];
    if (!isBasicType(clazz) && !clazz.equals(targetTypes[0])) {//如果不是基本类型并且泛型不一致,则需要继续转换
    Collection collection = value.getClass().newInstance();
    for (Object obj : value) {
    collection.add(convertPojo(obj, (Class) targetTypes[0]));
    }
    setFieldValue(targetField, targetObject, collection);
    return;
    }
    }
    }
    setFieldValue(targetField, targetObject, value);
    }

    /**
    * 设置枚举类型.
    *
    * @param value
    * @param origField
    * @param targetField
    * @param targetObject
    * @param <T>
    */
    private static <T> void setEnum(Enum value, Field origField, Field targetField, T targetObject) throws Exception {
    if (origField.equals(targetField)) {
    setFieldValue(targetField, targetObject, value);
    } else {
    //枚举类型都具有一个static修饰的valueOf方法
    Method method = targetField.getType().getMethod("valueOf", String.class);
    setFieldValue(targetField, targetObject, method.invoke(null, value.toString()));
    }
    }

    /**
    * 设置日期类型.
    *
    * @param value
    * @param targetField
    * @param targetFieldType
    * @param targetObject
    * @param <T>
    */
    private static <T> void setDate(Date value, Field targetField, Class targetFieldType
    , T targetObject, boolean sameType) throws IllegalAccessException {
    Date date = null;
    if (sameType) {
    date = value;
    } else if (targetFieldType.equals(java.sql.Date.class)) {
    date = new java.sql.Date(value.getTime());
    } else if (targetFieldType.equals(java.util.Date.class)) {
    date = new Date(value.getTime());
    } else if (targetFieldType.equals(java.sql.Timestamp.class)) {
    date = new java.sql.Timestamp(value.getTime());
    }
    setFieldValue(targetField, targetObject, date);
    }

    /**
    * 获取适配方法.
    * 把目标类全部字段放到map中,并把这把map放入CACHE_FIELDS
    *
    * @param clazz 类型
    * @param fieldName 字段名
    * @return 目标类型中与原对象属性名一致的字段
    */
    public static Field getTargetField(Class clazz, String fieldName) {
    String classKey = clazz.getName();
    //如果下次再来查找同一个类的所有字段,可以在CACHE_FIELDS找之前存过的包含该类型多有字段的map
    Map<String, Field> fieldMap = CACHE_FIELDS.get(classKey);
    if (fieldMap == null) {
    fieldMap = new HashMap<>();
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
    if (isStatic(field)) {
    continue;
    }
    fieldMap.put(field.getName(), field);
    }
    CACHE_FIELDS.put(classKey, fieldMap);
    }
    return fieldMap.get(fieldName);
    }

    /**
    * 判断是否为基础类型.
    *
    * @param clazz 类型
    * @return truefalse
    */
    public static boolean isBasicType(Class clazz) {
    return clazz.isPrimitive() || BASIC_CLASS.contains(clazz);
    }

    /**
    * 判断变量是否有静态修饰符static.
    *
    * @param field 要判断的字段
    * @return 是否有静态修饰
    */
    public static boolean isStatic(Field field) {
    return (8 & field.getModifiers()) == 8;
    }
    }
  • 相关阅读:
    ubuntu 安装 systemback
    嵌入式gdb远程调试
    pecl 安装 phpredis
    Linux服务器内存池技术是如何实现的
    统一登录的几种常用设计模式
    数据库并发控制
    抽取一部分服务端做BFF(Backend For Frontend服务于前端的后端)
    干货 | 质量保障新手段,携程回归测试平台实践 原创 Sedro 携程技术 2021-01-21
    服务端绘图
    中间件技术在百度云原生测试中的应用实践 原创 路由器 百度智能化测试 今天
  • 原文地址:https://www.cnblogs.com/xiaoeyu/p/11342529.html
Copyright © 2011-2022 走看看