---初始化项目
This commit is contained in:
@ -0,0 +1,81 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ArrayUtils {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] of(T... parameters) {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T>T[] valueOf(List<T> list){
|
||||
if(list!=null) {
|
||||
T[] result = null;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
T item = list.get(i);
|
||||
if(result==null) {
|
||||
result = (T[]) Array.newInstance(item.getClass(),list.size());
|
||||
}
|
||||
result[i] = item;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] ofCollection(Collection<T> objs){
|
||||
T[] result=null;
|
||||
if(objs!=null) {
|
||||
Iterator<T> it=objs.iterator();
|
||||
int i=0;
|
||||
while (it.hasNext()) {
|
||||
T item =it.next();
|
||||
if(result==null) {
|
||||
result = (T[]) Array.newInstance(item.getClass(),objs.size());
|
||||
}
|
||||
result[i] = item;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> String join(T[] array){
|
||||
return join(array,",",null);
|
||||
}
|
||||
|
||||
|
||||
public static <T> String join(T[] array,String split){
|
||||
return join(array, split, null);
|
||||
}
|
||||
|
||||
public static <T> String join(T[] array,String split,String suffix){
|
||||
if(array==null || array.length==0){
|
||||
return null;
|
||||
}
|
||||
StringBuilder str=new StringBuilder();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if(i>0) {
|
||||
str.append(split);
|
||||
}
|
||||
if(suffix!=null) str.append(suffix);
|
||||
str.append(array[i].toString());
|
||||
if(suffix!=null) str.append(suffix);
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,447 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.pictc.exceptions.TFieldException;
|
||||
import com.pictc.exceptions.TMethodException;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author 张福财
|
||||
* @date 2023年8月11日
|
||||
* @Description: java对象反射工具类
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public class BeanUtils {
|
||||
|
||||
|
||||
private BeanUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 获取java类的属性map集合
|
||||
* @param @param cls
|
||||
* @param @return 参数
|
||||
* @return Map<String,Field> 返回类型
|
||||
* @throws
|
||||
*/
|
||||
public static Map<String, Field> getMapFields(Class<?> cls) {
|
||||
Map<String, Field> fields = CollectionUtils.newHashMap();
|
||||
if (cls != null) {
|
||||
List<Field> fieldList = new ArrayList<Field>();
|
||||
Set<String> names = new HashSet<String>();
|
||||
getFields(cls, fieldList,names);
|
||||
for (Field field : fieldList) {
|
||||
if (hasGetSet(field, cls)) {
|
||||
fields.put(field.getName(), field);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 获取对象非空值的Map集合
|
||||
* @param @param obj
|
||||
* @param @return 参数
|
||||
* @return Map<String,Object> 返回类型
|
||||
* @throws
|
||||
*/
|
||||
public static Map<String,Object> getBeanNotNullValue(Object obj){
|
||||
Map<String,Object> rel=CollectionUtils.newHashMap();
|
||||
if(obj==null) {
|
||||
return rel;
|
||||
}
|
||||
Field[] fields= getFields(obj.getClass());
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Object val=getFieldValue(fields[i], obj);
|
||||
if(val!=null) {
|
||||
rel.put(fields[i].getName(),val);
|
||||
}
|
||||
}
|
||||
return rel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 获取Class 包含指定注解类型的属性
|
||||
* @param @param cls
|
||||
* @param @param annotation
|
||||
* @param @return 参数
|
||||
* @return List<Field> 返回类型
|
||||
* @throws
|
||||
*/
|
||||
public static List<Field> getFields(Class<?> cls, Class<? extends Annotation> annotation) {
|
||||
List<Field> result = CollectionUtils.newArrayList();
|
||||
Field[] fields = getFields(cls);
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Field field = fields[i];
|
||||
if (field.isAnnotationPresent(annotation)) {
|
||||
result.add(field);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 获取Class 属性数组
|
||||
* @param @param cls
|
||||
* @param @return 参数
|
||||
* @return Field[] 返回类型
|
||||
* @throws
|
||||
*/
|
||||
public static Field[] getFields(Class<?> cls) {
|
||||
List<Field> fields = new ArrayList<Field>();
|
||||
Set<String> names = new HashSet<String>();
|
||||
getFields(cls, fields,names);
|
||||
Field[] result = new Field[fields.size()];
|
||||
fields.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static void getFields(Class<?> cls, List<Field> fields,Set<String> names) {
|
||||
if (!cls.equals(Object.class)) {
|
||||
Field[] _fields = cls.getDeclaredFields();
|
||||
for (int i = 0; i < _fields.length; i++) {
|
||||
Field field = _fields[i];
|
||||
if(names.contains(field.getName())) {
|
||||
continue;
|
||||
}
|
||||
fields.add(field);
|
||||
names.add(field.getName());
|
||||
}
|
||||
getFields(cls.getSuperclass(), fields,names);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 判断class是否有指定属性名的getter、setter方法
|
||||
* @param fieldName
|
||||
* @param cls
|
||||
* @return boolean 返回类型
|
||||
*/
|
||||
public static boolean hasGetSet(String fieldName, Class<?> cls) {
|
||||
try {
|
||||
return hasGetSet(cls.getDeclaredField(fieldName), cls);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Class【"+cls+"】-属性【"+fieldName+"】获取getter、setter方法异常",e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean hasGetSet(Field field, Class<?> cls) {
|
||||
Class<?> type = field.getType();
|
||||
String name = field.getName();
|
||||
String getName = null;
|
||||
String uname = getMethodName(name);
|
||||
if (type.equals(boolean.class) || type.equals(Boolean.class)) {
|
||||
if (name.startsWith("is")) {
|
||||
getName = name;
|
||||
} else {
|
||||
getName = "is" + uname;
|
||||
}
|
||||
} else {
|
||||
getName = "get" + uname;
|
||||
}
|
||||
String setName = "set" + uname;
|
||||
Class<?> beanType = cls;
|
||||
do {
|
||||
if (findGetSet(beanType, getName, setName, type)) {
|
||||
return true;
|
||||
}
|
||||
beanType = beanType.getSuperclass();
|
||||
} while (!Object.class.equals(beanType));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static boolean findGetSet(Class<?> beanType, String getName, String setName, Class<?> type) {
|
||||
Method getMethod = null;
|
||||
Method setMethod = null;
|
||||
try {
|
||||
getMethod = beanType.getDeclaredMethod(getName);
|
||||
setMethod = beanType.getDeclaredMethod(setName, type);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return getMethod != null && setMethod != null;
|
||||
}
|
||||
|
||||
|
||||
private static String getMethodName(String name) {
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
|
||||
|
||||
public static void setFieldValue(Field field, Object value, Object bean) {
|
||||
try {
|
||||
if(field==null) {
|
||||
throw new TFieldException("setFieldValue时field不能为空");
|
||||
}
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
field.set(bean, value);
|
||||
} catch (Exception e) {
|
||||
throw new TFieldException("setFieldValue异常", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void setFieldValue(String fieldName, Object value, Object bean) {
|
||||
setFieldValue(getField(fieldName, bean), value, bean);
|
||||
}
|
||||
|
||||
|
||||
public static <T> T getFieldValue(String fieldName, Object bean) {
|
||||
return getFieldValue(getField(fieldName, bean), bean);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static <T> T getFieldValue(Field field, Object bean) {
|
||||
Object value = null;
|
||||
if(field==null) {
|
||||
throw new TFieldException("获取属性值时field不能为空");
|
||||
}
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
try {
|
||||
value = field.get(bean);
|
||||
} catch (Exception e) {
|
||||
throw new TFieldException("getFieldValue异常", e);
|
||||
}
|
||||
return value==null?null:(T)value;
|
||||
}
|
||||
|
||||
public static Field getField(String fieldName, Object bean) {
|
||||
return getField(fieldName, bean.getClass());
|
||||
}
|
||||
|
||||
public static Field getField(String fieldName, Class<?> cls) {
|
||||
try {
|
||||
return cls.getDeclaredField(fieldName);
|
||||
} catch (Exception e) {
|
||||
throw new TFieldException("获取属性异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T newInstance(Class<?> cls) {
|
||||
return newInstance(cls,false);
|
||||
}
|
||||
|
||||
public static <T> T newInstance(ClassLoader loader,Class<?> cls) {
|
||||
return newInstance(loader,cls,false);
|
||||
}
|
||||
|
||||
public static <T> T newInstance(Class<?> cls,boolean ignoreError) {
|
||||
return newInstance(null,cls,ignoreError);
|
||||
}
|
||||
|
||||
public static <T> T newInstance(ClassLoader loader,Class<?> cls,boolean ignoreError) {
|
||||
try {
|
||||
return (T) ClassUtils.loadClass(loader,cls.getName()).getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
if(!ignoreError) {
|
||||
throw new RuntimeException("实例化:Class【"+cls.getName()+"】异常",e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T newInstance(String className) {
|
||||
return newInstance(className, false);
|
||||
}
|
||||
|
||||
public static <T> T newInstance(String className,boolean ignoreError) {
|
||||
try {
|
||||
return (T) ClassUtils.loadClass(className).getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
if(!ignoreError) {
|
||||
throw new RuntimeException("实例化:Class【"+className+"】异常",e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T>T deepCopy(Object source){
|
||||
if(source!=null) {
|
||||
Map<String,Object> cache = CollectionUtils.newHashMap();
|
||||
try {
|
||||
return (T) deepCopy(source.getClass(),source,cache);
|
||||
} finally {
|
||||
cache.clear();
|
||||
cache = null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T>T deepCopy(Type javaType,Object source){
|
||||
if(source!=null) {
|
||||
Map<String,Object> cache = CollectionUtils.newHashMap();
|
||||
try {
|
||||
return (T) deepCopy(javaType,source,cache);
|
||||
} finally {
|
||||
cache.clear();
|
||||
cache = null;
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object deepCopy(Type javaType,Object source,Map<String,Object> cache){
|
||||
if(source==null) {
|
||||
return null;
|
||||
}
|
||||
String addr = Integer.toHexString(source.hashCode());
|
||||
if(cache.containsKey(addr)) {
|
||||
return cache.get(addr);
|
||||
}
|
||||
|
||||
TypeInfo type = new TypeInfo(javaType);
|
||||
Object target = null;
|
||||
if(type.isPrimitive() || type.isEnum()) {
|
||||
target = source;
|
||||
}else if(type.isArray()) {
|
||||
int length = Array.getLength(source);
|
||||
List<Object> list = new ArrayList<Object>(length);
|
||||
for (int j = 0; j < length; j += 1) {
|
||||
Object obj = Array.get(source, j);
|
||||
list.add(deepCopy(type.getArrayType(),obj));
|
||||
}
|
||||
target = list.toArray();
|
||||
}else if(type.isCollection()) {
|
||||
Collection<Object> cvals = (Collection<Object>) source;
|
||||
Collection<Object> nvals = type.newCollection();
|
||||
for (Object obj : cvals) {
|
||||
nvals.add(deepCopy(type.getCollectionType(),obj));
|
||||
}
|
||||
target = nvals;
|
||||
}else if(type.isMap()) {
|
||||
Map<Object, Object> mapVal = type.newMap();
|
||||
Map<?, ?> valMap = (Map<?, ?>) source;
|
||||
for (final Entry<?, ?> e : valMap.entrySet()) {
|
||||
final Object value = e.getValue();
|
||||
if (value != null) {
|
||||
mapVal.put(e.getKey(),deepCopy(value));
|
||||
}
|
||||
}
|
||||
target = mapVal;
|
||||
}else {
|
||||
Class<?> klass = type.getKlass();
|
||||
target = newInstance(klass);
|
||||
cache.put(addr,target);
|
||||
Field[] fields = getFields(klass);
|
||||
Class<?> sklazz = source.getClass();
|
||||
Map<String, Field> mapFields = getMapFields(sklazz);
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
Field field = fields[i];
|
||||
Field sf = mapFields.get(field.getName());
|
||||
if(sf==null || !sf.getType().equals(field.getType())) {
|
||||
continue;
|
||||
}
|
||||
Object val = getFieldValue(sf, source);
|
||||
if(val!=null) {
|
||||
setFieldValue(field,deepCopy(field.getGenericType(),val, cache),target);
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用方法
|
||||
* */
|
||||
public static <T>T callMethod(Method method, Object obj, Object... values) throws InstantiationException,
|
||||
IllegalAccessException, NumberFormatException, IllegalArgumentException,
|
||||
InvocationTargetException {
|
||||
return (T) method.invoke(obj, values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断类是否含义该属性
|
||||
*
|
||||
* @param klass
|
||||
* @param field
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasField(Class<?> klass, String field) {
|
||||
Class<?> btype = klass;
|
||||
while (!Object.class.equals(btype)) {
|
||||
try {
|
||||
btype.getDeclaredField(field);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
btype = btype.getSuperclass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Method getMethod(Class<?> cls, String name, Class<?>... agrs) {
|
||||
Method method = null;
|
||||
try {
|
||||
if (agrs == null || agrs.length == 0) {
|
||||
method = cls.getDeclaredMethod(name);
|
||||
} else {
|
||||
method = cls.getDeclaredMethod(name, agrs);
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
throw new TMethodException(e);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
public static Method getHasMethod(Class<?> cls, String name, Class<?>... agrs) {
|
||||
Method method = null;
|
||||
try {
|
||||
if (agrs == null || agrs.length == 0) {
|
||||
method = cls.getDeclaredMethod(name);
|
||||
} else {
|
||||
method = cls.getDeclaredMethod(name, agrs);
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
return method;
|
||||
}
|
||||
|
||||
public static <T>T copyBean(Object source,T target){
|
||||
if(source!=null) {
|
||||
Field[] ffields = getFields(target.getClass());
|
||||
Map<String,Field> tarNames = CollectionUtils.newHashMap();
|
||||
for (int i = 0; i < ffields.length; i++) {
|
||||
tarNames.put(ffields[i].getName(),ffields[i]);
|
||||
}
|
||||
Field[] fields = getFields(source.getClass());
|
||||
for (Field field : fields) {
|
||||
if(tarNames.containsKey(field.getName())) {
|
||||
setFieldValue(tarNames.get(field.getName()),getFieldValue(field,source),target);
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,342 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
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.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.sql.Date;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ClassUtils {
|
||||
|
||||
private static Set<Class<?>> primitives=CollectionUtils.newHashSet();
|
||||
private static Set<Class<?>> numbers=CollectionUtils.newHashSet();
|
||||
private static Set<Class<?>> integers=CollectionUtils.newHashSet();
|
||||
private static Set<Class<?>> doubles=CollectionUtils.newHashSet();
|
||||
private static Set<Class<?>> dates=CollectionUtils.newHashSet();
|
||||
private static Set<Class<?>> strings=CollectionUtils.newHashSet();
|
||||
|
||||
static {
|
||||
primitives.add(BigDecimal.class);primitives.add(BigInteger.class);
|
||||
primitives.add(Integer.class);primitives.add(int.class);
|
||||
primitives.add(Double.class);primitives.add(double.class);
|
||||
primitives.add(Float.class);primitives.add(float.class);
|
||||
primitives.add(Long.class);primitives.add(long.class);
|
||||
primitives.add(Short.class);primitives.add(short.class);
|
||||
primitives.add(Byte.class);primitives.add(byte.class);
|
||||
primitives.add(Boolean.class);primitives.add(boolean.class);
|
||||
primitives.add(Character.class);primitives.add(char.class);
|
||||
primitives.add(String.class);primitives.add(Date.class);
|
||||
primitives.add(Timestamp.class);primitives.add(java.util.Date.class);
|
||||
primitives.add(Time.class);
|
||||
|
||||
integers.add(Integer.class);integers.add(int.class);
|
||||
integers.add(Long.class);integers.add(long.class);
|
||||
integers.add(Short.class);integers.add(short.class);
|
||||
integers.add(Byte.class);integers.add(byte.class);
|
||||
integers.add(BigInteger.class);
|
||||
|
||||
doubles.add(Double.class);doubles.add(double.class);
|
||||
doubles.add(Float.class);doubles.add(float.class);
|
||||
doubles.add(BigDecimal.class);
|
||||
|
||||
numbers.add(Integer.class);numbers.add(int.class);
|
||||
numbers.add(Double.class);numbers.add(double.class);
|
||||
numbers.add(Float.class);numbers.add(float.class);
|
||||
numbers.add(Long.class);numbers.add(long.class);
|
||||
numbers.add(Short.class);numbers.add(short.class);
|
||||
numbers.add(Byte.class);numbers.add(byte.class);
|
||||
numbers.add(BigDecimal.class);numbers.add(BigInteger.class);
|
||||
|
||||
dates.add(Date.class); dates.add(Time.class);
|
||||
dates.add(Timestamp.class);dates.add(java.util.Date.class);
|
||||
|
||||
strings.add(Character.class);strings.add(char.class);
|
||||
strings.add(String.class);strings.add(StringBuilder.class);
|
||||
strings.add(StringBuffer.class);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为基本数据类型
|
||||
* */
|
||||
public static boolean isPrimitive(Class<?> klass) {
|
||||
return primitives.contains(klass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为字符串类型
|
||||
* */
|
||||
public static boolean isString(Class<?> cls) {
|
||||
return strings.contains(cls) || hashClass(cls, CharSequence.class);
|
||||
}
|
||||
|
||||
public static boolean isNumber(Class<?> type) {
|
||||
return numbers.contains(type);
|
||||
}
|
||||
|
||||
public static boolean isInt(Class<?> type) {
|
||||
return integers.contains(type);
|
||||
}
|
||||
|
||||
public static boolean isDouble(Class<?> type) {
|
||||
return doubles.contains(type);
|
||||
}
|
||||
|
||||
public static boolean isDate(Class<?> type) {
|
||||
return dates.contains(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是map集合
|
||||
* */
|
||||
public static boolean isMap(Class<?> klass) {
|
||||
return hashClass(klass, Map.class);
|
||||
}
|
||||
/**
|
||||
* 是否是set集合
|
||||
* */
|
||||
public static boolean isSet(Class<?> klass) {
|
||||
return hashClass(klass, Set.class);
|
||||
}
|
||||
/**
|
||||
* 是否是list集合
|
||||
* */
|
||||
public static boolean isList(Class<?> klass) {
|
||||
return hashClass(klass, List.class);
|
||||
}
|
||||
|
||||
public static boolean isCollection(Class<?> klass) {
|
||||
return isList(klass) || isSet(klass);
|
||||
}
|
||||
|
||||
/**
|
||||
* klass是否实现了face类或接口
|
||||
* @author tanuki
|
||||
* @param klass 要判断的类型
|
||||
* @param face 指定的类型
|
||||
* */
|
||||
public static boolean hashClass(Class<?> klass, Class<?> face) {
|
||||
if (klass.equals(face)) {
|
||||
return true;
|
||||
} else {
|
||||
if (Object.class.equals(klass)) {
|
||||
return false;
|
||||
}
|
||||
Class<?>[] cls = klass.getInterfaces();
|
||||
for (int i = 0; i < cls.length; i++) {
|
||||
if (hashClass(cls[i], face)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!klass.isInterface()) {
|
||||
if (hashClass(klass.getSuperclass(), face)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type 类型转 class
|
||||
* */
|
||||
public static Class<?> getClass(Type type) throws ClassNotFoundException{
|
||||
String cStr=type.toString();
|
||||
if(cStr.indexOf("class ")==0){
|
||||
return Class.forName(cStr.substring(6, cStr.length()));
|
||||
}else if(cStr.indexOf("interface ")==0){
|
||||
return Class.forName(cStr.substring(10, cStr.length()));
|
||||
}else{
|
||||
if(cStr.indexOf("<")!=-1){
|
||||
return Class.forName(cStr.substring(0, cStr.indexOf("<")));
|
||||
}
|
||||
return Class.forName(cStr.substring(0, cStr.length()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Type[] getFeildFan(Field field) {
|
||||
Type type = field.getGenericType();
|
||||
if(type instanceof ParameterizedType){
|
||||
return ((ParameterizedType)type).getActualTypeArguments();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Type getFeildFan(Field field,int index) {
|
||||
Type type = field.getGenericType();
|
||||
if(type instanceof ParameterizedType){
|
||||
return ((ParameterizedType)type).getActualTypeArguments()[index];
|
||||
}
|
||||
return field.getType();
|
||||
}
|
||||
|
||||
public static Class<?> getFeildFanClass(Field field,int index) throws ClassNotFoundException {
|
||||
return getClass(getFeildFan(field, index));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结合的泛型
|
||||
* */
|
||||
public static Type getCollectionFan(Type type){
|
||||
Type result=null;
|
||||
if(type instanceof ParameterizedType){
|
||||
result=((ParameterizedType)type).getActualTypeArguments()[0];
|
||||
}else{
|
||||
result=type;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取结合的泛型
|
||||
* @throws ClassNotFoundException
|
||||
* */
|
||||
public static Class<?> getCollectionFanClass(Type type) throws ClassNotFoundException{
|
||||
Class<?> result=null;
|
||||
if(type instanceof ParameterizedType){
|
||||
result= getClass(((ParameterizedType)type).getActualTypeArguments()[0]);
|
||||
}else{
|
||||
result = getClass(type);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结合的泛型
|
||||
* @throws ClassNotFoundException
|
||||
* */
|
||||
public static Class<?> getArrayClass(Class<?> type) throws ClassNotFoundException{
|
||||
return type.getComponentType();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 反射对象获取泛型
|
||||
* </p>
|
||||
*
|
||||
* @param clazz 对象
|
||||
* @param index 泛型所在位置
|
||||
* @return Class
|
||||
*/
|
||||
public static Class<?> getSuperClassGenericType(final Class<?> clazz, final int index) {
|
||||
Type genType = clazz.getGenericSuperclass();
|
||||
if (!(genType instanceof ParameterizedType)) {
|
||||
log.warn("Warn: {}'s superclass not ParameterizedType", clazz.getSimpleName());
|
||||
return Object.class;
|
||||
}
|
||||
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
|
||||
if (index >= params.length || index < 0) {
|
||||
log.warn("Warn: Index: {}, Size of {}'s Parameterized Type: {} .", index,clazz.getSimpleName(), params.length);
|
||||
return Object.class;
|
||||
}
|
||||
if (!(params[index] instanceof Class)) {
|
||||
log.warn("Warn: {} not set the actual class on superclass generic parameter",clazz.getSimpleName());
|
||||
return Object.class;
|
||||
}
|
||||
return (Class<?>) params[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Map的泛型
|
||||
* */
|
||||
public static Type[] getMapFan(Type type){
|
||||
Type[] result=null;
|
||||
if(type instanceof ParameterizedType){
|
||||
result=((ParameterizedType)type).getActualTypeArguments();
|
||||
}else{
|
||||
result=new Type[0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取远程jar包加载到当前jvm中
|
||||
* */
|
||||
public static void loadJar(Set<String> urls) {
|
||||
Method method = null;
|
||||
boolean accessible = false;
|
||||
try {
|
||||
method= URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
accessible = method.isAccessible();
|
||||
if (accessible == false) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||
for (String address : urls) {
|
||||
method.invoke(classLoader,new URL(address));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(method!=null) {
|
||||
method.setAccessible(accessible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ClassLoader getDefaultClassLoader() {
|
||||
ClassLoader cl = null;
|
||||
try {
|
||||
cl = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {}
|
||||
if (cl == null) {
|
||||
cl = ClassUtils.class.getClassLoader();
|
||||
if (cl == null) {
|
||||
try {
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {}
|
||||
}
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T>T newInstance(String className) {
|
||||
try {
|
||||
return (T) ClassUtils.loadClass(className).newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class<?> loadClass(String className) {
|
||||
ClassLoader loader = getDefaultClassLoader();
|
||||
if(loader==null) throw new RuntimeException("ClassLoader为空");
|
||||
try {
|
||||
return loader.loadClass(className);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> loadClass(ClassLoader loader,String className) {
|
||||
try {
|
||||
if(loader==null) {
|
||||
return loadClass(className);
|
||||
}
|
||||
return loader.loadClass(className);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class CollectionUtils{
|
||||
|
||||
public static <T>List<T> newVector(){
|
||||
return new Vector<T>();
|
||||
}
|
||||
|
||||
public static <T>List<T> newConcurrentArrayList(){
|
||||
return new CopyOnWriteArrayList<T>();
|
||||
}
|
||||
|
||||
public static <T>List<T> newArrayList(){
|
||||
return new ArrayList<T>();
|
||||
}
|
||||
|
||||
public static <T>List<T> newArrayList(int size){
|
||||
return new ArrayList<T>(size);
|
||||
}
|
||||
|
||||
public static <T>List<T> newLinkedList(){
|
||||
return new LinkedList<T>();
|
||||
}
|
||||
|
||||
|
||||
public static <V, K>Map<K,V> newHashMap(){
|
||||
return new HashMap<K,V>();
|
||||
}
|
||||
|
||||
public static <V, K> Map<K,V> newHashtable(){
|
||||
return new Hashtable<K,V>();
|
||||
}
|
||||
|
||||
public static <V, K> Map<K,V> newIdentityHashMap(){
|
||||
return new IdentityHashMap<K,V>();
|
||||
}
|
||||
|
||||
public static <V, K> Map<K,V> newLinkedHashMap(){
|
||||
return new LinkedHashMap<K,V>();
|
||||
}
|
||||
|
||||
public static <V, K> Map<K,V> newTreeMap(){
|
||||
return new TreeMap<K,V>();
|
||||
}
|
||||
|
||||
public static <V, K> Map<K,V> newWeakHashMap(){
|
||||
return new WeakHashMap<K,V>();
|
||||
}
|
||||
|
||||
public static <V, K> Map<K,V> newConcurrentHashMap(){
|
||||
return new ConcurrentHashMap<K,V>();
|
||||
}
|
||||
|
||||
public static Properties newProperties(){
|
||||
return new Properties();
|
||||
}
|
||||
|
||||
|
||||
public static <T> Set<T> newHashSet(){
|
||||
return new HashSet<T>();
|
||||
}
|
||||
|
||||
public static <T> Set<T> newLinkedHashSet(){
|
||||
return new LinkedHashSet<T>();
|
||||
}
|
||||
|
||||
public static <T> Set<T> newTreeSet(){
|
||||
return new TreeSet<T>();
|
||||
}
|
||||
|
||||
public static <T> Set<T> newConcurrentSet(){
|
||||
return new ConcurrentSkipListSet<T>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] toArray(Collection<T> collection) {
|
||||
if(collection!=null) {
|
||||
return (T[]) collection.toArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(Collection<?> collection) {
|
||||
return collection==null || collection.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isNotEmpty(Collection<?> collection) {
|
||||
return collection!=null && !collection.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,873 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
import java.sql.Date;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
|
||||
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
|
||||
import com.esotericsoftware.kryo.kryo5.minlog.Log;
|
||||
import com.google.api.client.util.Sets;
|
||||
import com.pictc.annotations.datalog.JoinCaseType;
|
||||
import com.pictc.annotations.datalog.JoinValueType;
|
||||
import com.pictc.annotations.datalog.LogJoin;
|
||||
import com.pictc.annotations.datalog.LogJoinColumn;
|
||||
import com.pictc.annotations.datalog.ValueDirectionType;
|
||||
import com.pictc.converts.ConverUtil;
|
||||
import com.pictc.datalog.LogFieldInfo;
|
||||
import com.pictc.datalog.LogJoinInfo;
|
||||
import com.pictc.datalog.LogTableInfo;
|
||||
import com.pictc.exceptions.OrmException;
|
||||
import com.pictc.jdbc.JdbcContext;
|
||||
import com.pictc.jdbc.ResultSetUtils;
|
||||
import com.pictc.jdbc.model.JdbcParam;
|
||||
import com.xjrsoft.common.utils.SecureUtil;
|
||||
import com.xjrsoft.module.datalog.entity.DataChangeLog;
|
||||
import com.xjrsoft.module.datalog.entity.json.FieldChange;
|
||||
import com.xjrsoft.module.datalog.service.DatalogService;
|
||||
import com.xjrsoft.module.datalog.vo.OperationType;
|
||||
import com.xjrsoft.module.organization.dto.UserDto;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@SuppressWarnings({"unused","rawtypes","unchecked"})
|
||||
@Component
|
||||
public class DataLogTools {
|
||||
|
||||
private static Map<Class<?>,LogTableInfo> annotations = Maps.newHashMap();
|
||||
|
||||
private static Set<String> logTables = null;
|
||||
|
||||
private static Object lock = new Object();
|
||||
|
||||
public static final String SQL_HAS_TABLE = "select count(*) from log_table_info where tbl_name = ?";
|
||||
|
||||
public static final String SQL_INST_TABLE = "INSERT INTO log_table_info (tbl_name) VALUES (?);";
|
||||
|
||||
public static final String SQL_LOG_TABLE_LIST = "select tbl_name FROM log_table_info";
|
||||
|
||||
public static final String SQL_PLACEHOLDER = "\\$\\{TBL_NAME\\}";
|
||||
|
||||
public static final String[] SQL_CREATE_TABLE = {
|
||||
"CREATE TABLE ${TBL_NAME} (\r\n" +
|
||||
" id VARCHAR(32) NOT NULL,\r\n" +
|
||||
" flow_id VARCHAR(32),\r\n" +
|
||||
" pid VARCHAR(32) DEFAULT '#',\r\n" +
|
||||
" entity_class_name VARCHAR(255),\r\n" +
|
||||
" bus_name VARCHAR(100),\r\n" +
|
||||
" entity_id BIGINT,\r\n" +
|
||||
" field_changes TEXT,\r\n" +
|
||||
" operation_type VARCHAR(20),\r\n" +
|
||||
" operator_id BIGINT,\r\n" +
|
||||
" operator_name VARCHAR(100),\r\n" +
|
||||
" operation_time TIMESTAMPTZ,\r\n" +
|
||||
" operation_ip VARCHAR(50),\r\n" +
|
||||
" PRIMARY KEY (id)\r\n" +
|
||||
" );",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"flow_id\" IS '流水id';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"pid\" IS '父表ID,根节点#';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"entity_class_name\" IS '实体类名称(全类名)';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"bus_name\" IS '业务名称';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"entity_id\" IS '操作的实体ID(主键值)';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"field_changes\" IS '属性值记录(JSON格式存储字段变更详情)';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"operation_type\" IS '操作类型:INSERT-新增,UPDATE-修改,DELETE-删除';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"operator_id\" IS '操作人ID';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"operator_name\" IS '操作人姓名';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"operation_time\" IS '操作时间';",
|
||||
"COMMENT ON COLUMN ${TBL_NAME}.\"operation_ip\" IS '操作IP地址';",
|
||||
"CREATE INDEX idx_${TBL_NAME}_enityt_id ON ${TBL_NAME} (entity_id)"
|
||||
};
|
||||
|
||||
public static final String SQL_INSERT = "INSERT INTO ${TBL_NAME} (\r\n" +
|
||||
" id, flow_id, pid, entity_class_name, bus_name, \r\n" +
|
||||
" entity_id, field_changes, operation_type, operator_id, \r\n" +
|
||||
" operator_name, operation_time, operation_ip\r\n" +
|
||||
") VALUES (?,?,?,?,?,?,?,?,?,?,?,?);";
|
||||
|
||||
|
||||
public static final String SQL_LIST = "SELECT * FROM ${TBL_NAME} WHERE entity_id = ? ORDER BY operation_time DESC, flow_id DESC";
|
||||
|
||||
public static final Set<String> excludeFields = SetUtils.of("tenantId");
|
||||
|
||||
|
||||
public static DataChangeLog createLog(Class<?> klazz,OperationType type) {
|
||||
DataChangeLog createLog = createLog(klazz, type, null);
|
||||
return createLog.setFlowId(IdUtil.getSnowflakeNextIdStr());
|
||||
}
|
||||
|
||||
public static DataChangeLog createLog(Class<?> klazz,OperationType type,DataChangeLog parent) {
|
||||
UserDto currentUser = SecureUtil.getCurrentUser();
|
||||
LogTableInfo annotation = getAnnotation(klazz);
|
||||
//变更人的IP地址
|
||||
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
DataChangeLog changeLog = new DataChangeLog()
|
||||
.setEntityClassName(klazz.getCanonicalName())
|
||||
.setBusName(annotation.getName())
|
||||
.setId(IdUtil.getSnowflakeNextIdStr())
|
||||
.setOperationIp(ipAddress)
|
||||
.setOperationType(type)
|
||||
.setOperatorId(currentUser.getId())
|
||||
.setOperatorName(currentUser.getName())
|
||||
.setOperationTime(LocalDateTime.now());
|
||||
if(parent!=null) {
|
||||
changeLog.setFlowId(parent.getFlowId());
|
||||
changeLog.setPid(parent.getId());
|
||||
}
|
||||
return changeLog;
|
||||
}
|
||||
|
||||
public static LogTableInfo getAnnotation(Class<?> klazz) {
|
||||
synchronized (lock) {
|
||||
if(annotations.containsKey(klazz)) {
|
||||
return annotations.get(klazz);
|
||||
}
|
||||
LogTableInfo tableInfo = new LogTableInfo(klazz);
|
||||
if(tableInfo.isValid()) {
|
||||
annotations.put(klazz,tableInfo);
|
||||
return tableInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T>T insert(T entity) {
|
||||
Class<? extends Object> klazz = entity.getClass();
|
||||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||||
DataChangeLog datalog = createLog(klazz,OperationType.INSERT);
|
||||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||||
initJoinValue(entity,tabInfo,null);
|
||||
Long idValue = tabInfo.getIdValue(entity);
|
||||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||||
mapper.insert(BeanUtil.toBean(entity,tabInfo.getEntityType()));
|
||||
datalog.setEntityId(idValue);
|
||||
buildFields(datalog,tabInfo,entity,null);
|
||||
logs.add(datalog);
|
||||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||||
if(CollectionUtils.isNotEmpty(joins)) {
|
||||
for (LogJoinInfo join : joins) {
|
||||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||||
buildJoins(logs,datalog,OperationType.INSERT,tabInfo,join,entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
saveLogs(tabInfo,logs);
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
public static <T>T update(T dto) {
|
||||
Class<? extends Object> klazz = dto.getClass();
|
||||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||||
|
||||
Long idValue = tabInfo.getIdValue(dto);
|
||||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||||
Object old = findById(klazz, idValue);
|
||||
if(old!=null) {
|
||||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||||
DataChangeLog datalog = createLog(klazz,OperationType.UPDATE);
|
||||
initJoinValue(dto,tabInfo,null);
|
||||
|
||||
mapper.updateById(tabInfo.toEntity(dto));
|
||||
datalog.setEntityId(idValue);
|
||||
buildFields(datalog,tabInfo,dto,old);
|
||||
logs.add(datalog);
|
||||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||||
for (LogJoinInfo join : joins) {
|
||||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||||
buildJoins(logs,datalog,OperationType.UPDATE,tabInfo,join,dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
saveLogs(tabInfo,logs);
|
||||
}else {
|
||||
throw new OrmException("数据不存在");
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
||||
public static <T>T delete(T entity) {
|
||||
Class<? extends Object> klazz = entity.getClass();
|
||||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||||
|
||||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||||
Long idValue = tabInfo.getIdValue(entity);
|
||||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||||
DataChangeLog datalog = createLog(klazz,OperationType.DELETE);
|
||||
datalog.setEntityId(idValue);
|
||||
buildFields(datalog,tabInfo,entity,null);
|
||||
logs.add(datalog);
|
||||
delete(entity, tabInfo, mapper);
|
||||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||||
for (LogJoinInfo join : joins) {
|
||||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||||
buildJoins(logs,datalog,OperationType.DELETE,tabInfo,join,entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
saveLogs(tabInfo,logs);
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
public static <T>T deleteById(Class<T> klazz,Long id) {
|
||||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||||
T entity = findById(klazz, id);
|
||||
if(entity==null) return null;
|
||||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||||
|
||||
delete(entity, tabInfo, mapper);
|
||||
DataChangeLog datalog = createLog(klazz,OperationType.DELETE);
|
||||
datalog.setEntityId(id);
|
||||
buildFields(datalog,tabInfo,entity,null);
|
||||
logs.add(datalog);
|
||||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||||
for (LogJoinInfo join : joins) {
|
||||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||||
buildJoins(logs,datalog,OperationType.DELETE,tabInfo,join,entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
saveLogs(tabInfo,logs);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static boolean deleteByIds(Class<?> klazz, @Valid List<Long> ids) {
|
||||
for (Long id : ids) {
|
||||
deleteById(klazz, id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <T>T findById(Class<T> klazz,Serializable id){
|
||||
return findById(klazz,id,false);
|
||||
}
|
||||
|
||||
public static <T>T findById(Class<T> klazz,Serializable id,boolean full){
|
||||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||||
Object old = mapper.selectById(id);
|
||||
if(old==null) return null;
|
||||
T dto = (T) tabInfo.toDto(old);
|
||||
initJoinValues(tabInfo,dto,SetUtils.of(klazz), full);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public static void initJoinValues(LogTableInfo tabInfo,Object entity,Set<Class<?>> classPath,boolean full){
|
||||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||||
for (LogJoinInfo join : joins) {
|
||||
LogTableInfo joinTable = join.getTableInfo();
|
||||
if(full) {
|
||||
if(join.isList()) {
|
||||
List joinList = getJoinList(joinTable,join, mapper,tabInfo,entity);
|
||||
if(CollectionUtils.isNotEmpty(joinList)) {
|
||||
List listVal = new ArrayList();
|
||||
for (Object item : joinList) {
|
||||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||||
if(!classPath.contains(joinTable.getKlazz())) {
|
||||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||||
classes.add(joinTable.getKlazz());
|
||||
initJoinValues(joinTable,voOjb,classes,full);
|
||||
}
|
||||
listVal.add(voOjb);
|
||||
}
|
||||
tabInfo.setFieldValue(entity,join.getField(),listVal);
|
||||
}
|
||||
}else {
|
||||
Object objVal = getJoinObj(joinTable,join, mapper,tabInfo,entity);
|
||||
Object voOjb = BeanUtil.toBean(objVal,joinTable.getKlazz());
|
||||
if(!classPath.contains(joinTable.getKlazz())) {
|
||||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||||
classes.add(joinTable.getKlazz());
|
||||
initJoinValues(joinTable,voOjb,classes,full);
|
||||
}
|
||||
tabInfo.setFieldValue(entity,join.getField(),voOjb);
|
||||
}
|
||||
}else {
|
||||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||||
if(join.isList()) {
|
||||
List joinList = getJoinList(joinTable,join, mapper,tabInfo,entity);
|
||||
if(CollectionUtils.isNotEmpty(joinList)) {
|
||||
List listVal = new ArrayList();
|
||||
for (Object item : joinList) {
|
||||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||||
if(!classPath.contains(joinTable.getKlazz())) {
|
||||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||||
classes.add(joinTable.getKlazz());
|
||||
initJoinValues(joinTable,voOjb,classes,full);
|
||||
}
|
||||
listVal.add(voOjb);
|
||||
}
|
||||
tabInfo.setFieldValue(entity,join.getField(),listVal);
|
||||
}
|
||||
}else {
|
||||
Object objVal = getJoinObj(joinTable,join, mapper,tabInfo,entity);
|
||||
Object voOjb = BeanUtil.toBean(objVal,joinTable.getKlazz());
|
||||
if(!classPath.contains(joinTable.getKlazz())) {
|
||||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||||
classes.add(joinTable.getKlazz());
|
||||
initJoinValues(joinTable,voOjb,classes,full);
|
||||
}
|
||||
tabInfo.setFieldValue(entity,join.getField(),voOjb);
|
||||
}
|
||||
}
|
||||
}
|
||||
classPath.add(joinTable.getKlazz());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void delete(Object entity,LogTableInfo tableinfo,BaseMapper mapper){
|
||||
Long idValue = tableinfo.getIdValue(entity);
|
||||
if(idValue!=null && idValue > 0) {
|
||||
// QueryChainWrapper wrapper = new QueryChainWrapper(mapper);
|
||||
// wrapper.eq(tableinfo.getIdColumn(),tableinfo.getIdValue(entity));
|
||||
// mapper.delete(wrapper);
|
||||
mapper.deleteById(idValue);
|
||||
}else {
|
||||
throw new RuntimeException("删除数据时,表【"+tableinfo.getName()+"】的主键为空,删除失败!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static <T>void initJoinValue(T entity,LogTableInfo tabInfo,Set<Class<?>> classes) {
|
||||
if(classes==null) {
|
||||
classes = CollectionUtils.newHashSet();
|
||||
}
|
||||
if(classes.contains(tabInfo.getEntityType())) return ;
|
||||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||||
Long idValue = tabInfo.getIdValue(entity);
|
||||
if(idValue == null || idValue <=0) {
|
||||
idValue = IdWorker.getId();
|
||||
tabInfo.setIdValue(entity,idValue);
|
||||
}
|
||||
classes.add(tabInfo.getEntityType());
|
||||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||||
for (LogJoinInfo join : joins) {
|
||||
LogJoinColumn[] columns = join.getJoin().columns();
|
||||
LogTableInfo joinTable = join.getTableInfo();
|
||||
if(classes.contains(joinTable.getEntityType())) {
|
||||
continue;
|
||||
}
|
||||
Object joinValue = tabInfo.getFieldValue(entity, join.getField());
|
||||
if(joinValue!=null && joinValue instanceof List) {
|
||||
List listValue = (List) joinValue;
|
||||
for (LogJoinColumn joinColumn : columns) {
|
||||
if (joinColumn.valueType() == JoinValueType.FEILD
|
||||
&& joinColumn.valueDirection() == ValueDirectionType.RIGHT) {
|
||||
Object joinFieldValue = tabInfo.getFieldValue(entity, joinColumn.field());
|
||||
for (Object item : listValue) {
|
||||
Long idValue2 = joinTable.getIdValue(item);
|
||||
if(idValue2==null || idValue2 <=0) {
|
||||
joinTable.setIdValue(joinValue, IdWorker.getId());
|
||||
}
|
||||
joinTable.setFieldValue(item, joinColumn.relatedField(), joinFieldValue);
|
||||
Set<Class<?>> joinClasses = SetUtils.ofCollection(classes);
|
||||
initJoinValue(item,joinTable,joinClasses);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
Long idValue2 = joinTable.getIdValue(joinValue);
|
||||
if(idValue2==null || idValue2 <=0) {
|
||||
joinTable.setIdValue(joinValue,idValue2);
|
||||
}
|
||||
for (LogJoinColumn joinColumn : columns) {
|
||||
if(joinColumn.valueType()==JoinValueType.FEILD && joinColumn.valueDirection()==ValueDirectionType.LEFT) {
|
||||
Object joinFieldValue = joinTable.getFieldValue(joinValue, joinColumn.relatedField());
|
||||
tabInfo.setFieldValue(entity, joinColumn.field(),joinFieldValue);
|
||||
}else {
|
||||
Object joinFieldValue = tabInfo.getFieldValue(entity, joinColumn.field());
|
||||
joinTable.setFieldValue(joinValue, joinColumn.relatedField(), joinFieldValue);
|
||||
}
|
||||
}
|
||||
Set<Class<?>> joinClasses = SetUtils.ofCollection(classes);
|
||||
initJoinValue(joinValue,joinTable,joinClasses);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T>void buildJoins(List<DataChangeLog> logs,DataChangeLog parent,OperationType type,LogTableInfo parentInfo, LogJoinInfo join, T entity) {
|
||||
LogTableInfo joinTable = join.getTableInfo();
|
||||
BaseMapper mapper = MybatisTools.getMapper(joinTable.getEntityType());
|
||||
if(joinTable!=null) {
|
||||
if(join.isList()) {
|
||||
List listValue = BeanUtils.getFieldValue(join.getField(),entity);
|
||||
if(CollectionUtils.isNotEmpty(listValue)) {
|
||||
if(type==OperationType.INSERT || type==OperationType.DELETE) {
|
||||
if(type==OperationType.INSERT) {
|
||||
for (Object item : listValue) {
|
||||
Long idValue = joinTable.getIdValue(item);
|
||||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||||
datalog.setEntityId(idValue);
|
||||
Object bean = BeanUtil.toBean(item,joinTable.getEntityType());
|
||||
mapper.insert(bean);
|
||||
buildFields(datalog,joinTable,item,null);
|
||||
logs.add(datalog);
|
||||
}
|
||||
}else {
|
||||
for (Object item : listValue) {
|
||||
Long idValue = joinTable.getIdValue(item);
|
||||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||||
datalog.setEntityId(idValue);
|
||||
delete(voOjb, joinTable, mapper);
|
||||
buildFields(datalog,joinTable,voOjb,null);
|
||||
logs.add(datalog);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
for (Object item : listValue) {
|
||||
Long idValue = joinTable.getIdValue(item);
|
||||
Object nval = BeanUtil.toBean(item,joinTable.getKlazz());
|
||||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||||
datalog.setEntityId(idValue);
|
||||
Object old = findById(join.getTargetClass(), idValue);
|
||||
mapper.updateById(nval);
|
||||
buildFields(datalog,joinTable,nval,old);
|
||||
logs.add(datalog);
|
||||
}
|
||||
}
|
||||
} else if(type==OperationType.UPDATE || type==OperationType.DELETE){
|
||||
//进行修改或者删除时,级联对象为空时,需要删除旧数据
|
||||
List oldList = getJoinList(joinTable, join, mapper, parentInfo, entity);
|
||||
if(oldList!=null) {
|
||||
for (Object item : oldList) {
|
||||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||||
Long idValue = joinTable.getIdValue(item);
|
||||
DataChangeLog datalog = createLog(join.getTargetClass(),OperationType.DELETE,parent);
|
||||
datalog.setEntityId(idValue);
|
||||
delete(voOjb, joinTable, mapper);
|
||||
buildFields(datalog,joinTable,voOjb,null);
|
||||
logs.add(datalog);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Object val = BeanUtils.getFieldValue(join.getField(),entity);
|
||||
if(val!=null) {
|
||||
Long idValue = joinTable.getIdValue(val);
|
||||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||||
logs.add(datalog);
|
||||
datalog.setEntityId(idValue);
|
||||
if(type==OperationType.INSERT || type==OperationType.DELETE) {
|
||||
if(type==OperationType.INSERT) {
|
||||
mapper.insert(val);
|
||||
}else {
|
||||
delete(val, joinTable, mapper);
|
||||
}
|
||||
buildFields(datalog,joinTable, val, null);
|
||||
}else {
|
||||
Object old = mapper.selectById(idValue);
|
||||
buildFields(datalog,joinTable,val,old);
|
||||
Object bean = BeanUtil.toBean(val,joinTable.getEntityType());
|
||||
mapper.updateById(bean);
|
||||
}
|
||||
} else if(type==OperationType.UPDATE || type==OperationType.DELETE){
|
||||
//进行修改或者删除时,级联对象为空时,需要删除旧数据
|
||||
Object old = getJoinObj(joinTable, join, mapper, parentInfo, entity);
|
||||
if(old!=null) {
|
||||
Object voOjb = BeanUtil.toBean(old,joinTable.getKlazz());
|
||||
Long idValue = joinTable.getIdValue(old);
|
||||
DataChangeLog datalog = createLog(join.getTargetClass(),OperationType.DELETE,parent);
|
||||
datalog.setEntityId(idValue);
|
||||
delete(voOjb, joinTable, mapper);
|
||||
buildFields(datalog,joinTable,voOjb,null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List getJoinList(LogTableInfo joinTable, LogJoinInfo join, BaseMapper mapper,
|
||||
LogTableInfo parentInfo,Object parent) {
|
||||
LogJoin joinAnnotation = join.getJoin();
|
||||
LogJoinColumn[] columns = joinAnnotation.columns();
|
||||
QueryChainWrapper queryWrapper = new QueryChainWrapper(mapper);
|
||||
for (LogJoinColumn joinCol : columns) {
|
||||
if(joinCol.valueType()==JoinValueType.FEILD) {
|
||||
Object value = parentInfo.getFieldValue(parent,joinCol.field());
|
||||
if(value==null) return null;
|
||||
queryWrapper.eq(joinTable.getColumn(joinCol.relatedField()),value);
|
||||
}else {
|
||||
if(StringUtils.isNotEmpty(joinCol.relatedField())) {
|
||||
queryWrapper.eq(joinTable.getColumn(joinCol.relatedField()),ConverUtil.jsonToValue(joinCol.staticType(),joinCol.staticValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return mapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
private static Object getJoinObj(LogTableInfo joinTable,LogJoinInfo join,BaseMapper mapper,LogTableInfo parentInfo,Object parent) {
|
||||
LogJoin joinAnnotation = join.getJoin();
|
||||
LogJoinColumn[] columns = joinAnnotation.columns();
|
||||
QueryChainWrapper query = new QueryChainWrapper(mapper);
|
||||
for (LogJoinColumn joinCol : columns) {
|
||||
if(joinCol.valueType()==JoinValueType.FEILD) {
|
||||
Object value = parentInfo.getFieldValue(parent,joinCol.field());
|
||||
if(value==null) return null;
|
||||
query.eq(joinTable.getColumn(joinCol.relatedField()),value);
|
||||
}else {
|
||||
if(StringUtils.isNotEmpty(joinCol.relatedField())) {
|
||||
query.eq(joinTable.getColumn(joinCol.relatedField()),ConverUtil.jsonToValue(joinCol.staticType(),joinCol.staticValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return mapper.selectObjs(query);
|
||||
}
|
||||
|
||||
|
||||
private static <T>void buildFields(DataChangeLog datalog,LogTableInfo tableInfo,T entity,T old) {
|
||||
List<LogFieldInfo> fields = tableInfo.getFields();
|
||||
for (LogFieldInfo item : fields) {
|
||||
if(excludeFields.contains(item.getFieldName())) {
|
||||
continue;
|
||||
}
|
||||
FieldChange change = new FieldChange();
|
||||
change.setField(item.getFieldName());
|
||||
change.setName(item.getName());
|
||||
if(old!=null) {
|
||||
Object newVal = BeanUtils.getFieldValue(item.getField(),entity);
|
||||
Object oldVal = BeanUtils.getFieldValue(item.getField(),old);
|
||||
boolean flag = false;
|
||||
if((newVal==null && oldVal!=null) || (newVal!=null && oldVal==null)) {
|
||||
flag = true;
|
||||
}else if(newVal!=null && oldVal!=null && !newVal.equals(oldVal)) {
|
||||
flag = true;
|
||||
}
|
||||
change.setOldValue(parseValue(oldVal,item.getJavaType()));
|
||||
change.setNewValue(parseValue(newVal,item.getJavaType()));
|
||||
if(flag) {
|
||||
datalog.addFiledChnage(change);
|
||||
}
|
||||
}else {
|
||||
change.setNewValue(parseValue(BeanUtils.getFieldValue(item.getField(),entity),item.getField().getType()));
|
||||
datalog.addFiledChnage(change);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String parseValue(Object val,Class<?> type) {
|
||||
if(val==null) return null;
|
||||
if (type.equals(String.class)) {
|
||||
return String.class.cast(val);
|
||||
|
||||
} else if (type.equals(BigDecimal.class)) {
|
||||
return BigDecimal.class.cast(val).toString();
|
||||
|
||||
} else if (type.equals(BigInteger.class)) {
|
||||
return BigInteger.class.cast(val).toString();
|
||||
|
||||
} else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)
|
||||
|| type.equals(Integer.class) || type.equals(Integer.TYPE)
|
||||
|| type.equals(Long.class) || type.equals(Long.TYPE)
|
||||
|| type.equals(Float.class) || type.equals(Float.TYPE)
|
||||
|| type.equals(Double.class) || type.equals(Double.TYPE)
|
||||
) {
|
||||
return val.toString();
|
||||
|
||||
} else if (type.equals(byte[].class)) {
|
||||
byte[] buf = (byte[])val;
|
||||
return new String(buf, Charset.forName("UTF-8"));
|
||||
|
||||
} else if (type.equals(Date.class) || type.equals(Time.class) || type.equals(Timestamp.class) || type.equals(java.util.Date.class)) {
|
||||
String fmt = null;
|
||||
if(type.equals(Date.class)) {
|
||||
fmt = DateUtils.GENERAL;
|
||||
}else if(type.equals(Time.class)) {
|
||||
fmt = DateUtils.FMT_TIME;
|
||||
}else {
|
||||
fmt = DateUtils.LONG_FORMAT;
|
||||
}
|
||||
return DateUtils.format(java.util.Date.class.cast(val),fmt);
|
||||
}else if (type.equals(LocalDate.class)) {
|
||||
return DateUtils.format(LocalDate.class.cast(val));
|
||||
|
||||
} else if (type.equals(LocalDateTime.class)) {
|
||||
return DateUtils.format(LocalDateTime.class.cast(val));
|
||||
|
||||
} else if (type.equals(LocalTime.class)) {
|
||||
return DateUtils.format(LocalDateTime.class.cast(val));
|
||||
} else if (type.equals(OffsetDateTime.class)) {
|
||||
return DateUtils.format(OffsetDateTime.class.cast(val));
|
||||
|
||||
} else if (type.equals(OffsetTime.class)) {
|
||||
return DateUtils.format(OffsetTime.class.cast(val));
|
||||
}else if(type.isEnum()) {
|
||||
return val.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 保存数据日志
|
||||
* @param logs 日志记录对象
|
||||
* @return void 返回类型
|
||||
*/
|
||||
public static void saveLogs(LogTableInfo tableInfo,List<DataChangeLog> logs) {
|
||||
String tableName = parseLogTableName(tableInfo);
|
||||
initTable(tableName);
|
||||
String sql = parseSql(SQL_INSERT, tableName);
|
||||
List<List<JdbcParam>> batchParams = CollectionUtils.newArrayList();
|
||||
for (DataChangeLog log : logs) {
|
||||
List<JdbcParam> params = CollectionUtils.newArrayList();
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getId()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getFlowId()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getPid()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getEntityClassName()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getBusName()));
|
||||
params.add(JdbcParam.of(Types.BIGINT,long.class, log.getEntityId()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class,JSON.toJSONString(log.getFieldChanges())));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class,log.getOperationType().name()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,long.class,log.getOperatorId()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class,log.getOperatorName()));
|
||||
params.add(JdbcParam.of(Types.TIMESTAMP,Timestamp.class,log.getOperationTime()));
|
||||
params.add(JdbcParam.of(Types.VARCHAR,String.class,log.getOperationIp()));
|
||||
batchParams.add(params);
|
||||
}
|
||||
executeBatch(sql, batchParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 初始化日志表
|
||||
* @param tableName
|
||||
* @return void 返回类型
|
||||
*/
|
||||
private synchronized static boolean initTable(String tableName) {
|
||||
synchronized (lock) {
|
||||
//如果没有日志表时,重新创建
|
||||
if(!hasTable(tableName)) {
|
||||
for (int i = 0; i < SQL_CREATE_TABLE.length; i++) {
|
||||
execute(parseSql(SQL_CREATE_TABLE[i], tableName));
|
||||
}
|
||||
//将表名进行记录
|
||||
executeUpdate(SQL_INST_TABLE,ListUtils.ofArray(JdbcParam.ofString(tableName)));
|
||||
logTables.add(tableName);
|
||||
log.info("新增数据日志表:{}",tableName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static String parseSql(String sql,String tableName) {
|
||||
return sql.replaceAll(SQL_PLACEHOLDER,tableName);
|
||||
}
|
||||
|
||||
private static boolean hasTable(String tableName) {
|
||||
synchronized (lock) {
|
||||
if(logTables==null) {
|
||||
List<String> tabs = queryListPrimitive(SQL_LOG_TABLE_LIST,String.class, null);
|
||||
logTables = new HashSet<String>(tabs);
|
||||
}
|
||||
if(logTables.contains(tableName)) return true;
|
||||
Long count = queryPrimitive(SQL_HAS_TABLE,long.class,Lists.newArrayList(JdbcParam.ofString(tableName)));
|
||||
boolean flag = count!=null && count > 0;
|
||||
if(flag) {
|
||||
logTables.add(tableName);
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 根据数据id获取操作日志
|
||||
* @param klass 数据java类型
|
||||
* @param dataId 数据id
|
||||
* @return List<DataChangeLog> 返回类型
|
||||
*/
|
||||
public static <T>List<DataChangeLog> findLogsByEntityId(Class<T> klass,@NonNull Long dataId) {
|
||||
LogTableInfo tabInfo = getAnnotation(klass);
|
||||
String tableName = parseLogTableName(tabInfo);
|
||||
if(initTable(tableName)) {
|
||||
return null;
|
||||
}
|
||||
List<DataChangeLog> result = CollectionUtils.newArrayList();
|
||||
String sql = parseSql(SQL_LIST, tableName);
|
||||
JdbcContext context = null;
|
||||
try {
|
||||
context = new JdbcContext(true,false);
|
||||
context.init(sql);
|
||||
context.setParams(ListUtils.ofArray(JdbcParam.ofLong(dataId)));
|
||||
ResultSet set = context.executeQuery();
|
||||
Map<String, String> names = ResultSetUtils.getMapColumns(set);
|
||||
while (set.next()) {
|
||||
DataChangeLog log = new DataChangeLog();
|
||||
log.setId(set.getString("id"));
|
||||
log.setFlowId(set.getString("flow_id"));
|
||||
log.setPid(set.getString("pid"));
|
||||
log.setEntityClassName(set.getString("entity_class_name"));
|
||||
log.setBusName(set.getString("bus_name"));
|
||||
log.setEntityId(set.getLong("entity_id"));
|
||||
log.setOperationType(OperationType.valueOf(set.getString("operation_type")));
|
||||
log.setOperationIp(set.getString("operation_ip"));
|
||||
log.setOperatorId(set.getLong("operator_id"));
|
||||
log.setOperatorName(set.getString("operator_name"));
|
||||
log.setOperationTime(ResultSetUtils.getObject(set,"operation_time",LocalDateTime.class));
|
||||
String json = set.getString("field_changes");
|
||||
if(StringUtils.isNotEmpty(json)) {
|
||||
log.setFieldChanges(JSON.parseArray(json).toJavaList(FieldChange.class));
|
||||
}
|
||||
result.add(log);
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw context.createException(e);
|
||||
} finally {
|
||||
context.end();
|
||||
}
|
||||
}
|
||||
|
||||
private static String parseLogTableName(LogTableInfo tableInfo) {
|
||||
String name = tableInfo.getTableName();
|
||||
return "datalog_"+name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行ddl语句
|
||||
* */
|
||||
public static boolean execute(String sql){
|
||||
JdbcContext context = null;
|
||||
try {
|
||||
context = new JdbcContext(true,true);
|
||||
context.init(sql);
|
||||
return context.execute();
|
||||
} catch (SQLException e) {
|
||||
throw context.createException(e);
|
||||
}finally {
|
||||
context.end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改操作
|
||||
* */
|
||||
public static int executeUpdate(String sql,List<JdbcParam> params){
|
||||
JdbcContext context = null;
|
||||
try {
|
||||
context = new JdbcContext(true,true);
|
||||
context.init(sql);
|
||||
context.setParams(params);
|
||||
return context.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw context.createException(e);
|
||||
}finally {
|
||||
context.end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作
|
||||
* */
|
||||
public static int executeBatch(String sql,List<List<JdbcParam>> batchParams){
|
||||
JdbcContext context = null;
|
||||
try {
|
||||
context = new JdbcContext(true,true);
|
||||
context.init(sql);
|
||||
context.setBatchParams(batchParams);
|
||||
return context.executeBatch(-1);
|
||||
} catch (SQLException e) {
|
||||
throw context.createException(e);
|
||||
}finally {
|
||||
context.end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询基础数据类型
|
||||
* */
|
||||
public static <T>T queryPrimitive(String sql,Class<T> type,List<JdbcParam> params){
|
||||
JdbcContext context = null;
|
||||
try {
|
||||
context = new JdbcContext(true,true);
|
||||
context.init(sql);
|
||||
context.setParams(params);
|
||||
ResultSet set = context.executeQuery();
|
||||
while (set.next()) {
|
||||
return ResultSetUtils.getObject(set,1,type);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw context.createException(e);
|
||||
}finally {
|
||||
context.end();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询基础数据类型
|
||||
* */
|
||||
public static <T>List<T> queryListPrimitive(String sql,Class<T> type,List<JdbcParam> params){
|
||||
JdbcContext context = null;
|
||||
try {
|
||||
context = new JdbcContext(true,true);
|
||||
context.init(sql);
|
||||
context.setParams(params);
|
||||
ResultSet set = context.executeQuery();
|
||||
List<T> res = CollectionUtils.newArrayList();
|
||||
while (set.next()) {
|
||||
res.add(ResultSetUtils.getObject(set,1,type));
|
||||
}
|
||||
return res;
|
||||
} catch (SQLException e) {
|
||||
throw context.createException(e);
|
||||
}finally {
|
||||
context.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,448 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Calendar.DATE;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class DateUtils {
|
||||
|
||||
public static final String GENERAL = "yyyy-MM-dd";
|
||||
|
||||
public static final String FMT_TIME = "HH:mm:ss";
|
||||
|
||||
public static final String FMT_OFFSET_DATETIME = "yyyy-MM-dd HH:mm:ssXXX";
|
||||
|
||||
public static final String FMT_OFFSET_TIME = "HH:mm:ssXXX";
|
||||
|
||||
public static final String GENERAL_YYYYMMDD = "yyyyMMdd";
|
||||
|
||||
public static final String GENERAL_YYYYMMDDHHMMSS = "yyyyMMddHHmmSS";
|
||||
|
||||
public static final String LONG_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
public final static DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern(LONG_FORMAT);
|
||||
|
||||
// 针对GMT格式的日期转换格式
|
||||
public static final String GMT_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'";
|
||||
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat(LONG_FORMAT);
|
||||
|
||||
private static final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(GENERAL);
|
||||
|
||||
public static final ZoneId zone = ZoneId.of("GMT+8");
|
||||
|
||||
private static Set<Class<?>> dates = CollectionUtils.newHashSet();
|
||||
|
||||
static {
|
||||
dates.add(Date.class);
|
||||
dates.add(Time.class);
|
||||
dates.add(Timestamp.class);
|
||||
dates.add(java.util.Date.class);
|
||||
}
|
||||
|
||||
public static boolean isDate(Class<?> type) {
|
||||
return dates.contains(type);
|
||||
}
|
||||
|
||||
public static String formatDate(Date date) {
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public static Date formatDate2Date(Date date) {
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String format = sdf.format(date);
|
||||
try {
|
||||
return sdf.parse(format);
|
||||
} catch (ParseException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 按传入的格式化规则格式化传入的日期
|
||||
*
|
||||
* @param date : 传入日期对象
|
||||
* @param dateFormat : 格式化规则(如:yyyy-MM-dd,yyyyMMdd等,如果传空或NULL则默认为yyyy-MM-dd)
|
||||
* @return String
|
||||
* @author 张江立
|
||||
*/
|
||||
public static String formatDate(Date date, String dateFormat) {
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null == dateFormat || "".equals(dateFormat)) {
|
||||
dateFormat = "yyyy-MM-dd";
|
||||
}
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
|
||||
String formatDateAfterStr = sdf.format(date);
|
||||
|
||||
return formatDateAfterStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对格林日期转换为字符串
|
||||
*
|
||||
* @param datestr:日期字符串,如:datestr = "Tue Jun 05 2018 13:11:11 GMT"
|
||||
* @return Date
|
||||
*/
|
||||
public static Date GMTDateToString(String datestr) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(GMT_DATE_FORMAT, Locale.ENGLISH);
|
||||
Date date = null;
|
||||
try {
|
||||
date = sdf.parse(datestr);
|
||||
} catch (ParseException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入日期添加天数
|
||||
*
|
||||
* @param date : 日期对象
|
||||
* @param days : 天数
|
||||
* @return Date
|
||||
*/
|
||||
public static Date addDays(Date date, int days) {
|
||||
if (null == date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(DATE, days);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期字符串转成日期对象
|
||||
*
|
||||
* @param dateString; 如:"2012-12-06"
|
||||
* @param dateFormat :格式化规则(如:yyyy-MM-dd)
|
||||
* :DateUtils.GENERAL
|
||||
* :DateUtils.LONG_FORMAT
|
||||
* @return Date
|
||||
*/
|
||||
public static Date stringToDate(String dateString, String dateFormat) {
|
||||
Date date = null;
|
||||
if (null == dateString || "".equals(dateString) || "null".equalsIgnoreCase(dateString) || null == dateFormat || "".equals(dateFormat)) {
|
||||
return date;
|
||||
}
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
|
||||
date = sdf.parse(dateString);
|
||||
} catch (ParseException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return date;
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 日期字符串转成日期对象,默认格式: yyyy-MM-dd HH:mm:ss
|
||||
*
|
||||
* @param dateString
|
||||
* @return
|
||||
*/
|
||||
public static Date stringToDate(String dateString) {
|
||||
Date date = null;
|
||||
if (null == dateString || "".equals(dateString) || "null".equalsIgnoreCase(dateString)) {
|
||||
return date;
|
||||
}
|
||||
try {
|
||||
date = sdf.parse(dateString);
|
||||
} catch (ParseException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return date;
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回昨天
|
||||
*
|
||||
* @param today
|
||||
* @return
|
||||
*/
|
||||
public static Date yesterday(Date today) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(today);
|
||||
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回明天
|
||||
*
|
||||
* @param today
|
||||
* @return
|
||||
*/
|
||||
public static Date tomorrow(Date today) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(today);
|
||||
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 1);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static final String format(Date date, String pattern) {
|
||||
if(date==null) return null;
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public static final String format(LocalDate localDate) {
|
||||
return format(localDate, GENERAL);
|
||||
}
|
||||
|
||||
public static final String format(LocalDate localDate, String pattern) {
|
||||
if(localDate==null) return null;
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return localDate.format(dateFormatter);
|
||||
}
|
||||
|
||||
public static final String format(LocalTime localDate) {
|
||||
return format(localDate,FMT_TIME);
|
||||
}
|
||||
|
||||
public static final String format(LocalTime localDate,String pattern) {
|
||||
if(localDate==null) return null;
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return localDate.format(dateFormatter);
|
||||
}
|
||||
|
||||
public static final String format(LocalDateTime localDateTime) {
|
||||
return format(localDateTime,LONG_FORMAT);
|
||||
}
|
||||
|
||||
public static final String format(LocalDateTime localDateTime,String pattern) {
|
||||
if(localDateTime==null) return null;
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return localDateTime.format(dateFormatter);
|
||||
}
|
||||
|
||||
|
||||
public static final String format(OffsetDateTime offsetDateTime) {
|
||||
return format(offsetDateTime,FMT_OFFSET_DATETIME);
|
||||
}
|
||||
|
||||
public static final String format(OffsetDateTime offsetDateTime,String pattern) {
|
||||
if(offsetDateTime==null) return null;
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return offsetDateTime.format(dateFormatter);
|
||||
}
|
||||
|
||||
public static final String format(OffsetTime offsetTime) {
|
||||
return format(offsetTime,FMT_OFFSET_TIME);
|
||||
}
|
||||
|
||||
public static final String format(OffsetTime offsetDateTime,String pattern) {
|
||||
if(offsetDateTime==null) return null;
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return offsetDateTime.format(dateFormatter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final String format(Date date) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public static long getDateTime(String dateStr) {
|
||||
Date date = stringToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
// 取得当前日期(YYYYMMDD)
|
||||
public static String getYYYYMMDD() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(GENERAL_YYYYMMDD);
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
// 取得时间戳(YYYYMMDDHHMMSS)
|
||||
public static String getTimeStamp() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(GENERAL_YYYYMMDDHHMMSS);
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
public static String getYear() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
return cal.get(Calendar.YEAR) + "";
|
||||
}
|
||||
|
||||
public static String getMonth() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int i = cal.get(Calendar.MONTH) + 1;
|
||||
if (i < 10) {
|
||||
return "0" + i;
|
||||
}
|
||||
return i + "";
|
||||
}
|
||||
|
||||
public static String getDate() {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
int i = cal.get(Calendar.DATE);
|
||||
if (i < 10) {
|
||||
return "0" + i;
|
||||
}
|
||||
return i + "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上个月最后一天
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getMonthLastDate(String date) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
|
||||
Calendar c = Calendar.getInstance();
|
||||
Date parse = new Date();
|
||||
// 设置为指定日期
|
||||
if (StringUtils.isNotEmpty(date)) {
|
||||
date = date.replace("-", "");
|
||||
try {
|
||||
parse = sdf.parse(date);
|
||||
} catch (ParseException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
c.setTime(parse);
|
||||
// 指定日期月份减去一
|
||||
c.add(Calendar.MONTH, -1);
|
||||
// 指定日期月份减去一后的 最大天数
|
||||
c.set(Calendar.DATE, c.getActualMaximum(Calendar.DATE));
|
||||
// 获取最终的时间
|
||||
Date time = c.getTime();
|
||||
return sdf.format(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取yyyy-MM-dd当天
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getToday() {
|
||||
String today = LocalDate.now().format(fmt);
|
||||
return today;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取yyyy-MM-dd明天
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getTomorrow() {
|
||||
String tomorrow = LocalDate.now().plusDays(1).format(fmt);
|
||||
return tomorrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置时间
|
||||
*
|
||||
* @param date 时间
|
||||
* @param hour 小时
|
||||
* @param minute 分钟
|
||||
* @param second 秒钟
|
||||
* @param millisecond 毫秒
|
||||
* @return 返回值
|
||||
*/
|
||||
public static Date setDateTime(Date date, Integer hour, Integer minute, Integer second, Integer millisecond) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, second);
|
||||
calendar.set(Calendar.MILLISECOND, millisecond);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static LocalDateTime toLocalDateTime(String source){
|
||||
return toLocalDateTime(source, LONG_FORMAT);
|
||||
}
|
||||
|
||||
public static LocalDateTime toLocalDateTime(String source,String fmt){
|
||||
try {
|
||||
return LocalDateTime.parse(source,DateTimeFormatter.ofPattern(fmt));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static LocalDate toLocalDate(String source){
|
||||
return toLocalDate(source, GENERAL);
|
||||
}
|
||||
|
||||
public static LocalDate toLocalDate(String source,String fmt){
|
||||
try {
|
||||
return LocalDate.parse(source,DateTimeFormatter.ofPattern(fmt));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static LocalTime toLocalTime(String source){
|
||||
return toLocalTime(source, FMT_TIME);
|
||||
}
|
||||
|
||||
public static LocalTime toLocalTime(String source,String fmt){
|
||||
try {
|
||||
return LocalTime.parse(source,DateTimeFormatter.ofPattern(fmt));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Timestamp toTimestamp(String source,String fmt){
|
||||
try {
|
||||
SimpleDateFormat f = new SimpleDateFormat(fmt);
|
||||
return new Timestamp(f.parse(source).getTime());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static LocalDateTime toLocalDateTime(Date date) {
|
||||
return LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), zone);
|
||||
}
|
||||
|
||||
public static Date toDate(LocalDateTime ldtime) {
|
||||
return Date.from(ldtime.atZone(zone).toInstant());
|
||||
}
|
||||
|
||||
public static Timestamp toTimestamp(LocalDateTime ldtime) {
|
||||
return Timestamp.from(ldtime.atZone(zone).toInstant());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,349 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Socket;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
|
||||
|
||||
public class IoUtils {
|
||||
|
||||
private final static Charset charset=Charset.forName("UTF-8");
|
||||
|
||||
private final static ForkJoinPool forkJoinPool = new ForkJoinPool();
|
||||
|
||||
public static void closeQuietly(Closeable... closeables) {
|
||||
if (closeables == null)
|
||||
return;
|
||||
|
||||
for (Closeable closeable : closeables) {
|
||||
if (closeable == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In JDK 1.6, java.net.Socket doesn't implement Closeable, so we have this
|
||||
// overload.
|
||||
public static void closeQuietly(final Socket... sockets) {
|
||||
if (sockets == null)
|
||||
return;
|
||||
|
||||
for (Socket socket : sockets) {
|
||||
if (socket == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the text read from the given reader as a String. Closes the given
|
||||
* reader upon return.
|
||||
*/
|
||||
public static String getText(Reader reader) throws IOException {
|
||||
try {
|
||||
StringBuilder source = new StringBuilder();
|
||||
BufferedReader buffered = new BufferedReader(reader);
|
||||
String line = buffered.readLine();
|
||||
|
||||
while (line != null) {
|
||||
source.append(line);
|
||||
source.append('\n');
|
||||
line = buffered.readLine();
|
||||
}
|
||||
|
||||
return source.toString();
|
||||
} finally {
|
||||
closeQuietly(reader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text read from the given file as a String.
|
||||
*/
|
||||
public static String getText(File path) throws IOException {
|
||||
return getText(new FileReader(path));
|
||||
}
|
||||
|
||||
|
||||
public static String getText(InputStream stream) throws IOException {
|
||||
return getText(new InputStreamReader(stream,charset));
|
||||
}
|
||||
|
||||
public static String getText(InputStream stream,Charset charset) throws IOException {
|
||||
return getText(new InputStreamReader(stream,charset));
|
||||
}
|
||||
|
||||
public static void createDirectory(File dir) throws IOException {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[8192];
|
||||
|
||||
try {
|
||||
int read = in.read(buffer);
|
||||
while (read > 0) {
|
||||
out.write(buffer, 0, read);
|
||||
read = in.read(buffer);
|
||||
}
|
||||
} finally {
|
||||
closeQuietly(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyFile(File source, File target) throws FileNotFoundException, IOException {
|
||||
if (!source.isFile())
|
||||
throw new IOException(
|
||||
String.format("Error copying file %s to %s; source file does not exist", source, target));
|
||||
|
||||
createDirectory(target.getParentFile());
|
||||
doCopyFile(source, target);
|
||||
checkSameSize(source, target);
|
||||
}
|
||||
|
||||
public static List<File> listFilesRecursively(File baseDir) throws IOException {
|
||||
if (!baseDir.exists())
|
||||
return Collections.emptyList();
|
||||
|
||||
List<File> result = new ArrayList<File>();
|
||||
doListFilesRecursively(baseDir, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getFileExtension(String filename) {
|
||||
int index = filename.lastIndexOf('.');
|
||||
return index == -1 ? null : filename.substring(index + 1, filename.length());
|
||||
}
|
||||
|
||||
public static void createFile(File file) throws IOException {
|
||||
if(!file.exists()) {
|
||||
if(file.isDirectory()) {
|
||||
file.mkdirs();
|
||||
}else {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void doListFilesRecursively(File baseDir, List<File> result) throws IOException {
|
||||
List<File> dirs = new ArrayList<File>();
|
||||
File[] files = baseDir.listFiles();
|
||||
if (files == null) {
|
||||
throw new IOException("Failed to list files of directory '" + baseDir + "'");
|
||||
}
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
result.add(file);
|
||||
} else {
|
||||
dirs.add(file);
|
||||
}
|
||||
}
|
||||
for (File dir : dirs) {
|
||||
doListFilesRecursively(dir, result);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doCopyFile(File source, File target) throws IOException {
|
||||
FileInputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
|
||||
try {
|
||||
in = new FileInputStream(source);
|
||||
out = new FileOutputStream(target);
|
||||
// instead of checking transferred size, we'll compare file sizes in
|
||||
// checkSameSize()
|
||||
in.getChannel().transferTo(0, Long.MAX_VALUE, out.getChannel());
|
||||
} finally {
|
||||
closeQuietly(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkSameSize(File source, File target) throws IOException {
|
||||
long fromSize = source.length();
|
||||
long toSize = target.length();
|
||||
|
||||
if (fromSize != toSize)
|
||||
throw new IOException(
|
||||
String.format("Error copying file %s to %s; source file size is %d, but target file size is %d",
|
||||
source, target, fromSize, toSize));
|
||||
}
|
||||
|
||||
public static byte[] getBytes(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
copyStream(in, out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
public static byte[] getBytes(File in) throws IOException {
|
||||
return getBytes(new FileInputStream(in));
|
||||
}
|
||||
|
||||
public static void streamToFile(InputStream in, File file) throws IOException {
|
||||
if (!file.exists()) {
|
||||
//createDirectory(file.getParentFile());
|
||||
file.createNewFile();// 将压缩文件内容写入到这个文件中
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
int count;
|
||||
byte[] buf = new byte[8192];
|
||||
while ((count = in.read(buf)) != -1) {
|
||||
fos.write(buf, 0, count);
|
||||
}
|
||||
fos.flush();
|
||||
closeQuietly(in, fos);
|
||||
}
|
||||
|
||||
public static void byteToFile(byte[] bytes, File file) throws IOException {
|
||||
if (!file.exists()) {
|
||||
//createDirectory(file.getParentFile());
|
||||
file.createNewFile();// 将压缩文件内容写入到这个文件中
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(bytes);
|
||||
fos.flush();
|
||||
closeQuietly(fos);
|
||||
}
|
||||
|
||||
public static void writeFile(File file, OutputStream out, boolean close) throws IOException {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(file);
|
||||
int count;
|
||||
byte[] buf = new byte[8192];
|
||||
while ((count = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, count);
|
||||
}
|
||||
out.flush();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
closeQuietly(in);
|
||||
if (close) {
|
||||
closeQuietly(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class FileSizeFinder extends RecursiveTask<Long> {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
final File file;
|
||||
public FileSizeFinder(final File theFile) {
|
||||
file = theFile;
|
||||
}
|
||||
@Override
|
||||
public Long compute() {
|
||||
long size = 0;
|
||||
if (file.isFile()) {
|
||||
size = file.length();
|
||||
} else {
|
||||
final File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
List<ForkJoinTask<Long>> tasks = new ArrayList<ForkJoinTask<Long>>();
|
||||
for (final File child : children) {
|
||||
if (child.isFile()) {
|
||||
size += child.length();
|
||||
} else {
|
||||
tasks.add(new FileSizeFinder(child));
|
||||
}
|
||||
}
|
||||
for (final ForkJoinTask<Long> task : invokeAll(tasks)) {
|
||||
size += task.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
public static long getFileSize(File file) {
|
||||
return forkJoinPool.invoke(new FileSizeFinder(file));
|
||||
}
|
||||
|
||||
public static String getProjectPath() {
|
||||
String url=Thread.currentThread().getContextClassLoader().getResource("").getPath();
|
||||
try {
|
||||
url=url.substring(1, url.length()-15);
|
||||
if(url.contains("/targe")) {
|
||||
url = url.replace("/targe","");
|
||||
}
|
||||
return URLDecoder.decode(url,"utf-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
public static void delFile(File file) {
|
||||
if(file.isDirectory()) {
|
||||
File[] childs = file.listFiles();
|
||||
if(childs!=null) {
|
||||
for (int i = 0; i < childs.length; i++) {
|
||||
if(childs[i].isDirectory()) {
|
||||
delFile(childs[i]);
|
||||
}else {
|
||||
childs[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
public static List<File> findFile(File file,FilenameFilter filter) {
|
||||
List<File> res = new ArrayList<File>();
|
||||
findChilds(res, file, filter);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void findChilds(List<File> res,File file,FilenameFilter filter) {
|
||||
if(file.isDirectory()) {
|
||||
File[] delFiles=file.listFiles(filter);
|
||||
for (int i = 0; i < delFiles.length; i++) {
|
||||
res.add(delFiles[i]);
|
||||
}
|
||||
File[] childs= file.listFiles();
|
||||
for (int i = 0; i < childs.length; i++) {
|
||||
findChilds(res,childs[i],filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.invoke.SerializedLambda;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class LambdaUtils {
|
||||
|
||||
private LambdaUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static <T, R>SerializedLambda getLambda(TFunction<T, R> fn) {
|
||||
// 从function取出序列化方法
|
||||
Method writeReplaceMethod = null;
|
||||
try {
|
||||
writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
|
||||
writeReplaceMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// 从序列化方法取出序列化的lambda信息
|
||||
SerializedLambda lambda = null;
|
||||
try {
|
||||
lambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return lambda;
|
||||
}
|
||||
|
||||
public static <T, R>Field getField(TFunction<T, R> fn) {
|
||||
// 从序列化方法取出序列化的lambda信息
|
||||
SerializedLambda lambda = getLambda(fn);
|
||||
String fieldName = getFieldName(lambda);
|
||||
Field field = null;
|
||||
try {
|
||||
field = Class.forName(lambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName);
|
||||
} catch (ClassNotFoundException | NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private static <T, R>String getFieldName(SerializedLambda lambda) {
|
||||
// 从lambda信息取出method、field、class等
|
||||
String implMethodName = lambda.getImplMethodName();
|
||||
// 确保方法是符合规范的get方法,boolean类型是is开头
|
||||
if (!implMethodName.startsWith("is") && !implMethodName.startsWith("get")) {
|
||||
throw new RuntimeException("get方法名称: " + implMethodName + ", 不符合java bean规范");
|
||||
}
|
||||
// get方法开头为 is 或者 get,将方法名 去除is或者get,然后首字母小写,就是属性名
|
||||
int prefixLen = implMethodName.startsWith("is") ? 2 : 3;
|
||||
|
||||
String fieldName = implMethodName.substring(prefixLen);
|
||||
String firstChar = fieldName.substring(0, 1);
|
||||
fieldName = fieldName.replaceFirst(firstChar, firstChar.toLowerCase());
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public static <T, R>String getFieldName(TFunction<T, R> fn) {
|
||||
SerializedLambda lambda = getLambda(fn);
|
||||
return getFieldName(lambda);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,129 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ListUtils {
|
||||
|
||||
public static enum ListType{
|
||||
ArrayList,LinkedList,Vector,CopyOnWriteArrayList
|
||||
}
|
||||
|
||||
public static ListType parseType(Class<?> cls) {
|
||||
if(LinkedList.class.equals(cls)) {
|
||||
return ListType.LinkedList;
|
||||
}else if(Vector.class.equals(cls)) {
|
||||
return ListType.Vector;
|
||||
}else if(CopyOnWriteArrayList.class.equals(cls)) {
|
||||
return ListType.CopyOnWriteArrayList;
|
||||
}else {
|
||||
return ListType.ArrayList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static <T> List<T> getMapNewInstance(ListType type) {
|
||||
List<T> result=null;
|
||||
switch (type) {
|
||||
case LinkedList:
|
||||
result=CollectionUtils.newLinkedList();
|
||||
break;
|
||||
case Vector:
|
||||
result=CollectionUtils.newVector();
|
||||
break;
|
||||
case CopyOnWriteArrayList:
|
||||
result=CollectionUtils.newConcurrentArrayList();
|
||||
break;
|
||||
default:
|
||||
result=CollectionUtils.newArrayList();
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T>List<T> newInstance(Class<?> cls) {
|
||||
return getMapNewInstance(parseType(cls));
|
||||
}
|
||||
|
||||
|
||||
public static <T> void forEach(@NonNull List<T> list,ListForEach<? super T> action){
|
||||
int i=0;
|
||||
Iterator<T> iterator=list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
action.accept(iterator.next(),i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ListForEach<T>{
|
||||
|
||||
void accept(T t,int index);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> ofArray(T... objs){
|
||||
List<T> result=null;
|
||||
if(objs!=null && objs.length>0) {
|
||||
result=CollectionUtils.newArrayList();
|
||||
for (int i = 0; i < objs.length; i++) {
|
||||
result.add(objs[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> newArrayList(T... objs){
|
||||
List<T> result=null;
|
||||
if(objs!=null && objs.length>0) {
|
||||
result=CollectionUtils.newArrayList();
|
||||
for (int i = 0; i < objs.length; i++) {
|
||||
result.add(objs[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> ofCollection(Collection<?> list){
|
||||
List<T> result=null;
|
||||
if(list!=null && list.size()>0) {
|
||||
result=CollectionUtils.newArrayList();
|
||||
for (Object t : list) {
|
||||
result.add((T)t);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> List<T> ofArrays(T[] objs){
|
||||
List<T> result=null;
|
||||
if(objs!=null && objs.length>0) {
|
||||
result=CollectionUtils.newArrayList();
|
||||
for (int i = 0; i < objs.length; i++) {
|
||||
result.add(objs[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T>T getFirst(List<T> list){
|
||||
if(CollectionUtils.isNotEmpty(list)) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeMap;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class MapUtils {
|
||||
|
||||
public static enum MapType {
|
||||
hashMap,Hashtable,Properties,LinkedHashMap,IdentityHashMap,
|
||||
TreeMap,WeakHashMap,ConcurrentHashMap
|
||||
}
|
||||
|
||||
public static MapType parseMapType(Class<?> cls) {
|
||||
if(Hashtable.class.equals(cls)) {
|
||||
return MapType.Hashtable;
|
||||
}else if(Properties.class.equals(cls)) {
|
||||
return MapType.Properties;
|
||||
}else if(LinkedHashMap.class.equals(cls)) {
|
||||
return MapType.LinkedHashMap;
|
||||
}else if(IdentityHashMap.class.equals(cls)) {
|
||||
return MapType.IdentityHashMap;
|
||||
}else if(TreeMap.class.equals(cls)) {
|
||||
return MapType.TreeMap;
|
||||
}else if(WeakHashMap.class.equals(cls)) {
|
||||
return MapType.WeakHashMap;
|
||||
}else if(ConcurrentHashMap.class.equals(cls)) {
|
||||
return MapType.ConcurrentHashMap;
|
||||
}else {
|
||||
return MapType.hashMap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V> Map<K,V> getMapNewInstance(MapType type) {
|
||||
Map<K,V> result=null;
|
||||
switch (type) {
|
||||
case Hashtable:
|
||||
result=CollectionUtils.newHashtable();
|
||||
break;
|
||||
case Properties:
|
||||
result=(Map<K, V>) CollectionUtils.newProperties();
|
||||
break;
|
||||
case LinkedHashMap:
|
||||
result=CollectionUtils.newLinkedHashMap();
|
||||
break;
|
||||
case IdentityHashMap:
|
||||
result=CollectionUtils.newIdentityHashMap();
|
||||
break;
|
||||
case TreeMap:
|
||||
result=CollectionUtils.newTreeMap();
|
||||
break;
|
||||
case WeakHashMap:
|
||||
result=CollectionUtils.newWeakHashMap();
|
||||
break;
|
||||
case ConcurrentHashMap:
|
||||
result=CollectionUtils.newConcurrentHashMap();
|
||||
break;
|
||||
default:
|
||||
result=CollectionUtils.newHashMap();
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <K, V> Map<K,V> newInstance(Class<?> cls) {
|
||||
return getMapNewInstance(parseMapType(cls));
|
||||
}
|
||||
|
||||
public static <K, V, R> Map<K,V> ofList(Collection<V> collections,TFunction<V, R> fn) {
|
||||
Map<K,V> map = CollectionUtils.newHashtable();
|
||||
Field field = LambdaUtils.getField(fn);
|
||||
for (V v : collections) {
|
||||
K k = BeanUtils.getFieldValue(field, v);
|
||||
map.put(k, v);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class MybatisTools implements ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* 存储Mapper类与实体类的映射关系
|
||||
* key: Mapper接口的Class对象
|
||||
* value: 对应的实体类的Class对象
|
||||
*/
|
||||
private static final Map<Class<?>,BaseMapper<?>> ENTITY_MAPPER_MAP = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
// 获取所有继承自BaseMapper的接口(即MyBatis-Plus的Mapper接口)
|
||||
|
||||
Map<String, BaseMapper> mapperBeans = applicationContext.getBeansOfType(BaseMapper.class);
|
||||
|
||||
for (BaseMapper<?> mapper : mapperBeans.values()) {
|
||||
// 获取Mapper接口的Class对象(因为mapper是代理对象,需要获取原始接口)
|
||||
Class<?> mapperInterface = getMapperInterface(mapper.getClass());
|
||||
|
||||
// 解析Mapper接口对应的实体类
|
||||
Class<?> entityClass = resolveEntityClass(mapperInterface);
|
||||
|
||||
if (entityClass != null) {
|
||||
ENTITY_MAPPER_MAP.put(entityClass, mapper);
|
||||
}
|
||||
}
|
||||
System.out.println(ENTITY_MAPPER_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Mapper代理对象对应的原始接口
|
||||
*/
|
||||
private Class<?> getMapperInterface(Class<?> mapperProxyClass) {
|
||||
// MyBatis的Mapper代理类会实现对应的Mapper接口
|
||||
Class<?>[] interfaces = mapperProxyClass.getInterfaces();
|
||||
for (Class<?> iface : interfaces) {
|
||||
// 判断是否是BaseMapper的子类
|
||||
if (BaseMapper.class.isAssignableFrom(iface) && iface != BaseMapper.class) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return mapperProxyClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析Mapper接口对应的实体类(通过泛型参数)
|
||||
*/
|
||||
private Class<?> resolveEntityClass(Class<?> mapperInterface) {
|
||||
// 获取Mapper接口的泛型父类(BaseMapper<T>)
|
||||
Type[] genericInterfaces = mapperInterface.getGenericInterfaces();
|
||||
for (Type genericInterface : genericInterfaces) {
|
||||
if (genericInterface instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
|
||||
// 检查是否是BaseMapper
|
||||
if (parameterizedType.getRawType() == BaseMapper.class) {
|
||||
// 获取泛型参数T(即实体类)
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArguments.length > 0 && actualTypeArguments[0] instanceof Class) {
|
||||
return (Class<?>) actualTypeArguments[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据实体类获取对应的Mapper类
|
||||
*/
|
||||
public static BaseMapper<?> getMapper(Class<?> entityClass) {
|
||||
return ENTITY_MAPPER_MAP.get(entityClass);
|
||||
}
|
||||
|
||||
|
||||
public static TableInfo getTableInfo(Class<?> entityClass) {
|
||||
return TableInfoHelper.getTableInfo(entityClass);
|
||||
}
|
||||
|
||||
public static TableInfo getTableInfo(String tablename) {
|
||||
return TableInfoHelper.getTableInfo(tablename);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class RegexUtils {
|
||||
|
||||
private static final Set<String> symbols=SetUtils.of("\\","^","$","*","+","?","{","}","[","]",".","|","-","\\b","\\B"
|
||||
,"\\c","\\d","\\D","\\f","\\n","\\r","\\s","\\S","\\t","\\v","\\w","\\W","\\x","\\u");
|
||||
|
||||
private static final String prefix="${";
|
||||
|
||||
private static final String suffixed="}";
|
||||
|
||||
private static final Pattern placeholder_regex=buildPlaceholderPattern(prefix, suffixed);
|
||||
|
||||
private RegexUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static boolean has(String regex,String str) {
|
||||
return has(Pattern.compile(regex), str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符中是否包含占位符
|
||||
* */
|
||||
public static boolean has(Pattern pattern,String str) {
|
||||
return pattern.matcher(str).find();
|
||||
}
|
||||
|
||||
public static boolean has(String str) {
|
||||
return placeholder_regex.matcher(str).find();
|
||||
}
|
||||
|
||||
public static List<String> findPlaceholder(String str) {
|
||||
return findPlaceholder(str,placeholder_regex,2,1);
|
||||
}
|
||||
|
||||
public static List<String> findPlaceholder(String str,String regex,int prefixLeng,int endLeng) {
|
||||
return findPlaceholder(str,Pattern.compile(regex),prefixLeng,endLeng);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找字符串中的占位符中的字符
|
||||
* */
|
||||
public static List<String> findPlaceholder(String str,Pattern pattern,int prefixLeng,int endLeng) {
|
||||
Matcher m=pattern.matcher(str);
|
||||
List<String> result=null;
|
||||
while (m.find()) {
|
||||
if(result==null) result=CollectionUtils.newArrayList();
|
||||
result.add(m.group().substring(prefixLeng, m.group().length()-endLeng));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String replacePlaceholder(String str,String[] replaceStr) {
|
||||
return replacePlaceholder(placeholder_regex, str, replaceStr);
|
||||
}
|
||||
|
||||
|
||||
public static String replacePlaceholder(String str,Map<String,String> values) {
|
||||
List<String> placeholders = findPlaceholder(str);
|
||||
List<String> replaceValues = CollectionUtils.newArrayList();
|
||||
for (String key : placeholders) {
|
||||
replaceValues.add(values.get(key));
|
||||
}
|
||||
String[] _vals = new String[replaceValues.size()];
|
||||
replaceValues.toArray(_vals);
|
||||
return replacePlaceholder(placeholder_regex, str,_vals);
|
||||
}
|
||||
|
||||
public static String replacePlaceholder(Pattern regex,String str,String[] replaceStr) {
|
||||
Matcher m=regex.matcher(str);
|
||||
StringBuilder result=new StringBuilder();
|
||||
int index=0;int before=0;
|
||||
while (m.find()) {
|
||||
result.append(str.subSequence(before, m.start()));
|
||||
before=m.end();
|
||||
if(index<replaceStr.length) {
|
||||
String _value = replaceStr[index];
|
||||
if(_value!=null) {
|
||||
result.append(_value);
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if(str.length()!=before) result.append(str.subSequence(before, str.length()));
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义字符中的正则元符
|
||||
* */
|
||||
public static String decodeRegex(String str) {
|
||||
for (String key : symbols) {
|
||||
if(str.contains(key)) {
|
||||
str=str.replace(key,"\\"+key);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建占位符的正则表达式
|
||||
* */
|
||||
public static Pattern buildPlaceholderPattern(String prefix,String suffixed) {
|
||||
prefix=decodeRegex(prefix);
|
||||
suffixed=decodeRegex(suffixed);
|
||||
return Pattern.compile(String.format("%s[^%s]*%s", prefix,suffixed,suffixed));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
public class SanDefaultFilter implements SanFilter{
|
||||
|
||||
public final String CLASS_SUFFIX = "^([^\\$]+|[^\\d+]+)\\.class";
|
||||
|
||||
@Override
|
||||
public boolean accept(String current_package,String scan_package) {
|
||||
if(StringUtils.isEmpty(scan_package)) {
|
||||
return true;
|
||||
}else if(scan_package.contains("*")) {
|
||||
return current_package.matches(scan_package);
|
||||
}
|
||||
return current_package.startsWith(scan_package);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(String className) {
|
||||
return className.matches(CLASS_SUFFIX);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
|
||||
public interface SanFilter {
|
||||
|
||||
public final String CLASS_SUFFIX = "^([^\\$]+|[^\\d+]+)\\.class";
|
||||
|
||||
public default boolean accept(String current_package,String scan_package) {
|
||||
if(scan_package.contains("*")) {
|
||||
return current_package.matches(scan_package);
|
||||
}
|
||||
return current_package.equals(scan_package) || current_package.startsWith(scan_package);
|
||||
};
|
||||
|
||||
public default boolean accept(String className) {
|
||||
return className.matches(CLASS_SUFFIX);
|
||||
};
|
||||
|
||||
public default boolean accept(Class<?> klazz) {
|
||||
return true;
|
||||
};
|
||||
|
||||
}
|
||||
@ -0,0 +1,200 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
public class ScanClasses {
|
||||
|
||||
private static Log log=LogFactory.getLog(ScanClasses.class);
|
||||
|
||||
/** 过滤器 **/
|
||||
private static SanFilter filter =new SanDefaultFilter();
|
||||
|
||||
public static final String CLASS_SUFFIX = ".class";
|
||||
|
||||
private static final String FILE_PROCOTOL="file";
|
||||
|
||||
private static final String JAR_PROCOTOL="jar";
|
||||
|
||||
private ScanClasses() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(Set<String> packages) {
|
||||
return scan(packages, filter);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(Set<String> packages,SanFilter filter) {
|
||||
return scan(packages,null,filter);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(Set<String> packages,Set<Class<? extends Annotation>> annotations) {
|
||||
return scan(packages,annotations,filter);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(Set<String> packages,Set<Class<? extends Annotation>> annotations,SanFilter filter) {
|
||||
Set<Class<?>> classes=CollectionUtils.newHashSet();
|
||||
Iterator<String> iterator=packages.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
scan(classes,iterator.next(),annotations,filter);
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(String[] packages) {
|
||||
return scan(packages, filter);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(String[] packages,SanFilter filter) {
|
||||
return scan(packages,null,filter);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(String[] packages,Set<Class<? extends Annotation>> annotations) {
|
||||
return scan(packages,annotations,filter);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> scan(String[] packages,Set<Class<? extends Annotation>> annotations,SanFilter filter) {
|
||||
Set<Class<?>> classes=CollectionUtils.newHashSet();
|
||||
for (int i = 0; i < packages.length; i++) {
|
||||
scan(classes,packages[i],annotations,filter);
|
||||
}
|
||||
return classes;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void scan(Set<Class<?>> classes,String scan_package,Set<Class<? extends Annotation>> annotations,SanFilter filter){
|
||||
String current_package=getCurrentPackage(scan_package);
|
||||
// 获取包的名字 并进行替换
|
||||
String packageDirName = current_package.replace('.', '/');
|
||||
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
|
||||
Enumeration<URL> dirs = null;
|
||||
try {
|
||||
dirs = ClassUtils.getDefaultClassLoader().getResources(packageDirName);
|
||||
while(dirs.hasMoreElements()) {
|
||||
URL url = dirs.nextElement();
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("url协议--->"+url.getProtocol());
|
||||
}
|
||||
if(FILE_PROCOTOL.equals(url.getProtocol())) {
|
||||
File file = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
|
||||
if(!file.exists() || !file.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
if(file.isDirectory()) {
|
||||
File[] files=file.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
scanFile(scan_package,current_package,files[i],annotations,classes,filter);
|
||||
}
|
||||
}else {
|
||||
scanFile(scan_package, current_package, file,annotations,classes,filter);
|
||||
}
|
||||
}else if(JAR_PROCOTOL.equals(url.getProtocol())) {
|
||||
scanJar(scan_package, current_package, ((JarURLConnection)url.openConnection()).getJarFile(),annotations,classes,filter);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("扫描claess异常",e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String getCurrentPackage(String scan_package) {
|
||||
if(scan_package.contains(".*")) {
|
||||
return scan_package.substring(0,scan_package.indexOf(".*"));
|
||||
}
|
||||
return scan_package;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下次扫描的包路径
|
||||
* */
|
||||
private static String getNextPackage(String current_package,String file_name) {
|
||||
String nextPackage=null;
|
||||
if(StringUtils.isEmpty(current_package)) {
|
||||
nextPackage= getClassName(file_name);
|
||||
}else {
|
||||
nextPackage=current_package+"."+getClassName(file_name);
|
||||
}
|
||||
return nextPackage;
|
||||
}
|
||||
|
||||
private static void scanFile(String scan_package,String current_package,File file,Set<Class<? extends Annotation>> annotations,Set<Class<?>> classes,SanFilter filter) {
|
||||
if(filter==null || (filter!=null && filter.accept(current_package,scan_package))){
|
||||
String file_name=file.getName();
|
||||
if(file.isDirectory()) {
|
||||
File[] files=file.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
scanFile(scan_package,getNextPackage(current_package,file_name),files[i],annotations,classes,filter);
|
||||
}
|
||||
}else {
|
||||
if(filter==null || (filter!=null && filter.accept(file_name))) {
|
||||
parseClass(scan_package, current_package,getNextPackage(current_package,file_name),annotations,classes,filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void parseClass(String scan_package,String current_package,String className,Set<Class<? extends Annotation>> annotations,Set<Class<?>> classes,SanFilter filter) {
|
||||
Class<?> cls= ClassUtils.loadClass(className);
|
||||
if(annotations!=null && !annotations.isEmpty()) {
|
||||
for (Class<? extends Annotation> annotation : annotations) {
|
||||
if(cls.getAnnotation(annotation)!=null) {
|
||||
classes.add(cls);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}else if(filter!=null && filter.accept(cls)){
|
||||
classes.add(cls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void scanJar(String scan_package,String current_package,JarFile jar,Set<Class<? extends Annotation>> annotations,Set<Class<?>> classes,SanFilter filter) {
|
||||
Enumeration<JarEntry> entrys= jar.entries();
|
||||
while(entrys.hasMoreElements()) {
|
||||
JarEntry entry=entrys.nextElement();
|
||||
if(!entry.isDirectory()) {
|
||||
String cpackage = getJarPackage(entry);
|
||||
if(filter==null || filter.accept(cpackage,scan_package)) {
|
||||
String name = entry.getName();
|
||||
if(filter==null || filter.accept(name)) {
|
||||
parseClass(scan_package,cpackage,getJarClassName(entry),annotations,classes,filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getJarPackage(JarEntry entry) {
|
||||
String name = entry.getName();
|
||||
if(name.lastIndexOf("/")!=-1) {
|
||||
name = name.substring(0, name.lastIndexOf("/"));
|
||||
}
|
||||
return name.replace("/", ".");
|
||||
}
|
||||
|
||||
private static String getJarClassName(JarEntry entry) {
|
||||
return entry.getName().substring(0, entry.getName().length()-6).replaceAll("/", ".");
|
||||
}
|
||||
|
||||
private static String getClassName(String name) {
|
||||
return name.split("\\.")[0];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @Description TODO(这里用一句话描述这个类的作用)
|
||||
* @author zhangfucai
|
||||
* @Date 2023年1月8日 下午6:29:01
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class ScanFile {
|
||||
|
||||
|
||||
private static final String FILE_PROCOTOL="file";
|
||||
|
||||
private static final String JAR_PROCOTOL="jar";
|
||||
|
||||
public static void scan(String name,ScanFileFilter filter) {
|
||||
try {
|
||||
Enumeration<URL> dirs = getDefaultClassLoader().getResources(name);
|
||||
if(dirs!=null) {
|
||||
while(dirs.hasMoreElements()) {
|
||||
URL url = dirs.nextElement();
|
||||
if(FILE_PROCOTOL.equals(url.getProtocol())) {
|
||||
filter.accept(url.openStream());
|
||||
}else if(JAR_PROCOTOL.equals(url.getProtocol())) {
|
||||
JarFile jarFile = ((JarURLConnection)url.openConnection()).getJarFile();
|
||||
ZipEntry entry = jarFile.getEntry(name);
|
||||
if(entry!=null) {
|
||||
filter.accept(jarFile.getInputStream(entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
log.info("没有扫描到任何东西!");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static ClassLoader getDefaultClassLoader() {
|
||||
ClassLoader cl = null;
|
||||
try {
|
||||
cl = Thread.currentThread().getContextClassLoader();
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
if (cl == null) {
|
||||
cl = ScanFile.class.getClassLoader();
|
||||
if (cl == null) {
|
||||
try {
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @Description TODO(这里用一句话描述这个类的作用)
|
||||
* @author zhangfucai
|
||||
* @Date 2023年1月8日 下午6:29:56
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public interface ScanFileFilter {
|
||||
|
||||
public void accept(InputStream in);
|
||||
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class SetUtils {
|
||||
|
||||
public static enum SetType{
|
||||
HashSet,TreeSet,LinkedHashSet,ConcurrentSkipListSet
|
||||
}
|
||||
|
||||
|
||||
public static SetType parseType(Class<?> cls) {
|
||||
if(LinkedHashSet.class.equals(cls)) {
|
||||
return SetType.LinkedHashSet;
|
||||
}else if(TreeSet.class.equals(cls)) {
|
||||
return SetType.TreeSet;
|
||||
}else if(ConcurrentSkipListSet.class.equals(cls)) {
|
||||
return SetType.ConcurrentSkipListSet;
|
||||
}else {
|
||||
return SetType.HashSet;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Set<T> getMapNewInstance(SetType type) {
|
||||
Set<T> result=null;
|
||||
switch (type) {
|
||||
case LinkedHashSet:
|
||||
result=CollectionUtils.newLinkedHashSet();
|
||||
break;
|
||||
case TreeSet:
|
||||
result=CollectionUtils.newTreeSet();
|
||||
break;
|
||||
case ConcurrentSkipListSet:
|
||||
result=CollectionUtils.newConcurrentSet();
|
||||
break;
|
||||
default:
|
||||
result=CollectionUtils.newHashSet();
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static <T> Set<T> newInstance(Class<?> cls) {
|
||||
return getMapNewInstance(parseType(cls));
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T> Set<T> of(T... objs){
|
||||
Set<T> result=null;
|
||||
if(objs!=null && objs.length>0) {
|
||||
result=CollectionUtils.newHashSet();
|
||||
for (int i = 0; i < objs.length; i++) {
|
||||
result.add(objs[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> Set<T> ofArray(T[] objs){
|
||||
Set<T> result=null;
|
||||
if(objs!=null && objs.length>0) {
|
||||
result=CollectionUtils.newHashSet();
|
||||
for (int i = 0; i < objs.length; i++) {
|
||||
result.add(objs[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> Set<T> ofCollection(Collection<T> objs){
|
||||
Set<T> result=null;
|
||||
if(objs!=null) {
|
||||
result=getMapNewInstance(SetType.HashSet);
|
||||
Iterator<T> it=objs.iterator();
|
||||
while (it.hasNext()) {
|
||||
result.add(it.next());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T, V, R> Set<V> ofCollection(Collection<T> collections,TFunction<V, R> fn) {
|
||||
Set<V> set = CollectionUtils.newHashSet();
|
||||
Field field = LambdaUtils.getField(fn);
|
||||
for (T t : collections) {
|
||||
V v = BeanUtils.getFieldValue(field, t);
|
||||
set.add(v);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
public static <T>T getFirst(Set<T> sets){
|
||||
if(CollectionUtils.isNotEmpty(sets)) {
|
||||
for (T t : sets) {
|
||||
if(t!= null) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.pictc.cache.CacheFactory;
|
||||
import com.pictc.cache.TanukiCache;
|
||||
|
||||
/**
|
||||
* @Description TODO(这里用一句话描述这个类的作用)
|
||||
* @author zhangfucai
|
||||
* @Date 2022年11月6日 上午10:22:31
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Component
|
||||
public class SpringAnnotationUtils implements EnvironmentAware{
|
||||
|
||||
private static final TanukiCache<String,InvocationHandler> handlerCache= CacheFactory.factory("Invocation-cache");
|
||||
|
||||
private static final TanukiCache<String,Annotation> findCache = CacheFactory.factory("Annotation-cache");
|
||||
|
||||
private static final String findKeyFormat="%s@%s";
|
||||
|
||||
private static final String handlerKeyFormat="%s@%s";
|
||||
|
||||
private static Environment environment;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Annotation>A findAnnotation(Class<?> clazz,Class<A> annotationType){
|
||||
if(!clazz.isAnnotationPresent(annotationType)) {
|
||||
return null;
|
||||
}
|
||||
String key=String.format(findKeyFormat, clazz.getName(),annotationType.getName());
|
||||
if(!findCache.containsKey(key)) {
|
||||
findCache.save(key, resolveAnnotationEnvValue(clazz.getAnnotation(annotationType)));
|
||||
}
|
||||
return (A) findCache.get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Annotation>A findAnnotation(AnnotatedElement element,Class<A> annotationType){
|
||||
if(!element.isAnnotationPresent(annotationType)) {
|
||||
return null;
|
||||
}
|
||||
String key=String.format(findKeyFormat,System.identityHashCode(element),annotationType.getName());
|
||||
if(!findCache.containsKey(key)) {
|
||||
findCache.save(key, resolveAnnotationEnvValue(element.getAnnotation(annotationType)));
|
||||
}
|
||||
return (A) findCache.get(key);
|
||||
}
|
||||
|
||||
private static <A extends Annotation>A resolveAnnotationEnvValue(A annotation) {
|
||||
Map<String, Object> values=AnnotationUtils.getAnnotationAttributes(annotation);
|
||||
if(values!=null) {
|
||||
Set<Entry<String, Object>> vs= values.entrySet();
|
||||
for (Entry<String, Object> entry : vs) {
|
||||
values.put(entry.getKey(),parseValue(entry.getValue()));
|
||||
}
|
||||
}
|
||||
changeValues(annotation, values);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String,Object> getValues(Annotation annotation){
|
||||
String key=String.format(handlerKeyFormat,annotation.getClass().getName(),System.identityHashCode(annotation));
|
||||
if(!handlerCache.containsKey(key)) {
|
||||
handlerCache.save(key, Proxy.getInvocationHandler(annotation));
|
||||
}
|
||||
InvocationHandler invocationHandler =handlerCache.get(key);
|
||||
try {
|
||||
Field declaredField = invocationHandler.getClass().getDeclaredField("memberValues");
|
||||
declaredField.setAccessible(true);
|
||||
return (Map<String, Object>) declaredField.get(invocationHandler);
|
||||
} catch (Exception e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void changeValue(Annotation annotation,String name,Object value) {
|
||||
Map<String, Object> values = getValues(annotation);
|
||||
if(values!=null) {
|
||||
values.put(name,value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void changeValues(Annotation annotation,Map<String,Object> attrs) {
|
||||
Map<String, Object> values = getValues(annotation);
|
||||
if(values!=null) {
|
||||
values.putAll(attrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Object parseValue(Object val) {
|
||||
if(environment==null) {
|
||||
return val;
|
||||
}
|
||||
if(val!=null && val instanceof String && RegexUtils.has(val.toString())) {
|
||||
String strVal=val.toString();
|
||||
List<String> names=RegexUtils.findPlaceholder(strVal);
|
||||
String[] values=new String[names.size()];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
String key=names.get(i);
|
||||
String[] keys=key.split(":");
|
||||
if(keys.length==2) {
|
||||
if(environment.containsProperty(keys[0])) {
|
||||
values[i]=environment.getProperty(keys[0]);
|
||||
}else {
|
||||
values[i]=keys[1];
|
||||
}
|
||||
}else {
|
||||
values[i] = environment.getProperty(key);
|
||||
}
|
||||
}
|
||||
return RegexUtils.replacePlaceholder(strVal, values);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
SpringAnnotationUtils.environment=environment;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,176 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* @Description springbean 工具类型
|
||||
* @author zhangfucai
|
||||
* @Date 2023年6月29日 下午3:47:01
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public class SpringTools implements ApplicationContextAware,EnvironmentAware{
|
||||
|
||||
public static final String CONFIG_KEY_APPLICATION = "spring.application.name";
|
||||
|
||||
public static final String CONFIG_KEY_PROFILE = "spring.profiles.active";
|
||||
|
||||
public static final String CONFIG_PROD_VALUE = "prod";
|
||||
|
||||
private static ApplicationContext context;
|
||||
|
||||
private static Environment environment;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
SpringTools.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
SpringTools.environment = environment;
|
||||
}
|
||||
|
||||
|
||||
public static ConfigurableApplicationContext logStarter(Class<?> appClass,String[] args) {
|
||||
long start = System.currentTimeMillis();
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
|
||||
return logStarter(start, builder.headless(false).run(args));
|
||||
}
|
||||
|
||||
public static ConfigurableApplicationContext logStarter(long start,ConfigurableApplicationContext context) {
|
||||
ConfigurableEnvironment env = context.getEnvironment();
|
||||
Integer _port = env.getProperty("server.port",int.class);
|
||||
int port = _port==null?8080:_port.intValue();
|
||||
String profile = env.getProperty(CONFIG_KEY_PROFILE,"dev");
|
||||
Map<String,String> values = new HashMap<String, String>();
|
||||
ServerProperties server = context.getBean(ServerProperties.class);
|
||||
String path = getContextPath(server.getServlet().getContextPath());
|
||||
String portPath = port==80?"":":"+port;
|
||||
values.put("${serverName}", env.getProperty(CONFIG_KEY_APPLICATION));
|
||||
values.put("${profiles}", profile);
|
||||
values.put("${time}",String.valueOf((System.currentTimeMillis()-start)/1000));
|
||||
values.put("${url}", "http://localhost"+portPath+path);
|
||||
printBanner(values);
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param values
|
||||
*/
|
||||
private static void printBanner(Map<String, String> values) {
|
||||
ScanFile.scan("t-banner.txt",new ScanFileFilter() {
|
||||
|
||||
private boolean ready = false;
|
||||
|
||||
@Override
|
||||
public void accept(InputStream in) {
|
||||
if(!ready) {
|
||||
ready = true;
|
||||
}else {
|
||||
return;
|
||||
}
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(in));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
for (String key : values.keySet()) {
|
||||
line = line.replace(key, values.get(key));
|
||||
}
|
||||
System.out.println(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}finally {
|
||||
IoUtils.closeQuietly(reader);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String getLocalIp() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException("获取本地ip异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getContextPath(String path) {
|
||||
if(!StringUtils.isEmpty(path)) {
|
||||
if(!path.startsWith("/")) {
|
||||
path = "/"+path;
|
||||
}
|
||||
if(path.endsWith("/")) {
|
||||
path = path.substring(0,path.length()-1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public static <T>T getBean(Class<T> clazz){
|
||||
return context.getBean(clazz);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T>T getBean(String name){
|
||||
if(context.containsBean(name)) {
|
||||
return (T) context.getBean(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T>Map<String, T> getBeansOfType(Class<T> clazz){
|
||||
return context.getBeansOfType(clazz);
|
||||
}
|
||||
|
||||
public static <T>List<T> getBeans(Class<T> clazz){
|
||||
return getBeans(clazz, false);
|
||||
}
|
||||
|
||||
public static <T>List<T> getBeans(Class<T> clazz,boolean sort){
|
||||
List<T> beans = CollectionUtils.newArrayList();
|
||||
Map<String, T> maps = getBeansOfType(clazz);
|
||||
if(maps!=null && maps.isEmpty()==false) {
|
||||
beans = new ArrayList<T>(maps.values());
|
||||
if(sort) AnnotationAwareOrderComparator.sort(beans);
|
||||
}
|
||||
return beans;
|
||||
}
|
||||
|
||||
public static <T>T getProperty(String key,Class<T> targetType,T defaultValue) {
|
||||
return environment.getProperty(key, targetType, defaultValue);
|
||||
}
|
||||
|
||||
public static <T>T getProperty(String key,Class<T> targetType) {
|
||||
return environment.getProperty(key, targetType);
|
||||
}
|
||||
|
||||
public static String getProperty(String key) {
|
||||
return environment.getProperty(key);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
|
||||
public class StringUtils {
|
||||
|
||||
private StringUtils() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static boolean isEmpty(String str) {
|
||||
if(str==null || "".equals(str.trim())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNotEmpty(String str) {
|
||||
return !isEmpty(str);
|
||||
}
|
||||
|
||||
public static String parseBytes(byte[] data,Charset charset) {
|
||||
return new String(data, charset);
|
||||
}
|
||||
|
||||
|
||||
public static String parseStream(InputStream in,Charset charset) throws IOException {
|
||||
return parseStream(new InputStreamReader(in, charset));
|
||||
}
|
||||
|
||||
public static String parseStream(Reader reader) throws IOException {
|
||||
try {
|
||||
StringBuilder source = new StringBuilder();
|
||||
BufferedReader buffered = new BufferedReader(reader);
|
||||
String line = buffered.readLine();
|
||||
|
||||
while (line != null) {
|
||||
source.append(line);
|
||||
source.append('\n');
|
||||
line = buffered.readLine();
|
||||
}
|
||||
return source.toString();
|
||||
} finally {
|
||||
IoUtils.closeQuietly(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static byte[] toBytes(String str,Charset charset) {
|
||||
if(str==null) {
|
||||
return null;
|
||||
}
|
||||
return str.getBytes(charset);
|
||||
}
|
||||
|
||||
|
||||
public static InputStream toInputStream(String str,Charset charset) {
|
||||
return new ByteArrayInputStream(toBytes(str,charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将驼峰命名的字符串转为下划线
|
||||
* */
|
||||
public static String convertHump(String str) {
|
||||
StringBuilder result=new StringBuilder();
|
||||
char[] chars=str.toCharArray();
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if(Character.isUpperCase(chars[i])) {
|
||||
if(i>0) {
|
||||
result.append('_');
|
||||
}
|
||||
result.append(Character.toLowerCase(chars[i]));
|
||||
continue;
|
||||
}
|
||||
result.append(chars[i]);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String excludeEmpty(String val,String defVal) {
|
||||
if(isEmpty(val)) {
|
||||
return defVal;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public static String format(String str,Object... args) {
|
||||
if(str!=null && args !=null && args.length > 0) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object item = args[i];
|
||||
str = str.replace("{"+i+"}",item!=null?item.toString():"");
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String opt(String val,String defVal) {
|
||||
if(isEmpty(val)) {
|
||||
return defVal;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public static boolean eq(String val,String secondVal) {
|
||||
if(val==null && secondVal==null) {
|
||||
return true;
|
||||
}
|
||||
if(val!=null) {
|
||||
return val.equals(secondVal);
|
||||
}
|
||||
return secondVal.equals(val);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 支持序列化的 Function
|
||||
*
|
||||
* @author miemie
|
||||
* @since 2018-05-12
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TFunction<T, R> extends Function<T, R>, Serializable {
|
||||
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
package com.pictc.utils;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @Description TODO(这里用一句话描述这个类的作用)
|
||||
* @author zhangfucai
|
||||
* @Date 2022年11月7日 下午11:30:00
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Getter
|
||||
public class TypeInfo {
|
||||
|
||||
private Type type;
|
||||
|
||||
private Class<?> klass;
|
||||
|
||||
private Type[] generics;
|
||||
|
||||
public TypeInfo(Type type) {
|
||||
super();
|
||||
this.type = type;
|
||||
if(type instanceof Class) {
|
||||
klass = (Class<?>)type;
|
||||
List<Type> types = CollectionUtils.newArrayList();
|
||||
addGenerics(types, klass.getGenericSuperclass());
|
||||
Type[] itypes = klass.getGenericInterfaces();
|
||||
if(itypes!=null) {
|
||||
for (int i = 0; i < itypes.length; i++) {
|
||||
addGenerics(types, itypes[i]);
|
||||
}
|
||||
}
|
||||
generics = ArrayUtils.ofCollection(types);
|
||||
}else if(type instanceof ParameterizedType) {
|
||||
ParameterizedType gtype = ((ParameterizedType)type);
|
||||
klass = (Class<?>) gtype.getRawType();
|
||||
generics = gtype.getActualTypeArguments();
|
||||
}
|
||||
}
|
||||
|
||||
private void addGenerics(List<Type> types,Type stype) {
|
||||
if(stype!=null && stype instanceof ParameterizedType) {
|
||||
ParameterizedType gtype = ((ParameterizedType)stype);
|
||||
Type[] sgs = gtype.getActualTypeArguments();
|
||||
if(sgs!=null) {
|
||||
for (Type _t : sgs) {
|
||||
types.add(_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static TypeInfo valueOf(Type type) {
|
||||
return new TypeInfo(type);
|
||||
}
|
||||
|
||||
public boolean isGenerics() {
|
||||
return generics!=null;
|
||||
}
|
||||
|
||||
public Type getGenericType(int index) {
|
||||
if(!isGenerics()) {
|
||||
throw new RuntimeException("不是泛型,无法获取泛型类型");
|
||||
}
|
||||
return generics[index];
|
||||
}
|
||||
|
||||
public Type getCollectionType() {
|
||||
if(!isGenerics()) {
|
||||
throw new RuntimeException("不是泛型,无法获取泛型类型");
|
||||
}
|
||||
return generics[0];
|
||||
}
|
||||
|
||||
public boolean isArray() {
|
||||
return klass.isArray();
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return klass.isInterface();
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return ClassUtils.isPrimitive(klass);
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return klass.isEnum();
|
||||
}
|
||||
|
||||
public boolean isCollection() {
|
||||
return ClassUtils.isCollection(klass);
|
||||
}
|
||||
|
||||
public boolean isList() {
|
||||
return ClassUtils.isList(klass);
|
||||
}
|
||||
|
||||
public boolean isSet() {
|
||||
return ClassUtils.isSet(klass);
|
||||
}
|
||||
|
||||
public boolean isMap() {
|
||||
return ClassUtils.isMap(klass);
|
||||
}
|
||||
|
||||
public Class<?> getArrayType(){
|
||||
return klass.getComponentType();
|
||||
}
|
||||
|
||||
public <T>Collection<T> newCollection(){
|
||||
return isList()?newList():newSet();
|
||||
}
|
||||
|
||||
public <T>List<T> newList(){
|
||||
return ListUtils.getMapNewInstance(ListUtils.parseType(klass));
|
||||
}
|
||||
|
||||
public <T>Set<T> newSet(){
|
||||
return SetUtils.getMapNewInstance(SetUtils.parseType(klass));
|
||||
}
|
||||
|
||||
public <K,V>Map<K,V> newMap(){
|
||||
return MapUtils.getMapNewInstance(MapUtils.parseMapType(klass));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("Class:[%s],泛型:%s", klass.getName(),Arrays.toString(generics));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user