喜欢与改变

导航

tool 不同对象中 类型与属性名的属性 进行数据转换

  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;
}
}

posted on 2019-08-12 20:58  喜欢与改变  阅读(355)  评论(0编辑  收藏  举报