top.doudou.common.tool.bean.ConvertBeanUtils Maven / Gradle / Ivy
package top.doudou.common.tool.bean;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import top.doudou.base.exception.ConvertException;
import top.doudou.base.exception.CustomException;
import top.doudou.base.stream.StreamCloseUtils;
import top.doudou.common.tool.utils.FieldUtils;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* bean属性的转换
*
* @author 傻男人<[email protected]>
* @date 2020-03-25
*/
@Slf4j
public class ConvertBeanUtils {
/**
* 实体属性相互转换
* @param entity
* @param doClass
* @param
* @return
*/
public static T copyProperties(E entity, Class doClass) {
if (entity == null) {
return null;
} else if (doClass == null) {
log.info("转换的class不能为null");
throw new CustomException("转换的class不能为null");
}
try {
T newInstance = doClass.newInstance();
BeanUtils.copyProperties(entity, newInstance);
return newInstance;
} catch (Exception e) {
log.info("属性转换异常!");
throw new CustomException("bean属性转换异常");
}
}
/**
* 属性复制
* @param source 源
* @param target 目标
*/
public static void copyProperties(Object source, Object target) {
if (source == null || target == null) {
throw new CustomException("源或者目标都不能为空");
}
try {
BeanUtils.copyProperties(source, target);
} catch (Exception e) {
log.info("属性转换异常!");
throw new CustomException("bean属性转换异常");
}
}
/**
* 转map
* @param obj
* @return 三种方式耗时最低
*/
public static Map convertBean2Map(Object obj) {
if (obj == null) {
return null;
}
Map map = Maps.newHashMap();
try {
List fields = FieldUtils.getAllNoStaticFields(obj.getClass());
for (Field field : fields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
public static Map convertMap(Map map){
Map result = Maps.newHashMap();
map.forEach((key,value)->result.put(key,new Gson().toJson(value)));
return result;
}
public static T convert(String json, Class target, Charset charset){
if(StringUtils.isBlank(json)){
return null;
}
T t = null;
try {
ObjectMapper mapper = new ObjectMapper();
//当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
//设置日期格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
t = mapper.readValue(new String(json.getBytes(charset), charset), target);
return t;
} catch (IOException e) {
e.printStackTrace();
}
return t;
}
/**
* 转map
* @param obj
* @return 三种方式最耗时
*/
public static Map objToMap(Object obj) {
Gson gson = new Gson();
return gson.fromJson(gson.toJson(obj),Map.class);
}
/**
* 实体类转map
* @param obj
* @return
*/
public static Map convertBeanToMap(Object obj) {
if (obj == null) {
return null;
}
Map map = Maps.newHashMap();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 过滤class属性
if (!key.equals("serialVersionUID") && !key.equals("class")) {
// 得到property对应的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(obj);
if(null==value){
map.put(key,"");
}else{
map.put(key,value);
}
}
}
} catch (Exception e) {
log.error("convertBean2Map Error {}" ,e);
}
return map;
}
/**
* Map转实体类
* @param map
* @param beanClass
* @return
*/
public static T mapToObj(Map map, Class beanClass) {
if (map == null) return null;
try {
T t = beanClass.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
Method setter = property.getWriteMethod();
if (setter != null) {
setter.invoke(t, map.get(property.getName()));
}
}
return t;
}catch (Exception e){
e.printStackTrace();
throw new CustomException("bean属性转换异常");
}
}
/**
* bean属性复制(bean中包含list)
*/
public static T copyPropertiesContainList(Object source, Class doClass) {
if (source == null) {
return null;
} else if (doClass == null) {
log.info("转换的class不能为null");
throw new CustomException("转换的class不能为null");
}
Field[] sourFields = source.getClass().getDeclaredFields();
// 将 source 的属性对象为 value,属性名为 key 封装为 map
Map sourFieldMap = Maps.newHashMap();
Arrays.stream(sourFields).forEach(sourField -> sourFieldMap.put(sourField.getName(), sourField));
try {
T target = doClass.newInstance();
Field[] tarFields = target.getClass().getDeclaredFields();
for (Field tarField : tarFields) {
// 从 sourFieldMap 中通过 fieldName 取值,若能取出表示存在相同的属性名
Field sourField = sourFieldMap.get(tarField.getName());
if (sourField == null || "serialVersionUID".equals(sourField.getName())) {
continue;
}
Class tarGenericClass = getGenericClass(tarField);
Class sourGenericClass = getGenericClass(sourField);
// 获取属性声明的类型 Class 对象
Class> sourType = sourField.getType();
Class> tarType = tarField.getType();
sourField.setAccessible(true);
tarField.setAccessible(true);
// 若不是 List 或其父接口类型,为 null
if (tarGenericClass == null && sourGenericClass == null) {
// target 属性类型是 source 属性类型的子类或子接口
if (sourType.isAssignableFrom(tarType)) {
tarField.set(target, sourField.get(source));
}
} else if (tarGenericClass != null && sourGenericClass != null) {
// Iterable 是 List 最顶层接口,在 sourGenericClass 中判断是声明类型是 List 或其父接口
Iterable sourList = (Iterable) sourField.get(source);
if (sourList == null) {
continue;
}
// 该集合用于添加 target 拷贝的对象
List tarList = Lists.newArrayList();
for (Object sourObj : sourList) {
tarList.add(copyPropertiesContainList(sourObj, tarGenericClass.newInstance().getClass()));
}
tarField.set(target, tarList);
}
}
return target;
} catch (Exception e) {
log.info("复制属性出错");
throw new CustomException("bean属性转换异常");
}
}
/**
* 获取属性类型中的泛型类型,获取泛型的过程适用于其他类型,但是本方法仅适用于 List 集合,
* 并且只有一个泛型的情况,若有需求后续增加功能。
*
* @param field
* @return
* @throws Exception
*/
private static Class getGenericClass(Field field) throws Exception {
// 获取属性声明的类型 Class 对象
Class> type = field.getType();
// 判断该 type 是否是 List 或其父接口
if (type.isAssignableFrom(List.class)) {
// 获取该属性声明的类型(Type 接口),getType():是获取属性声明的类型 Class 对象
Type genericType = field.getGenericType();
if (genericType == null) {
return null;
}
// 判断 geneicType 是否是参数化类型,即明确指定泛型的类型,如:java.util.List
if (genericType instanceof ParameterizedType) {
//因为 genericType 是 ParameterizedType 的实例,故可以强转
ParameterizedType pt = (ParameterizedType) genericType;
// 获取泛型的类型数组
Type[] genericArgs = pt.getActualTypeArguments();
// 当泛型类型大于 1 个时,抛出异常
if (genericArgs.length > 1) {
throw new Exception(genericType + " " + field.getName() + ": 泛型不只一个无法赋值");
}
// 当只有一个泛型类型时,获取泛型类型
return (Class) genericArgs[0];
}
}
return null;
}
/**
* 将Java对象序列化为二进制数据
*
* @param obj 需要序列化的的对象
* @return 二进制数据
*/
public static byte[] objectToByte(Object obj) {
ByteArrayOutputStream bo = null;
ObjectOutputStream oo = null;
try {
bo = new ByteArrayOutputStream();
oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
byte[] bytes = bo.toByteArray();
return bytes;
} catch (Exception e) {
log.info(" 对象序列化出现问题,出现问题的原因为 {}", e.getMessage());
throw new ConvertException("convert to byte[] error");
} finally {
StreamCloseUtils.close(bo);
StreamCloseUtils.close(oo);
}
}
/**
* 将序列化化后的二进制数据反序列化为对象
*
* @param bytes 序列化化后的二进制数据
* @return 对象
*/
public static Object byteToObject(byte[] bytes) {
ByteArrayInputStream bi = null;
ObjectInputStream oi = null;
try {
bi = new ByteArrayInputStream(bytes);
oi = new ObjectInputStream(bi);
return oi.readObject();
} catch (Exception e) {
log.info("对象反序列化出现问题,出现问题的原因为 {}", e.getMessage());
throw new ConvertException("byte[] convert to Object error");
}finally {
StreamCloseUtils.close(bi);
StreamCloseUtils.close(oi);
}
}
/**
* 将序列化化后的二进制数据反序列化为对象
*
* @param target 希望序列化成的数据类型,不能为空
*
* @param bytes 序列化化后的二进制数据
* @return 对象
*/
@SuppressWarnings("unchecked")
public static T byteToObject(Class target, byte[] bytes) {
return (T)byteToObject(bytes);
}
}