package com.vci.starter.web.util;
|
|
import com.vci.starter.web.toolmodel.DateConverter;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.cglib.beans.BeanCopier;
|
import org.springframework.cglib.core.Converter;
|
import org.springframework.util.CollectionUtils;
|
|
import java.lang.reflect.Field;
|
import java.util.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentMap;
|
|
/**
|
* 业务类型专用的拷贝工具,这个是浅拷贝,
|
* @author weidy
|
* @date 2022-1-18
|
*/
|
public class BeanUtilForVCI {
|
|
/**
|
* 日志
|
*/
|
private static Logger logger = LoggerFactory.getLogger(BeanUtilForVCI.class);
|
|
/**
|
* 存放拷贝对象的缓存
|
*/
|
private static final ConcurrentMap<String, BeanCopier> beanCopierMap = new ConcurrentHashMap<>();
|
|
/**
|
* 拷贝数据
|
* 大小写可以忽略
|
* 下划线 _ 被忽略
|
* null和空字符串的也会被覆盖
|
* @param source 来源属性
|
* @param target 目标属性
|
*/
|
public static void copyPropertiesIgnoreCase(Object source, Object target) {
|
copyPropertiesIgnoreCase(source,target,false);
|
}
|
|
/**
|
* 拷贝属性
|
* @param source 源对象
|
* @param target 目标对象
|
* @param fieldMap 属性的映射
|
*/
|
public static void copyPropertiesIgnoreCase(Object source,Object target,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap){
|
copyPropertiesIgnoreCase(source,target,false,fieldMap);
|
}
|
|
/**
|
* 拷贝数据
|
* 大小写可以忽略
|
* 下划线 _ 被忽略
|
* @param source 来源属性
|
* @param target 目标属性
|
* @param ignoreNull 是否忽略控制
|
*/
|
public static void copyPropertiesIgnoreCase(Object source,Object target,boolean ignoreNull){
|
copyPropertiesIgnoreCase(source, target, ignoreNull,null);
|
}
|
|
/**
|
* 拷贝本体的属性内容
|
* @param source 来源对象
|
* @param target 目标对象
|
*/
|
public static void copyDeclaredIgnoreCase(Object source,Object target){
|
copyDeclaredIgnoreCase(source,target,false);
|
}
|
|
/**
|
* 拷贝本体的属性内容
|
* @param source 来源对象
|
* @param target 目标对象
|
* @param ignoreNull 忽略空值的属性
|
*/
|
public static void copyDeclaredIgnoreCase(Object source,Object target,boolean ignoreNull){
|
copyDeclaredIgnoreCase(source,target,ignoreNull,null);
|
}
|
|
/**
|
* 拷贝本体的属性内容
|
* @param source 来源对象
|
* @param target 目标对象
|
* @param ignoreNull 忽略空值的属性
|
* @param fieldMap 字段的映射
|
*/
|
public static void copyDeclaredIgnoreCase(Object source,Object target,boolean ignoreNull,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap){
|
copyDeclaredIgnoreCase(source,target,ignoreNull,fieldMap,null);
|
}
|
|
/**
|
* 拷贝本体的属性内容
|
* @param source 来源对象
|
* @param target 目标对象
|
* @param ignoreNull 忽略空值的属性
|
* @param fieldMap 字段的映射
|
* @param ignoreField 忽略字段
|
*/
|
public static void copyDeclaredIgnoreCase(Object source,Object target,boolean ignoreNull,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap,Collection<String> ignoreField){
|
Map<String, Field> sourceMap = CacheFieldMap.getDeclaredFieldMap(source.getClass());
|
Map<String, Field> targetMap = CacheFieldMap.getDeclaredFieldMap(target.getClass());
|
copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,ignoreField,sourceMap,targetMap);
|
}
|
/**
|
* 拷贝数据
|
* 大小写可以忽略
|
* 下划线 _ 被忽略
|
* @param source 来源属性
|
* @param target 目标属性
|
* @param ignoreNull 是否忽略控制
|
*/
|
public static void copyPropertiesIgnoreCase(Object source, Object target, boolean ignoreNull, Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap, Collection<String> ignoreField) {
|
Map<String, Field> sourceMap = CacheFieldMap.getFieldMap(source.getClass());
|
Map<String, Field> targetMap = CacheFieldMap.getFieldMap(target.getClass());
|
copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,ignoreField,sourceMap,targetMap);
|
}
|
|
/**
|
* 拷贝数据
|
* 大小写可以忽略
|
* 下划线 _ 被忽略
|
* @param source 来源属性
|
* @param target 目标属性
|
* @param ignoreNull 是否忽略控制
|
*/
|
public static void copyPropertiesIgnoreCase(Object source, Object target, boolean ignoreNull,
|
Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap, Collection<String> ignoreField,
|
Map<String, Field> sourceMap,Map<String, Field> targetMap ) {
|
if(fieldMap == null){
|
fieldMap = new HashMap<>();
|
}
|
Map<String, String> finalFieldMap = fieldMap;
|
targetMap.values().forEach((it) -> {
|
boolean not = false;
|
if(ignoreField!=null && ignoreField.contains(it.getName())){
|
not = true;
|
}
|
if(!not) {
|
String itFieldName = it.getName().toLowerCase().replace("_", "");
|
itFieldName = finalFieldMap.getOrDefault(itFieldName, itFieldName);
|
Field field = sourceMap.getOrDefault(itFieldName, null);
|
if (field != null) {
|
it.setAccessible(true);
|
field.setAccessible(true);
|
try {
|
//忽略null和空字符串
|
//处理boolean和String
|
String sourceClassName = field.getClass().getName();
|
String targetClassName = it.getClass().getName();
|
if (((sourceClassName.equalsIgnoreCase(Boolean.class.getName())
|
|| sourceClassName.equalsIgnoreCase(boolean.class.getName())
|
) && targetClassName.equalsIgnoreCase(String.class.getName()))
|
|| ((targetClassName.equalsIgnoreCase(Boolean.class.getName())
|
|| targetClassName.equalsIgnoreCase(boolean.class.getName()))
|
&& sourceClassName.equalsIgnoreCase(String.class.getName()))) {
|
if (targetClassName.equalsIgnoreCase(String.class.getName())) {
|
it.set(target, String.valueOf((Boolean) field.get(source)));
|
} else {
|
it.set(target, Boolean.valueOf((String) field.get(source)));
|
}
|
} else {
|
if (!ignoreNull) {
|
it.set(target, field.get(source));
|
} else {
|
//需要判断是否为空
|
Object sourceValue = field.get(source);
|
if (sourceValue != null && StringUtils.isNotBlank(sourceValue.toString())) {
|
it.set(target, sourceValue);
|
}
|
}
|
}
|
} catch (IllegalAccessException e) {
|
if (logger.isErrorEnabled()) {
|
logger.error("拷贝属性出错" + e);
|
}
|
}
|
}
|
}
|
});
|
}
|
|
|
|
|
/**
|
* 拷贝数据
|
* 大小写可以忽略
|
* 下划线 _ 被忽略
|
* @param source 来源属性
|
* @param target 目标属性
|
* @param ignoreNull 是否忽略控制
|
*/
|
public static void copyPropertiesIgnoreCase(Object source,Object target,boolean ignoreNull,Map<String/**原对象的属性名字**/,String/**目标对象的属性名称**/> fieldMap){
|
copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,null);
|
}
|
|
/**
|
* 缓存对象的属性
|
*/
|
private static class CacheFieldMap {
|
/**
|
* 对象属性的缓存
|
*/
|
private static Map<String/**类的名字**/, Map<String/**属性的名称小写**/, Field/**属性的对象**/>> cacheMap = new HashMap<>();
|
|
/**
|
* 对象的自己类的环境,不包括父类
|
*/
|
private static Map<String/**类的名称**/,Map<String/**属性的名称小写**/,Field/**属性的对象**/>> declaredCacheMap = new HashMap<>();
|
|
/**
|
* 获取属性的映射
|
* @param clazz 类
|
* @return 属性名称小写和属性的映射
|
*/
|
private static Map<String/**属性名称**/, Field> getFieldMap(Class clazz) {
|
Map<String, Field> result = cacheMap.get(clazz.getName());
|
if (result == null) {
|
synchronized (CacheFieldMap.class) {
|
if (result == null) {
|
Map<String, Field> fieldMap = new HashMap<>();
|
List<Field> allFields = VciBaseUtil.getAllFieldForObj(clazz);
|
if(!CollectionUtils.isEmpty(allFields)){
|
allFields.stream().forEach(field -> {
|
fieldMap.put(field.getName().toLowerCase().replace("_", ""), field);
|
});
|
}
|
cacheMap.put(clazz.getName(), fieldMap);
|
result = cacheMap.get(clazz.getName());
|
}
|
}
|
}
|
return result;
|
}
|
|
/**
|
* 获取属性的映射(不包含父类)
|
* @param clazz 类
|
* @return 属性名称小写和属性的映射
|
*/
|
private static Map<String/**属性名称**/,Field> getDeclaredFieldMap(Class clazz){
|
Map<String, Field> result = declaredCacheMap.get(clazz.getName());
|
if(result == null){
|
synchronized(CacheFieldMap.class){
|
if (result == null) {
|
Map<String, Field> fieldMap = new HashMap<>();
|
Field[] allFields = clazz.getDeclaredFields();
|
if(allFields!=null && allFields.length>0){
|
Arrays.stream(allFields).forEach(field -> {
|
fieldMap.put(field.getName().toLowerCase().replace("_", ""), field);
|
});
|
}
|
declaredCacheMap.put(clazz.getName(), fieldMap);
|
result = declaredCacheMap.get(clazz.getName());
|
}
|
}
|
}
|
return result;
|
}
|
}
|
|
/**
|
* 获取类拷贝的对象
|
* @param source 源对象类
|
* @param target 目标对象类
|
* @param useConverter 是否使用转换器
|
* @return 拷贝对象
|
*/
|
public static BeanCopier getBeanCopier(Class<?> source, Class<?> target,boolean useConverter) {
|
String beanCopierKey = generateBeanKey(source, target);
|
if (beanCopierMap.containsKey(beanCopierKey)) {
|
return beanCopierMap.get(beanCopierKey);
|
} else {
|
BeanCopier beanCopier = BeanCopier.create(source, target, useConverter);
|
beanCopierMap.putIfAbsent(beanCopierKey, beanCopier);
|
}
|
return beanCopierMap.get(beanCopierKey);
|
}
|
|
/**
|
* 生成两个类的key,用于存放到缓存之中
|
* @param source 源对象类型
|
* @param target 目标对象类
|
* @return 两个类的名称连接到一起后的名字
|
*/
|
public static String generateBeanKey(Class<?> source, Class<?> target) {
|
return source.getName() + "@" + target.getName();
|
}
|
|
/**
|
* 两个对象之间转换
|
* @param source 源对象
|
* @param target 目标对象
|
* @param useConvert 是否使用默认的转换器,请在出现属性名称相同而类型不同,或者有对象类型,集合属性时才转换
|
*/
|
public static void convert(Object source,Object target,boolean useConvert){
|
if(source != null && target !=null){
|
BeanCopier beanCopier = getBeanCopier(source.getClass(),target.getClass(),useConvert);
|
beanCopier.copy(source,target,useConvert?new DeepCopyConverter(target):null);
|
}
|
}
|
|
/**
|
* 两个对象之间转换
|
* @param source 源对象
|
* @param target 目标对象
|
* @return 目标对象
|
*/
|
public static void convert(Object source,Object target){
|
convert(source,target,true);
|
}
|
|
/**
|
* 深度拷贝转换器
|
*/
|
public static class DeepCopyConverter implements Converter {
|
|
/**
|
* 目标对象
|
*/
|
private Object target;
|
|
/**
|
* 构造方法
|
* @param target 目标对象
|
*/
|
public DeepCopyConverter(Object target) {
|
this.target = target;
|
}
|
|
/**
|
* 执行拷贝
|
* @param value 源对象的属性的值
|
* @param targetClazz 目标对象的属性的类
|
* @param methodName set方法的名字
|
* @return 转换后的值
|
*/
|
@Override
|
public Object convert(Object value, Class targetClazz, Object methodName) {
|
if (value instanceof List) {
|
List values = (List) value;
|
List retList = new ArrayList<>(values.size());
|
copyForCollection(values,retList,methodName);
|
return retList;
|
} else if(value instanceof Set){
|
Set values = (Set) value;
|
Set retSet = new HashSet<>();
|
copyForCollection(values,retSet,methodName);
|
} else if(value instanceof Vector){
|
Vector values = (Vector)value;
|
Vector retVector = new Vector();
|
copyForCollection(values,retVector,methodName);
|
}else if (value instanceof Map) {
|
Map values = (Map)value;
|
Map retMap = new HashMap();
|
for (final Object key : values.keySet()) {
|
Object mapValue = values.get(key);
|
String tempFieldName = methodName.toString().replace("set",
|
"");
|
String fieldName = tempFieldName.substring(0, 1)
|
.toLowerCase() + tempFieldName.substring(1);
|
Class clazz = ClassUtilForVCI.getElementType(target.getClass(), fieldName);
|
Object targetAttr = null;
|
try{
|
targetAttr = clazz.newInstance();
|
}catch (Throwable e){
|
//新的对象的属性初始化出错
|
}
|
BeanUtilForVCI.convert(mapValue, targetAttr);
|
retMap.put(key,targetAttr);
|
}
|
} else if (!ClassUtilForVCI.isPrimitive(targetClazz)) {
|
//这个是对象类型
|
Object targetAttr = null;
|
try{
|
targetAttr = targetClazz.newInstance();
|
}catch (Throwable e){
|
//新的对象属性初始化出错
|
}
|
BeanUtilForVCI.convert(value, targetAttr);
|
return targetAttr;
|
}
|
if(value instanceof Boolean && targetClazz.equals(String.class)){
|
//从boolean拷贝到string
|
return String.valueOf(value);
|
}
|
if(value instanceof String && (targetClazz.equals(Boolean.class)
|
|| targetClazz.equals(boolean.class))){
|
//从String拷贝到boolean
|
if("true".equalsIgnoreCase((String)value)){
|
return true;
|
}else{
|
return false;
|
}
|
}
|
if(value instanceof Date && targetClazz.equals(String.class)){
|
//时间格式
|
return VciDateUtil.date2Str((Date)value,VciDateUtil.DateTimeMillFormat);
|
}
|
if(value instanceof String && targetClazz.equals(Date.class)){
|
//转换
|
DateConverter dateConverter = new DateConverter();
|
dateConverter.setAsText((String)value);
|
return dateConverter.getValue();
|
}
|
return value;
|
}
|
|
/**
|
* 处理集合属性
|
* @param sourceCollection 源对象中集合属性的的值
|
* @param targetCollection 目标对象的集合属性的值
|
* @param methodName setter方法
|
*/
|
private void copyForCollection(Collection<?> sourceCollection,Collection targetCollection,Object methodName){
|
for (final Object source : sourceCollection) {
|
if(source instanceof Collection){
|
List<Object> targetValues = new ArrayList<>();
|
copyForCollection((Collection<?>)source,targetValues,methodName);
|
targetCollection.add(targetValues);
|
}else if(source instanceof Map){
|
String tempFieldName = methodName.toString().replace("set",
|
"");
|
String fieldName = tempFieldName.substring(0, 1)
|
.toLowerCase() + tempFieldName.substring(1);
|
Class clazz = ClassUtilForVCI.getElementType(target.getClass(), fieldName);
|
Object targetAttr = null;
|
try {
|
targetAttr = clazz.newInstance();
|
} catch (Throwable e) {
|
//新的对象的属性初始化出错
|
}
|
Map map = (Map) source;
|
for(Object key : map.keySet()){
|
VciBaseUtil.setValueForField(key.toString(),targetAttr,VciBaseUtil.getStringValueFromObject(map.get(key)));
|
}
|
targetCollection.add(targetAttr);
|
}else {
|
String tempFieldName = methodName.toString().replace("set",
|
"");
|
String fieldName = tempFieldName.substring(0, 1)
|
.toLowerCase() + tempFieldName.substring(1);
|
Class clazz = ClassUtilForVCI.getElementType(target.getClass(), fieldName);
|
Object targetAttr = null;
|
try {
|
targetAttr = clazz.newInstance();
|
} catch (Throwable e) {
|
//新的对象的属性初始化出错
|
}
|
BeanUtilForVCI.convert(source, targetAttr);
|
targetCollection.add(targetAttr);
|
}
|
}
|
}
|
}
|
}
|