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 true是 false 否
*/
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;
}
}