---初始化项目

This commit is contained in:
2025-10-10 09:20:48 +08:00
parent a8e0f1c377
commit 7f74c186da
203 changed files with 14674 additions and 0 deletions

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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;
};
}

View File

@ -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];
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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 {
}

View File

@ -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));
}
}