514 lines
16 KiB
Java
514 lines
16 KiB
Java
package com.sgcc.utils;
|
||
|
||
import com.google.common.collect.Maps;
|
||
import java.beans.BeanInfo;
|
||
import java.beans.IntrospectionException;
|
||
import java.beans.Introspector;
|
||
import java.beans.PropertyDescriptor;
|
||
import java.lang.reflect.Field;
|
||
import java.lang.reflect.Method;
|
||
import java.util.ArrayList;
|
||
import java.util.Arrays;
|
||
import java.util.HashSet;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.Set;
|
||
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.beans.BeanWrapper;
|
||
import org.springframework.beans.BeanWrapperImpl;
|
||
import org.springframework.core.io.Resource;
|
||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||
import org.springframework.core.type.classreading.MetadataReader;
|
||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||
import org.springframework.util.Assert;
|
||
import org.springframework.util.ReflectionUtils;
|
||
|
||
/**
|
||
* 实体转化工具类
|
||
*
|
||
* @author zhaoyuanyuan
|
||
* @version 1.0.0
|
||
* @date 2024/06/24 17:35
|
||
*/
|
||
@Slf4j
|
||
public class BeanUtils {
|
||
|
||
private static final String CLASS = "class";
|
||
|
||
private BeanUtils() {
|
||
throw new IllegalStateException("Utility class");
|
||
}
|
||
|
||
/**
|
||
* 判断对象是否为数字
|
||
*
|
||
* @param o
|
||
* @return
|
||
*/
|
||
public static boolean isNumber(Object o) {
|
||
if (o == null) {
|
||
return false;
|
||
}
|
||
if (o instanceof Number) {
|
||
return true;
|
||
}
|
||
if (o instanceof String) {
|
||
try {
|
||
Double.parseDouble((String) o);
|
||
return true;
|
||
} catch (NumberFormatException e) {
|
||
return false;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 将bean转化为map
|
||
*
|
||
* @param clazz bean
|
||
* @param <T> 泛型
|
||
* @return Map<String, Object> 返回对象
|
||
*/
|
||
public static <T> Map<String, Object> toMap(final T clazz) {
|
||
Map<String, Object> paramsMap = Maps.newHashMap();
|
||
try {
|
||
BeanInfo bi = Introspector.getBeanInfo(clazz.getClass());
|
||
PropertyDescriptor[] pd = bi.getPropertyDescriptors();
|
||
for (int i = 0; i < pd.length; i++) {
|
||
String name = pd[i].getName();
|
||
Method method = pd[i].getReadMethod();
|
||
Object value = method.invoke(clazz);
|
||
if (!CLASS.equals(name)) {
|
||
paramsMap.put(name, value);
|
||
}
|
||
}
|
||
} catch (IntrospectionException ie) {
|
||
log.error("IntrospectionException.className=" + clazz.getClass() + "BeanInfo error : ", ie);
|
||
} catch (Exception e) {
|
||
log.error("Exception.className=" + clazz.getClass() + "Method error :", e);
|
||
}
|
||
return paramsMap;
|
||
}
|
||
|
||
/**
|
||
* 获取到对象中属性为指定值的属性名
|
||
*
|
||
* @param source 要拷贝的对象
|
||
* @param values 指定的值数组
|
||
* @return
|
||
*/
|
||
public static String[] getPropertyNamesWithValues(Object source, String... values) {
|
||
List<String> valueList = (values != null ? Arrays.asList(values) : null);
|
||
final BeanWrapper src = new BeanWrapperImpl(source);
|
||
PropertyDescriptor[] pds = src.getPropertyDescriptors();
|
||
Set<String> propertyNames = new HashSet<>();
|
||
for (PropertyDescriptor pd : pds) {
|
||
Object srcValue = src.getPropertyValue(pd.getName());
|
||
if (valueList == null && srcValue == null) {
|
||
propertyNames.add(pd.getName());
|
||
} else if (valueList != null && valueList.contains(srcValue)) {
|
||
propertyNames.add(pd.getName());
|
||
} else {
|
||
// DO NOTHING
|
||
}
|
||
}
|
||
String[] result = new String[propertyNames.size()];
|
||
return propertyNames.toArray(result);
|
||
}
|
||
|
||
/**
|
||
* 列表实体类属性拷贝,忽略null值
|
||
*
|
||
* @param fromList 待转换实体列数组
|
||
* @param tClass 目标类
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> List<T> copyPropertiesIgnoreNull(List<F> fromList, Class<T> tClass) {
|
||
return copyPropertiesIgnoreValues(fromList, tClass, (String[]) null);
|
||
}
|
||
|
||
/**
|
||
* 实体类属性拷贝,忽略null值、空字符串""和"null"
|
||
*
|
||
* @param fromList 待转换实体列数组
|
||
* @param tClass 目标类
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> List<T> copyPropertiesIgnoreEmpty(List<F> fromList, Class<T> tClass) {
|
||
return copyPropertiesIgnoreValues(fromList, tClass, null, "", "null");
|
||
}
|
||
|
||
/**
|
||
* 实体类列表属性拷贝,忽略指定值
|
||
* 将entityList转换成modelList
|
||
*
|
||
* @param fromList 待转换实体列数组
|
||
* @param tClass 目标类
|
||
* @param values 指定的值数组
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> List<T> copyPropertiesIgnoreValues(List<F> fromList, Class<T> tClass, String... values) {
|
||
Assert.notNull(tClass, "tClass must not be null.");
|
||
List<T> tList = new ArrayList<>();
|
||
if (fromList != null && !fromList.isEmpty()) {
|
||
for (F f : fromList) {
|
||
T t = copyPropertiesIgnoreValues(f, tClass, values);
|
||
tList.add(t);
|
||
}
|
||
}
|
||
return tList;
|
||
}
|
||
|
||
/**
|
||
* 实体类列表属性拷贝
|
||
* 将entityList转换成modelList
|
||
*
|
||
* @param fromList 待转换实体列数组
|
||
* @param tClass 目标类
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> List<T> copyProperties(List<F> fromList, Class<T> tClass) {
|
||
Assert.notNull(tClass, "tClass must not be null.");
|
||
List<T> tList = new ArrayList<>();
|
||
if (fromList != null && !fromList.isEmpty()) {
|
||
for (F f : fromList) {
|
||
T t = copyProperties(f, tClass);
|
||
tList.add(t);
|
||
}
|
||
}
|
||
return tList;
|
||
}
|
||
|
||
/**
|
||
* 实体类属性拷贝,忽略null值
|
||
*
|
||
* @param entity 实体类
|
||
* @param modelClass 目标类
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> T copyPropertiesIgnoreNull(F entity, Class<T> modelClass) {
|
||
return copyPropertiesIgnoreValues(entity, modelClass, (String[]) null);
|
||
}
|
||
|
||
/**
|
||
* 实体类属性拷贝,忽略null值、空字符串""和"null"
|
||
*
|
||
* @param entity 实体类
|
||
* @param modelClass 目标类
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> T copyPropertiesIgnoreEmpty(F entity, Class<T> modelClass) {
|
||
return copyPropertiesIgnoreValues(entity, modelClass, null, "", "null");
|
||
}
|
||
|
||
/**
|
||
* 实体类属性拷贝,忽略指定值
|
||
*
|
||
* @param entity 实体类
|
||
* @param modelClass 目标类
|
||
* @param values 指定的值数组
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> T copyPropertiesIgnoreValues(F entity, Class<T> modelClass, String... values) {
|
||
return copyProperties(entity, modelClass, getPropertyNamesWithValues(entity, values));
|
||
}
|
||
|
||
/**
|
||
* 实体类属性拷贝
|
||
*
|
||
* @param entity 实体类
|
||
* @param modelClass 目标类
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> T copyProperties(F entity, Class<T> modelClass) {
|
||
return copyProperties(entity, modelClass, (String[]) null);
|
||
}
|
||
|
||
/**
|
||
* 实体类属性拷贝
|
||
*
|
||
* @param entity 实体类
|
||
* @param modelClass 目标类
|
||
* @param ignoreProperties 忽略属性列表
|
||
* @param <F>
|
||
* @param <T>
|
||
* @return
|
||
*/
|
||
public static <F, T> T copyProperties(F entity, Class<T> modelClass, String... ignoreProperties) {
|
||
Assert.notNull(modelClass, "modelClass must not be null.");
|
||
Object model = null;
|
||
|
||
try {
|
||
model = modelClass.newInstance();
|
||
} catch (InstantiationException e) {
|
||
log.error("copyProperties: InstantiationException", e);
|
||
} catch (IllegalAccessException e) {
|
||
log.error("copyProperties: IllegalAccessException", e);
|
||
}
|
||
|
||
if (entity != null) {
|
||
org.springframework.beans.BeanUtils.copyProperties(entity, model, ignoreProperties);
|
||
} else {
|
||
// DO NOTHING
|
||
}
|
||
return (T) model;
|
||
}
|
||
|
||
/**
|
||
* 将下划线大写方式命名的字符串转换为驼峰式。
|
||
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
|
||
* 例如:hello_world->helloWorld
|
||
*
|
||
* @param name 转换前的下划线大写方式命名的字符串
|
||
* @return 转换后的驼峰式命名的字符串
|
||
*/
|
||
public static String camelName(String name) {
|
||
StringBuilder result = new StringBuilder();
|
||
// 快速检查
|
||
if (name == null || name.isEmpty()) {
|
||
// 没必要转换
|
||
return "";
|
||
} else if (!name.contains("_")) {
|
||
// 不含下划线,仅将首字母小写
|
||
return name.substring(0, 1).toLowerCase() + name.substring(1).toLowerCase();
|
||
}
|
||
// 用下划线将原始字符串分割
|
||
String[] camels = name.split("_");
|
||
for (String camel : camels) {
|
||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||
if (camel.isEmpty()) {
|
||
continue;
|
||
}
|
||
// 处理真正的驼峰片段
|
||
if (result.length() == 0) {
|
||
// 第一个驼峰片段,全部字母都小写
|
||
result.append(camel.toLowerCase());
|
||
} else {
|
||
// 其他的驼峰片段,首字母大写
|
||
result.append(camel.substring(0, 1).toUpperCase());
|
||
result.append(camel.substring(1).toLowerCase());
|
||
}
|
||
}
|
||
return result.toString();
|
||
}
|
||
|
||
/**
|
||
* 将下划线大写方式命名的字符串转换为驼峰式。
|
||
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
|
||
* 例如:hello_world,test_id->helloWorld,testId
|
||
*
|
||
* @param names 转换前的下划线大写方式命名的字符串
|
||
* @return 转换后的驼峰式命名的字符串
|
||
*/
|
||
public static String camelNames(String names) {
|
||
if (names == null || names.equals("")) {
|
||
return null;
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
String[] fs = names.split(",");
|
||
for (String field : fs) {
|
||
field = camelName(field);
|
||
sb.append(field + ",");
|
||
}
|
||
String result = sb.toString();
|
||
return result.substring(0, result.length() - 1);
|
||
}
|
||
|
||
/**
|
||
* 将下划线大写方式命名的字符串转换为驼峰式。
|
||
* (首字母写) 如果转换前的下划线大写方式命名的字符串为空,
|
||
* 则返回空字符串。</br>
|
||
* 例如:hello_world->HelloWorld
|
||
*
|
||
* @param name 转换前的下划线大写方式命名的字符串
|
||
* @return 转换后的驼峰式命名的字符串
|
||
*/
|
||
public static String camelNameCapFirst(String name) {
|
||
// 转换为首字母小写的驼峰片段
|
||
String camel = camelName(name);
|
||
if (camel == null || camel.length() < 1) {
|
||
return name;
|
||
}
|
||
// 首字母大写
|
||
char[] charArray = camel.toCharArray();
|
||
charArray[0] -= 32;
|
||
return String.valueOf(charArray);
|
||
}
|
||
|
||
/**
|
||
* 将驼峰命名转化成下划线
|
||
*
|
||
* @param param
|
||
* @return
|
||
*/
|
||
public static String camelToUnderline(String param) {
|
||
if (param == null) {
|
||
return null;
|
||
}
|
||
int paramLen = param.length();
|
||
if (paramLen < 3) {
|
||
return param.toLowerCase();
|
||
}
|
||
int wordCount = 0;
|
||
StringBuilder sb = new StringBuilder(param);
|
||
// 从第三个字符开始 避免命名不规范
|
||
for (int i = 2; i < paramLen; i++) {
|
||
if (Character.isUpperCase(param.charAt(i))) {
|
||
sb.insert(i + wordCount, "_");
|
||
wordCount += 1;
|
||
}
|
||
}
|
||
return sb.toString().toLowerCase();
|
||
}
|
||
|
||
/**
|
||
* 根据指定的类名判定指定的类是否存在。
|
||
*
|
||
* @param className
|
||
* @return
|
||
*/
|
||
public static boolean validClass(String className) {
|
||
try {
|
||
Class.forName(className);
|
||
return true;
|
||
} catch (ClassNotFoundException e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判定类是否继承自父类
|
||
*
|
||
* @param cls 子类
|
||
* @param parentClass 父类
|
||
* @return
|
||
*/
|
||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||
public static boolean isInherit(Class cls, Class parentClass) {
|
||
return parentClass.isAssignableFrom(cls);
|
||
}
|
||
|
||
/**
|
||
* 输入基类包名,扫描其下的类,返回类的全路径
|
||
*
|
||
* @param basePackages 如:com.hotent
|
||
* @return
|
||
* @throws IllegalArgumentException
|
||
*/
|
||
@SuppressWarnings("all")
|
||
public static List<String> scanPackages(String basePackages)
|
||
throws IllegalArgumentException {
|
||
ResourcePatternResolver rl = new PathMatchingResourcePatternResolver();
|
||
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(
|
||
rl);
|
||
List result = new ArrayList();
|
||
String[] arrayPackages = basePackages.split(",");
|
||
try {
|
||
for (int j = 0; j < arrayPackages.length; j++) {
|
||
String packageToScan = arrayPackages[j];
|
||
String packagePart = packageToScan.replace('.', '/');
|
||
String classPattern = "classpath*:/" + packagePart
|
||
+ "/**/*.class";
|
||
Resource[] resources = rl.getResources(classPattern);
|
||
for (int i = 0; i < resources.length; i++) {
|
||
Resource resource = resources[i];
|
||
MetadataReader metadataReader = metadataReaderFactory
|
||
.getMetadataReader(resource);
|
||
String className = metadataReader.getClassMetadata()
|
||
.getClassName();
|
||
result.add(className);
|
||
}
|
||
}
|
||
} catch (Exception e) {
|
||
new IllegalArgumentException("scan pakcage class error,pakcages:"
|
||
+ basePackages);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 将字符串数据按照指定的类型进行转换。
|
||
*
|
||
* @param typeName 实际的数据类型
|
||
* @param value 字符串值。
|
||
* @return Object
|
||
*/
|
||
public static Object convertByActType(String typeName, String value) {
|
||
Object o = null;
|
||
if (typeName.equals("int")) {
|
||
o = Integer.parseInt(value);
|
||
} else if (typeName.equals("short")) {
|
||
o = Short.parseShort(value);
|
||
} else if (typeName.equals("long")) {
|
||
o = Long.parseLong(value);
|
||
} else if (typeName.equals("float")) {
|
||
o = Float.parseFloat(value);
|
||
} else if (typeName.equals("double")) {
|
||
o = Double.parseDouble(value);
|
||
} else if (typeName.equals("boolean")) {
|
||
o = Boolean.parseBoolean(value);
|
||
} else if (typeName.equals("java.lang.String")) {
|
||
o = value;
|
||
} else {
|
||
o = value;
|
||
}
|
||
return o;
|
||
}
|
||
|
||
/**
|
||
* 根据类和成员变量名称获取成员变量。
|
||
*
|
||
* @param thisClass
|
||
* @param fieldName
|
||
* @return
|
||
* @throws NoSuchFieldException Field
|
||
*/
|
||
public static Field getField(Class<?> thisClass, String fieldName)
|
||
throws NoSuchFieldException {
|
||
|
||
if (fieldName == null) {
|
||
throw new NoSuchFieldException("Error field !");
|
||
}
|
||
|
||
Field field = thisClass.getDeclaredField(fieldName);
|
||
return field;
|
||
}
|
||
|
||
/**
|
||
* 数据列表去重
|
||
*
|
||
* @param list
|
||
*/
|
||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||
public static void removeDuplicate(List list) {
|
||
HashSet h = new HashSet(list);
|
||
list.clear();
|
||
list.addAll(h);
|
||
}
|
||
|
||
private static void handleReflectionException(Exception e) {
|
||
ReflectionUtils.handleReflectionException(e);
|
||
}
|
||
|
||
} |