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 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 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 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 fieldMap,Collection ignoreField){ Map sourceMap = CacheFieldMap.getDeclaredFieldMap(source.getClass()); Map 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 fieldMap, Collection ignoreField) { Map sourceMap = CacheFieldMap.getFieldMap(source.getClass()); Map 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 fieldMap, Collection ignoreField, Map sourceMap,Map targetMap ) { if(fieldMap == null){ fieldMap = new HashMap<>(); } Map 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 fieldMap){ copyPropertiesIgnoreCase(source,target,ignoreNull,fieldMap,null); } /** * 缓存对象的属性 */ private static class CacheFieldMap { /** * 对象属性的缓存 */ private static Map> cacheMap = new HashMap<>(); /** * 对象的自己类的环境,不包括父类 */ private static Map> declaredCacheMap = new HashMap<>(); /** * 获取属性的映射 * @param clazz 类 * @return 属性名称小写和属性的映射 */ private static Map getFieldMap(Class clazz) { Map result = cacheMap.get(clazz.getName()); if (result == null) { synchronized (CacheFieldMap.class) { if (result == null) { Map fieldMap = new HashMap<>(); List 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 getDeclaredFieldMap(Class clazz){ Map result = declaredCacheMap.get(clazz.getName()); if(result == null){ synchronized(CacheFieldMap.class){ if (result == null) { Map 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 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); } } } } }