feat: 代码一键生成类的引入
代码一键生成类的引入代码一键生成类的引入
This commit is contained in:
+48
@@ -0,0 +1,48 @@
|
||||
package com.aos.element.common.exception;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 开发环境时输出更多的异常信息 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 14:55
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ExceptionInfo implements Serializable {
|
||||
/** serialVersionUID */
|
||||
private static final long serialVersionUID = -5072425562316472427L;
|
||||
/** 请求路径 */
|
||||
private String path;
|
||||
/** 请求参数 */
|
||||
private Object params;
|
||||
/** 请求方式 */
|
||||
private String method;
|
||||
/** 请求方地址 */
|
||||
private String remoteAddr;
|
||||
/** header */
|
||||
private Object headers;
|
||||
/** 追踪 id */
|
||||
private String traceId;
|
||||
/** 异常类 */
|
||||
private String exceptionClass;
|
||||
/** 错误信息 */
|
||||
private String errorMessage;
|
||||
/** 异常堆栈 */
|
||||
private String stackTrace;
|
||||
/** 日志系统链接 */
|
||||
private String hyperlink;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.aos.starter.core;
|
||||
|
||||
import com.aos.element.basic.basic.bundle.DynamicBundle;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: 消息外置, 需要在 resources/messages 创建对应的 [CoreBundle.properties] 文件 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.4.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.05.19 09:26
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public final class CoreBundle extends DynamicBundle {
|
||||
/** BUNDLE */
|
||||
@NonNls
|
||||
private static final String BUNDLE = "messages.CoreBundle";
|
||||
/** INSTANCE */
|
||||
private static final CoreBundle INSTANCE = new CoreBundle();
|
||||
|
||||
/**
|
||||
* Plugin bundle
|
||||
*
|
||||
* @since 0.0.1
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private CoreBundle() {
|
||||
super(BUNDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Message
|
||||
*
|
||||
* @param key key
|
||||
* @param params params
|
||||
* @return the string
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String message(@NotNull String key, Object... params) {
|
||||
return INSTANCE.getMessage(key, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Message pointer
|
||||
*
|
||||
* @param key key
|
||||
* @param params params
|
||||
* @return the supplier
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public static @NotNull Supplier<String> messagePointer(@NotNull String key, Object... params) {
|
||||
return INSTANCE.getLazyMessage(key, params);
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package com.aos.starter.core.api;
|
||||
|
||||
import com.aos.element.basic.basic.Result;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.0.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.10.14 00:55
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public interface GeneralResult {
|
||||
|
||||
/**
|
||||
* 请求成功
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default <T> Result<T> ok() {
|
||||
return this.ok(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求成功
|
||||
*
|
||||
* @param <T> 对象泛型
|
||||
* @param data 数据内容
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default <T> Result<T> ok(T data) {
|
||||
return R.succeed(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求失败
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param msg 提示内容
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default <T> Result<T> fail(String msg) {
|
||||
return R.failed(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求失败
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param errorCode 请求错误码
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default <T> Result<T> fail(IResultCode errorCode) {
|
||||
return R.failed(errorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Status result.
|
||||
*
|
||||
* @param flag the flag
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default Result<Boolean> status(boolean flag) {
|
||||
return this.status(flag, BaseCodes.FAILURE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Status result
|
||||
*
|
||||
* @param flag flag
|
||||
* @param resultCode result code
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default Result<Boolean> status(boolean flag, IResultCode resultCode) {
|
||||
return R.status(flag, resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Status result
|
||||
*
|
||||
* @param flag flag
|
||||
* @param message message
|
||||
* @return the result
|
||||
* @since 1.0.0
|
||||
*/
|
||||
default Result<Boolean> status(boolean flag, String message) {
|
||||
return R.status(flag, message);
|
||||
}
|
||||
}
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
package com.aos.starter.core.assertion;
|
||||
|
||||
import com.aos.element.basic.basic.asserts.Assertions;
|
||||
import com.aos.element.basic.core.function.CheckedCallable;
|
||||
import com.aos.element.basic.core.function.CheckedRunnable;
|
||||
import com.aos.starter.core.exception.BaseException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 枚举类异常断言,提供简便的方式判断条件,并在条件满足时抛出异常
|
||||
* 错误码和错误信息定义在枚举类中,在本断言方法中,传递错误信息需要的参数
|
||||
* 底层会使用 {@link Assertions}
|
||||
* </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.26 20:06
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface IAssert {
|
||||
|
||||
/**
|
||||
* New exception
|
||||
*
|
||||
* @param args args
|
||||
* @return the base exception
|
||||
* @since 1.7.0
|
||||
*/
|
||||
BaseException newException(Object... args);
|
||||
|
||||
/**
|
||||
* New exception
|
||||
*
|
||||
* @param t t
|
||||
* @param args args
|
||||
* @return the base exception
|
||||
* @since 1.7.0
|
||||
*/
|
||||
BaseException newException(Throwable t, Object... args);
|
||||
|
||||
/**
|
||||
* Not blank
|
||||
*
|
||||
* @param str str
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notBlank(String str, Object... args) {
|
||||
Assertions.notBlank(str, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not empty
|
||||
*
|
||||
* @param arrays arrays
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notEmpty(Object[] arrays, Object... args) {
|
||||
Assertions.notEmpty(arrays, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not empty
|
||||
*
|
||||
* @param c c
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notEmpty(Collection<?> c, Object... args) {
|
||||
Assertions.notEmpty(c, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not empty
|
||||
*
|
||||
* @param map map
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notEmpty(Map<?, ?> map, Object... args) {
|
||||
Assertions.notEmpty(map, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is false
|
||||
*
|
||||
* @param expression expression
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void isFalse(boolean expression, Object... args) {
|
||||
Assertions.isFalse(expression, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is true
|
||||
*
|
||||
* @param expression expression
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void isTrue(boolean expression, Object... args) {
|
||||
Assertions.isTrue(expression, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is null
|
||||
*
|
||||
* @param obj obj
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void isNull(Object obj, Object... args) {
|
||||
Assertions.isNull(obj, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not null
|
||||
*
|
||||
* @param obj obj
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notNull(Object obj, Object... args) {
|
||||
Assertions.notNull(obj, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* 适用于没有占位符的错误消息
|
||||
*
|
||||
* @param obj obj
|
||||
* @param runnable runnable
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notNull(Object obj, CheckedRunnable runnable) {
|
||||
Assertions.notNull(obj, this::newException, runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals
|
||||
*
|
||||
* @param o1 o 1
|
||||
* @param o2 o 2
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void equals(Object o1, Object o2, Object... args) {
|
||||
Assertions.equals(o1, o2, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not equals
|
||||
*
|
||||
* @param o1 o 1
|
||||
* @param o2 o 2
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void notEquals(Object o1, Object o2, Object... args) {
|
||||
Assertions.notEquals(o1, o2, () -> this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper
|
||||
*
|
||||
* @param runnable runnable
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void wrapper(CheckedRunnable runnable, Object... args) {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Throwable throwable) {
|
||||
this.fail(throwable, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param callable callable
|
||||
* @param args args
|
||||
* @return the t
|
||||
* @since 1.8.0
|
||||
*/
|
||||
default <T> T wrapper(CheckedCallable<T> callable, Object... args) {
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Throwable throwable) {
|
||||
this.fail(throwable, args);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail
|
||||
*
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void fail(Object... args) {
|
||||
this.fail(this.newException(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail
|
||||
*
|
||||
* @param t t
|
||||
* @param args args
|
||||
* @since 1.7.0
|
||||
*/
|
||||
default void fail(Throwable t, Object... args) {
|
||||
Assertions.fail(() -> this.newException(t, args));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.aos.starter.core.convert;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.springframework.boot.convert.ApplicationConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 类型 转换 服务,添加了 IEnum 转换 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:06
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public final class CustomConversionService extends ApplicationConversionService {
|
||||
|
||||
/**
|
||||
* Custom conversion service
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private CustomConversionService() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom conversion service
|
||||
*
|
||||
* @param embeddedValueResolver the embedded value resolver
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private CustomConversionService(@Nullable StringValueResolver embeddedValueResolver) {
|
||||
super(embeddedValueResolver);
|
||||
super.addConverter(new EnumToStringConverter());
|
||||
super.addConverter(new StringToEnumConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets instance.
|
||||
*
|
||||
* @return the instance
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public static GenericConversionService getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 静态内部类实现单例</p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:06
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static final class SingletonHolder {
|
||||
/** INSTANCE */
|
||||
private static final CustomConversionService INSTANCE = new CustomConversionService();
|
||||
|
||||
/**
|
||||
* Singleton holder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private SingletonHolder() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package com.aos.starter.core.convert;
|
||||
|
||||
|
||||
import com.aos.element.basic.basic.util.ClassUtils;
|
||||
import com.aos.element.basic.core.function.CheckedFunction;
|
||||
import com.aos.starter.core.util.ConvertUtils;
|
||||
import com.aos.starter.core.util.ReflectionUtils;
|
||||
import com.aos.starter.core.util.Unchecked;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cglib.core.Converter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 组合 spring cglib Converter 和 spring ConversionService </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:06
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class CustomConverter implements Converter {
|
||||
/** TYPE_CACHE */
|
||||
private static final ConcurrentMap<String, TypeDescriptor> TYPE_CACHE = new ConcurrentHashMap<>();
|
||||
/** Source clazz */
|
||||
private final Class<?> sourceClazz;
|
||||
/** Target clazz */
|
||||
private final Class<?> targetClazz;
|
||||
|
||||
/**
|
||||
* cglib convert
|
||||
*
|
||||
* @param value 源对象属性
|
||||
* @param target 目标对象属性类
|
||||
* @param fieldName 目标的field名,原为 set 方法名,MicaBeanCopier 里做了更改
|
||||
* @return {Object}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
@SuppressWarnings("checkstyle:ReturnCount")
|
||||
public Object convert(Object value, Class target, Object fieldName) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
// 类型一样,不需要转换
|
||||
if (ClassUtils.isAssignableValue(target, value)) {
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
TypeDescriptor targetDescriptor = CustomConverter.getTypeDescriptor(this.targetClazz, (String) fieldName);
|
||||
// 1. 判断 sourceClazz 为 Map
|
||||
if (Map.class.isAssignableFrom(this.sourceClazz)) {
|
||||
return ConvertUtils.convert(value, targetDescriptor);
|
||||
} else {
|
||||
TypeDescriptor sourceDescriptor = CustomConverter.getTypeDescriptor(this.sourceClazz, (String) fieldName);
|
||||
return ConvertUtils.convert(value, sourceDescriptor, targetDescriptor);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Converter error", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets type descriptor *
|
||||
*
|
||||
* @param clazz clazz
|
||||
* @param fieldName field name
|
||||
* @return the type descriptor
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static TypeDescriptor getTypeDescriptor(@NotNull Class<?> clazz, String fieldName) {
|
||||
String srcCacheKey = clazz.getName() + fieldName;
|
||||
// 忽略抛出异常的函数,定义完整泛型,避免编译问题
|
||||
CheckedFunction<String, TypeDescriptor> uncheckedFunction = key -> {
|
||||
// 这里 property 理论上不会为 null
|
||||
Field field = ReflectionUtils.getField(clazz, fieldName);
|
||||
if (field == null) {
|
||||
throw new NoSuchFieldException(fieldName);
|
||||
}
|
||||
return new TypeDescriptor(field);
|
||||
};
|
||||
return TYPE_CACHE.computeIfAbsent(srcCacheKey, Unchecked.function(uncheckedFunction));
|
||||
}
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
package com.aos.starter.core.convert;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import com.aos.starter.core.util.ConvertUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 接收参数 同 jackson Enum -> String 转换 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:05
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class EnumToStringConverter implements ConditionalGenericConverter {
|
||||
/** 缓存 Enum 类信息,提供性能 */
|
||||
private static final ConcurrentMap<Class<?>, AccessibleObject> ENUM_CACHE_MAP = Maps.newConcurrentMap();
|
||||
|
||||
/**
|
||||
* Matches boolean
|
||||
*
|
||||
* @param sourceType source type
|
||||
* @param targetType target type
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(@NotNull TypeDescriptor sourceType, @NotNull TypeDescriptor targetType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets convertible types *
|
||||
*
|
||||
* @return the convertible types
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
Set<ConvertiblePair> pairSet = new HashSet<>(4);
|
||||
pairSet.add(new ConvertiblePair(Enum.class, String.class));
|
||||
pairSet.add(new ConvertiblePair(Enum.class, Integer.class));
|
||||
pairSet.add(new ConvertiblePair(Enum.class, Long.class));
|
||||
return Collections.unmodifiableSet(pairSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert object
|
||||
*
|
||||
* @param source source
|
||||
* @param sourceType source type
|
||||
* @param targetType target type
|
||||
* @return the object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public Object convert(@Nullable Object source, @NotNull TypeDescriptor sourceType, @NotNull TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> sourceClazz = sourceType.getType();
|
||||
AccessibleObject accessibleObject = ENUM_CACHE_MAP.computeIfAbsent(sourceClazz, EnumToStringConverter::getAnnotation);
|
||||
Class<?> targetClazz = targetType.getType();
|
||||
// 如果为null,走默认的转换
|
||||
if (accessibleObject == null) {
|
||||
if (String.class == targetClazz) {
|
||||
return ((Enum) source).name();
|
||||
}
|
||||
int ordinal = ((Enum) source).ordinal();
|
||||
return ConvertUtils.convert(ordinal, targetClazz);
|
||||
}
|
||||
try {
|
||||
return EnumToStringConverter.invoke(sourceClazz, accessibleObject, source, targetClazz);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets annotation *
|
||||
*
|
||||
* @param clazz clazz
|
||||
* @return the annotation
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings("java:S3011")
|
||||
private static AccessibleObject getAnnotation(@NotNull Class<?> clazz) {
|
||||
Set<AccessibleObject> accessibleObjects = new HashSet<>();
|
||||
// JsonValue METHOD, FIELD
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
Collections.addAll(accessibleObjects, fields);
|
||||
// methods
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
Collections.addAll(accessibleObjects, methods);
|
||||
for (AccessibleObject accessibleObject : accessibleObjects) {
|
||||
// 复用 jackson 的 JsonValue 注解
|
||||
JsonValue jsonValue = accessibleObject.getAnnotation(JsonValue.class);
|
||||
if (jsonValue != null && jsonValue.value()) {
|
||||
accessibleObject.setAccessible(true);
|
||||
return accessibleObject;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke object
|
||||
*
|
||||
* @param clazz clazz
|
||||
* @param accessibleObject accessible object
|
||||
* @param source source
|
||||
* @param targetClazz target clazz
|
||||
* @return the object
|
||||
* @throws IllegalAccessException illegal access exception
|
||||
* @throws InvocationTargetException invocation target exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Nullable
|
||||
private static Object invoke(Class<?> clazz, AccessibleObject accessibleObject, Object source, Class<?> targetClazz)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
Object value = null;
|
||||
if (accessibleObject instanceof Field) {
|
||||
Field field = (Field) accessibleObject;
|
||||
value = field.get(source);
|
||||
} else if (accessibleObject instanceof Method) {
|
||||
Method method = (Method) accessibleObject;
|
||||
Class<?> paramType = method.getParameterTypes()[0];
|
||||
// 类型转换
|
||||
Object object = ConvertUtils.convert(source, paramType);
|
||||
value = method.invoke(clazz, object);
|
||||
}
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return ConvertUtils.convert(value, targetClazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.aos.starter.core.enums;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: 字段填充策略枚举类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.08 12:41
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public enum FieldFill {
|
||||
/** 默认不处理 */
|
||||
DEFAULT,
|
||||
/** 插入时填充字段 */
|
||||
INSERT,
|
||||
/** 更新时填充字段 */
|
||||
UPDATE,
|
||||
/** 插入和更新时填充字段 */
|
||||
INSERT_UPDATE
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
package com.aos.starter.core.jackson;
|
||||
|
||||
import com.aos.element.basic.basic.util.StringPool;
|
||||
import com.aos.element.basic.basic.util.StringUtils;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
|
||||
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: jackson 默认值为 null 时的处理, 主要是为了避免 app 端出现null导致闪退
|
||||
* 规则:
|
||||
* {@code
|
||||
* number: 0
|
||||
* string: null
|
||||
* date: null
|
||||
* boolean: false
|
||||
* array: []
|
||||
* Object: {}
|
||||
* }
|
||||
* todo-dong4j : (2020-07-10 14:5) [提供扩展接口, 可自定义 changeProperties ]
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.24 01:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DefaultBeanSerializerModifier extends com.fasterxml.jackson.databind.ser.BeanSerializerModifier {
|
||||
/**
|
||||
* Change properties list
|
||||
*
|
||||
* @param config config
|
||||
* @param beanDesc bean desc
|
||||
* @param beanProperties bean properties
|
||||
* @return the list
|
||||
* @see DefaultSerializerProvider#_serializeNull(JsonGenerator)
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
|
||||
BeanDescription beanDesc,
|
||||
@NotNull List<BeanPropertyWriter> beanProperties) {
|
||||
beanProperties.forEach(writer -> {
|
||||
// 如果已经有 null 序列化处理如注解: @JsonSerialize(nullsUsing = xxx) 跳过
|
||||
if (writer.hasNullSerializer()) {
|
||||
return;
|
||||
}
|
||||
JavaType type = writer.getType();
|
||||
Class<?> clazz = type.getRawClass();
|
||||
if (type.isTypeOrSubTypeOf(Number.class)) {
|
||||
// writer.assignNullSerializer(NullJsonSerializers.NUMBER_JSON_SERIALIZER);
|
||||
} else if (type.isTypeOrSubTypeOf(Boolean.class)) {
|
||||
writer.assignNullSerializer(NullJsonSerializers.BOOLEAN_JSON_SERIALIZER);
|
||||
} else if (type.isTypeOrSubTypeOf(Character.class)) {
|
||||
writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER);
|
||||
} else if (type.isTypeOrSubTypeOf(String.class)) {
|
||||
writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER);
|
||||
} else if (type.isArrayType() || clazz.isArray() || type.isTypeOrSubTypeOf(Collection.class)) {
|
||||
writer.assignNullSerializer(NullJsonSerializers.ARRAY_JSON_SERIALIZER);
|
||||
} else if (type.isTypeOrSubTypeOf(OffsetDateTime.class)) {
|
||||
writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER);
|
||||
} else if (type.isTypeOrSubTypeOf(Date.class) || type.isTypeOrSubTypeOf(TemporalAccessor.class)) {
|
||||
writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER);
|
||||
} else {
|
||||
writer.assignNullSerializer(NullJsonSerializers.OBJECT_JSON_SERIALIZER);
|
||||
}
|
||||
});
|
||||
return super.changeProperties(config, beanDesc, beanProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* The interface Null json serializers.
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.24 01:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:InterfaceIsType")
|
||||
public interface NullJsonSerializers {
|
||||
|
||||
/**
|
||||
* The constant STRING_JSON_SERIALIZER.
|
||||
*/
|
||||
JsonSerializer<Object> STRING_JSON_SERIALIZER = new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, @NotNull JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeString(StringPool.EMPTY);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The constant NUMBER_JSON_SERIALIZER.
|
||||
*/
|
||||
JsonSerializer<Object> NUMBER_JSON_SERIALIZER = new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, @NotNull JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeNumber(StringUtils.INDEX_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The constant BOOLEAN_JSON_SERIALIZER.
|
||||
*/
|
||||
JsonSerializer<Object> BOOLEAN_JSON_SERIALIZER = new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, @NotNull JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeObject(Boolean.FALSE);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The constant ARRAY_JSON_SERIALIZER.
|
||||
*/
|
||||
JsonSerializer<Object> ARRAY_JSON_SERIALIZER = new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, @NotNull JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeStartArray();
|
||||
gen.writeEndArray();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The constant OBJECT_JSON_SERIALIZER.
|
||||
*/
|
||||
JsonSerializer<Object> OBJECT_JSON_SERIALIZER = new JsonSerializer<Object>() {
|
||||
@Override
|
||||
public void serialize(Object value, @NotNull JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeStartObject();
|
||||
gen.writeEndObject();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.aos.starter.core.node;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 森林节点类</p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.26 20:42
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class ForestNode extends BaseNode {
|
||||
|
||||
/**
|
||||
* 节点内容
|
||||
*/
|
||||
private Object content;
|
||||
|
||||
/**
|
||||
* Instantiates a new Forest node.
|
||||
*
|
||||
* @param id the id
|
||||
* @param parentId the parent id
|
||||
* @param content the content
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public ForestNode(Integer id, Integer parentId, Object content) {
|
||||
this.id = id;
|
||||
this.parentId = parentId;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package com.aos.starter.core.node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 森林管理类</p>
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 14:53
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ForestNodeManager<T extends INode> {
|
||||
|
||||
/**
|
||||
* 森林的所有节点
|
||||
*/
|
||||
private final List<T> list;
|
||||
|
||||
/**
|
||||
* 森林的父节点ID
|
||||
*/
|
||||
private final List<Integer> parentIds = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Instantiates a new Forest node manager.
|
||||
*
|
||||
* @param items the items
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public ForestNodeManager(List<T> items) {
|
||||
list = items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据节点ID获取一个节点
|
||||
*
|
||||
* @param id 节点ID
|
||||
* @return 对应的节点对象 tree node at
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public INode getTreeNodeAt(int id) {
|
||||
for (INode forestNode : list) {
|
||||
if (forestNode.getId() == id) {
|
||||
return forestNode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加父节点ID
|
||||
*
|
||||
* @param parentId 父节点ID
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public void addParentId(Integer parentId) {
|
||||
parentIds.add(parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树的根节点(一个森林对应多颗树)
|
||||
*
|
||||
* @return 树的根节点集合 root
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public List<T> getRoot() {
|
||||
List<T> roots = new ArrayList<>();
|
||||
for (T forestNode : list) {
|
||||
if (forestNode.getParentId() == 0 || parentIds.contains(forestNode.getId())) {
|
||||
roots.add(forestNode);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.aos.starter.core.node;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 森林节点归并类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.26 20:42
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ForestNodeMerger {
|
||||
|
||||
/**
|
||||
* 将节点数组归并为一个森林 (多棵树) (填充节点的children域)
|
||||
* 时间复杂度为O(n^2)
|
||||
*
|
||||
* @param <T> T 泛型标记
|
||||
* @param items 节点域
|
||||
* @return 多棵树的根节点集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T extends INode> List<T> merge(List<T> items) {
|
||||
ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items);
|
||||
items.forEach(forestNode -> {
|
||||
if (forestNode.getParentId() != 0) {
|
||||
INode node = forestNodeManager.getTreeNodeAt(forestNode.getParentId());
|
||||
if (node != null) {
|
||||
node.getChildren().add(forestNode);
|
||||
} else {
|
||||
forestNodeManager.addParentId(forestNode.getId());
|
||||
}
|
||||
}
|
||||
});
|
||||
return forestNodeManager.getRoot();
|
||||
}
|
||||
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.aos.starter.core.reflection;
|
||||
|
||||
import com.aos.starter.core.reflection.factory.DefaultObjectFactory;
|
||||
import com.aos.starter.core.reflection.factory.ObjectFactory;
|
||||
import com.aos.starter.core.reflection.wrapper.DefaultObjectWrapperFactory;
|
||||
import com.aos.starter.core.reflection.wrapper.ObjectWrapperFactory;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: 默认的实体元数据包装对象, 使用 {@link DefaultMetaObject#forObject} 生成 {@link MetaObject}</p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:30
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public final class DefaultMetaObject {
|
||||
|
||||
/** DEFAULT_OBJECT_FACTORY */
|
||||
public static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
|
||||
/** DEFAULT_OBJECT_WRAPPER_FACTORY */
|
||||
public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
|
||||
/** NULL_META_OBJECT */
|
||||
public static final MetaObject NULL_META_OBJECT = MetaObject.forObject(Object.class,
|
||||
DEFAULT_OBJECT_FACTORY,
|
||||
DEFAULT_OBJECT_WRAPPER_FACTORY,
|
||||
new DefaultReflectorFactory());
|
||||
|
||||
/**
|
||||
* Default meta object
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private DefaultMetaObject() {
|
||||
}
|
||||
|
||||
/**
|
||||
* For object meta object
|
||||
*
|
||||
* @param object object
|
||||
* @return the meta object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("!null -> new")
|
||||
public static MetaObject forObject(Object object) {
|
||||
return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.aos.starter.core.reflection;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:54
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DefaultReflectorFactory implements ReflectorFactory {
|
||||
/** Reflector map */
|
||||
private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();
|
||||
/** Class cache enabled */
|
||||
private boolean classCacheEnabled = true;
|
||||
|
||||
/**
|
||||
* Is class cache enabled boolean
|
||||
*
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean isClassCacheEnabled() {
|
||||
return this.classCacheEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets class cache enabled *
|
||||
*
|
||||
* @param classCacheEnabled class cache enabled
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public void setClassCacheEnabled(boolean classCacheEnabled) {
|
||||
this.classCacheEnabled = classCacheEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find for class reflector
|
||||
*
|
||||
* @param type type
|
||||
* @return the reflector
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Reflector findForClass(Class<?> type) {
|
||||
if (this.classCacheEnabled) {
|
||||
// synchronized (type) removed see issue #461
|
||||
return this.reflectorMap.computeIfAbsent(type, Reflector::new);
|
||||
} else {
|
||||
return new Reflector(type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
package com.aos.starter.core.reflection.factory;
|
||||
|
||||
|
||||
|
||||
import com.aos.starter.core.reflection.ReflectionException;
|
||||
import com.aos.starter.core.reflection.Reflector;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DefaultObjectFactory implements ObjectFactory, Serializable {
|
||||
|
||||
/** serialVersionUID */
|
||||
private static final long serialVersionUID = -8855120656740914948L;
|
||||
|
||||
/**
|
||||
* Create t
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param type type
|
||||
* @return the t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public <T> T create(Class<T> type) {
|
||||
return this.create(type, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create t
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param type type
|
||||
* @param constructorArgTypes constructor arg types
|
||||
* @param constructorArgs constructor args
|
||||
* @return the t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
|
||||
Class<?> classToCreate = this.resolveInterface(type);
|
||||
// we know types are assignable
|
||||
return (T) this.instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is collection boolean
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param type type
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public <T> boolean isCollection(Class<T> type) {
|
||||
return Collection.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve interface class
|
||||
*
|
||||
* @param type type
|
||||
* @return the class
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected Class<?> resolveInterface(Class<?> type) {
|
||||
Class<?> classToCreate;
|
||||
if (type == List.class || type == Collection.class || type == Iterable.class) {
|
||||
classToCreate = ArrayList.class;
|
||||
} else if (type == Map.class) {
|
||||
classToCreate = HashMap.class;
|
||||
} else if (type == SortedSet.class) {
|
||||
classToCreate = TreeSet.class;
|
||||
} else if (type == Set.class) {
|
||||
classToCreate = HashSet.class;
|
||||
} else {
|
||||
classToCreate = type;
|
||||
}
|
||||
return classToCreate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate class t
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param type type
|
||||
* @param constructorArgTypes constructor arg types
|
||||
* @param constructorArgs constructor args
|
||||
* @return the t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
private <T> @NotNull T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
|
||||
try {
|
||||
Constructor<T> constructor;
|
||||
if (constructorArgTypes == null || constructorArgs == null) {
|
||||
constructor = type.getDeclaredConstructor();
|
||||
try {
|
||||
return constructor.newInstance();
|
||||
} catch (IllegalAccessException e) {
|
||||
if (Reflector.canControlMemberAccessible()) {
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
|
||||
try {
|
||||
return constructor.newInstance(constructorArgs.toArray(new Object[0]));
|
||||
} catch (IllegalAccessException e) {
|
||||
if (Reflector.canControlMemberAccessible()) {
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance(constructorArgs.toArray(new Object[0]));
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
|
||||
.stream().map(Class::getSimpleName).collect(Collectors.joining(","));
|
||||
String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
|
||||
.stream().map(String::valueOf).collect(Collectors.joining(","));
|
||||
throw new ReflectionException("Error instantiating {} with invalid types ({}) or values ({}). Cause: ",
|
||||
type, argTypes, argValues, e, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.aos.starter.core.reflection.invoker;
|
||||
|
||||
import com.aos.starter.core.reflection.Reflector;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class GetFieldInvoker implements Invoker {
|
||||
/** Field */
|
||||
private final Field field;
|
||||
|
||||
/**
|
||||
* Get field invoker
|
||||
*
|
||||
* @param field field
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public GetFieldInvoker(Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke object
|
||||
*
|
||||
* @param target target
|
||||
* @param args args
|
||||
* @return the object
|
||||
* @throws IllegalAccessException illegal access exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
|
||||
try {
|
||||
return this.field.get(target);
|
||||
} catch (IllegalAccessException e) {
|
||||
if (Reflector.canControlMemberAccessible()) {
|
||||
this.field.setAccessible(true);
|
||||
return this.field.get(target);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets type *
|
||||
*
|
||||
* @return the type
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
return this.field.getType();
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.aos.starter.core.reflection.wrapper;
|
||||
|
||||
import com.aos.starter.core.reflection.MetaObject;
|
||||
import com.aos.starter.core.reflection.ReflectionException;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:52
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {
|
||||
|
||||
/**
|
||||
* Has wrapper for boolean
|
||||
*
|
||||
* @param object object
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean hasWrapperFor(Object object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets wrapper for *
|
||||
*
|
||||
* @param metaObject meta object
|
||||
* @param object object
|
||||
* @return the wrapper for
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
|
||||
throw new ReflectionException("The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.");
|
||||
}
|
||||
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import com.aos.starter.core.convert.CustomConversionService;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 基于 spring ConversionService 类型转换 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:18
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ConvertUtils {
|
||||
|
||||
/**
|
||||
* Convenience operation for converting a source object to the specified targetType.
|
||||
* {@link TypeDescriptor#forObject(Object)}.
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source the source object
|
||||
* @param targetType the target type
|
||||
* @return the converted value
|
||||
* @throws IllegalArgumentException if targetType is {@code null}, or sourceType is {@code null} but source is not {@code null}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T convert(@Nullable Object source, Class<T> targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (ClassUtils.isAssignableValue(targetType, source)) {
|
||||
return (T) source;
|
||||
}
|
||||
GenericConversionService conversionService = CustomConversionService.getInstance();
|
||||
return conversionService.convert(source, targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience operation for converting a source object to the specified targetType,
|
||||
* where the target type is a descriptor that provides additional conversion context.
|
||||
* {@link TypeDescriptor#forObject(Object)}.
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source the source object
|
||||
* @param sourceType the source type
|
||||
* @param targetType the target type
|
||||
* @return the converted value
|
||||
* @throws IllegalArgumentException if targetType is {@code null}, or sourceType is {@code null} but source is not {@code null}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
GenericConversionService conversionService = CustomConversionService.getInstance();
|
||||
return (T) conversionService.convert(source, sourceType, targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience operation for converting a source object to the specified targetType,
|
||||
* where the target type is a descriptor that provides additional conversion context.
|
||||
* Simply delegates to {@link #convert(Object, TypeDescriptor, TypeDescriptor)} and
|
||||
* encapsulates the construction of the source type descriptor using
|
||||
* {@link TypeDescriptor#forObject(Object)}.
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source the source object
|
||||
* @param targetType the target type
|
||||
* @return the converted value
|
||||
* @throws IllegalArgumentException if targetType is {@code null}, or sourceType is {@code null} but source is not {@code null}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T convert(@Nullable Object source, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
GenericConversionService conversionService = CustomConversionService.getInstance();
|
||||
return (T) conversionService.convert(source, targetType);
|
||||
}
|
||||
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: DateTime 工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:18
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
public class DateTimeUtils {
|
||||
/**
|
||||
* The constant DATETIME_FORMAT.
|
||||
*/
|
||||
public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DateUtils.PATTERN_DATETIME);
|
||||
/**
|
||||
* The constant DATE_FORMAT.
|
||||
*/
|
||||
public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DateUtils.PATTERN_DATE);
|
||||
/**
|
||||
* The constant TIME_FORMAT.
|
||||
*/
|
||||
public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(DateUtils.PATTERN_TIME);
|
||||
|
||||
/**
|
||||
* 日期时间格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String formatDateTime(TemporalAccessor temporal) {
|
||||
return DATETIME_FORMAT.format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期时间格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String formatDate(TemporalAccessor temporal) {
|
||||
return DATE_FORMAT.format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String formatTime(TemporalAccessor temporal) {
|
||||
return TIME_FORMAT.format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @param pattern 表达式
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String format(TemporalAccessor temporal, String pattern) {
|
||||
return DateTimeFormatter.ofPattern(pattern).format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为时间
|
||||
*
|
||||
* @param dateStr 时间字符串
|
||||
* @param pattern 表达式
|
||||
* @return 时间 temporal accessor
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static TemporalAccessor parse(String dateStr, String pattern) {
|
||||
DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
|
||||
return format.parse(dateStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为时间
|
||||
*
|
||||
* @param dateStr 时间字符串
|
||||
* @param formatter DateTimeFormatter
|
||||
* @return 时间 temporal accessor
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static TemporalAccessor parse(String dateStr, @NotNull DateTimeFormatter formatter) {
|
||||
return formatter.parse(dateStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间转 Instant
|
||||
*
|
||||
* @param dateTime 时间
|
||||
* @return Instant instant
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Instant toInstant(@NotNull LocalDateTime dateTime) {
|
||||
return dateTime.atZone(ZoneId.systemDefault()).toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instant 转 时间
|
||||
*
|
||||
* @param instant Instant
|
||||
* @return Instant local date time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static LocalDateTime toDateTime(Instant instant) {
|
||||
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,827 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import com.aos.element.basic.basic.asserts.Assertions;
|
||||
import com.aos.element.basic.basic.constant.ConfigDefaultValue;
|
||||
import com.aos.element.basic.basic.util.ConcurrentDateFormat;
|
||||
import com.aos.element.basic.basic.util.Exceptions;
|
||||
import com.aos.element.basic.basic.util.StringPool;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 日期工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.09 10:38
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@SuppressWarnings("checkstyle:MethodLimit")
|
||||
public class DateUtils {
|
||||
|
||||
/** PATTERN_MS_DATETIME */
|
||||
public static final String PATTERN_MS_DATETIME = ConfigDefaultValue.DEFAULT_DATE_FORMAT.concat(":SSS");
|
||||
/** The constant PATTERN_DATETIME. */
|
||||
public static final String PATTERN_DATETIME = ConfigDefaultValue.DEFAULT_DATE_FORMAT;
|
||||
/** The constant PATTERN_DATE. */
|
||||
public static final String PATTERN_DATE = "yyyy-MM-dd";
|
||||
/** The constant PATTERN_DATE_HOUR. */
|
||||
public static final String PATTERN_DATE_HOUR = "yyyy-MM-dd HH";
|
||||
/** PATTERN_MONTH */
|
||||
public static final String PATTERN_MONTH = "yyyyMM";
|
||||
/** 时分秒 */
|
||||
public static final String PATTERN_TIME = "HH:mm:ss";
|
||||
/** PATTERN_DATE_NO_SEPARATOR */
|
||||
public static final String PATTERN_DATE_NO_SEPARATOR = "yyyyMMdd";
|
||||
/** PATTERN_TIME_NO_SEPARATOR */
|
||||
public static final String PATTERN_TIME_NO_SEPARATOR = "HHmmss";
|
||||
/** PATTERN_DATETIME_NO_SEPARATOR */
|
||||
public static final String PATTERN_DATETIME_NO_SEPARATOR = PATTERN_DATE_NO_SEPARATOR + PATTERN_TIME_NO_SEPARATOR;
|
||||
/** 老 date 格式化 */
|
||||
public static final ConcurrentDateFormat DATETIME_FORMAT = ConcurrentDateFormat.of(PATTERN_DATETIME);
|
||||
/** DATETIME_FORMAT_NO_SEPARATOR */
|
||||
public static final ConcurrentDateFormat DATETIME_FORMAT_NO_SEPARATOR = ConcurrentDateFormat.of(PATTERN_DATETIME_NO_SEPARATOR);
|
||||
/** The constant DATE_FORMAT. */
|
||||
public static final ConcurrentDateFormat DATE_FORMAT = ConcurrentDateFormat.of(PATTERN_DATE);
|
||||
/** DATE_FORMAT_NO_SEPARATOR */
|
||||
public static final ConcurrentDateFormat DATE_FORMAT_NO_SEPARATOR = ConcurrentDateFormat.of(PATTERN_DATE_NO_SEPARATOR);
|
||||
/** The constant TIME_FORMAT. */
|
||||
public static final ConcurrentDateFormat TIME_FORMAT = ConcurrentDateFormat.of(PATTERN_TIME);
|
||||
/** TIME_FORMAT_NO_SEPARATOR */
|
||||
public static final ConcurrentDateFormat TIME_FORMAT_NO_SEPARATOR = ConcurrentDateFormat.of(PATTERN_TIME_NO_SEPARATOR);
|
||||
/** java 8 时间格式化 */
|
||||
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DateUtils.PATTERN_DATETIME);
|
||||
/** DATETIME_FORMATTER_NO_SEPARATOR */
|
||||
public static final DateTimeFormatter DATETIME_FORMATTER_NO_SEPARATOR =
|
||||
DateTimeFormatter.ofPattern(DateUtils.PATTERN_DATETIME_NO_SEPARATOR);
|
||||
/** The constant DATE_FORMATTER. */
|
||||
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DateUtils.PATTERN_DATE);
|
||||
/** DATE_FORMATTER_NO_SEPARATOR */
|
||||
public static final DateTimeFormatter DATE_FORMATTER_NO_SEPARATOR = DateTimeFormatter.ofPattern(DateUtils.PATTERN_DATE_NO_SEPARATOR);
|
||||
/** The constant TIME_FORMATTER. */
|
||||
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(DateUtils.PATTERN_TIME);
|
||||
/** TIME_FORMATTER_NO_SEPARATOR */
|
||||
public static final DateTimeFormatter TIME_FORMATTER_NO_SEPARATOR = DateTimeFormatter.ofPattern(DateUtils.PATTERN_TIME_NO_SEPARATOR);
|
||||
|
||||
/**
|
||||
* 添加年
|
||||
*
|
||||
* @param date 时间
|
||||
* @param yearsToAdd 添加的年数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusYears(Date date, int yearsToAdd) {
|
||||
return DateUtils.set(date, Calendar.YEAR, yearsToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日期属性
|
||||
*
|
||||
* @param date 时间
|
||||
* @param calendarField 更改的属性
|
||||
* @param amount 更改数,-1表示减少
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
private static Date set(Date date, int calendarField, int amount) {
|
||||
Assert.notNull(date, "The date must not be null");
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setLenient(false);
|
||||
c.setTime(date);
|
||||
c.add(calendarField, amount);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加月
|
||||
*
|
||||
* @param date 时间
|
||||
* @param monthsToAdd 添加的月数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusMonths(Date date, int monthsToAdd) {
|
||||
return DateUtils.set(date, Calendar.MONTH, monthsToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加周
|
||||
*
|
||||
* @param date 时间
|
||||
* @param weeksToAdd 添加的周数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusWeeks(Date date, int weeksToAdd) {
|
||||
return DateUtils.plus(date, Period.ofWeeks(weeksToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期添加时间量
|
||||
*
|
||||
* @param date 时间
|
||||
* @param amount 时间量
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plus(@NotNull Date date, TemporalAmount amount) {
|
||||
Instant instant = date.toInstant();
|
||||
return Date.from(instant.plus(amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加天
|
||||
*
|
||||
* @param date 时间
|
||||
* @param daysToAdd 添加的天数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusDays(Date date, long daysToAdd) {
|
||||
return DateUtils.plus(date, Duration.ofDays(daysToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加小时
|
||||
*
|
||||
* @param date 时间
|
||||
* @param hoursToAdd 添加的小时数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusHours(Date date, long hoursToAdd) {
|
||||
return DateUtils.plus(date, Duration.ofHours(hoursToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分钟
|
||||
*
|
||||
* @param date 时间
|
||||
* @param minutesToAdd 添加的分钟数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusMinutes(Date date, long minutesToAdd) {
|
||||
return DateUtils.plus(date, Duration.ofMinutes(minutesToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加秒
|
||||
*
|
||||
* @param date 时间
|
||||
* @param secondsToAdd 添加的秒数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusSeconds(Date date, long secondsToAdd) {
|
||||
return DateUtils.plus(date, Duration.ofSeconds(secondsToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加毫秒
|
||||
*
|
||||
* @param date 时间
|
||||
* @param millisToAdd 添加的毫秒数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusMillis(Date date, long millisToAdd) {
|
||||
return DateUtils.plus(date, Duration.ofMillis(millisToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加纳秒
|
||||
*
|
||||
* @param date 时间
|
||||
* @param nanosToAdd 添加的纳秒数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date plusNanos(Date date, long nanosToAdd) {
|
||||
return DateUtils.plus(date, Duration.ofNanos(nanosToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少年
|
||||
*
|
||||
* @param date 时间
|
||||
* @param years 减少的年数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusYears(Date date, int years) {
|
||||
return DateUtils.set(date, Calendar.YEAR, -years);
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少月
|
||||
*
|
||||
* @param date 时间
|
||||
* @param months 减少的月数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusMonths(Date date, int months) {
|
||||
return DateUtils.set(date, Calendar.MONTH, -months);
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少周
|
||||
*
|
||||
* @param date 时间
|
||||
* @param weeks 减少的周数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusWeeks(Date date, int weeks) {
|
||||
return DateUtils.minus(date, Period.ofWeeks(weeks));
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期减少时间量
|
||||
*
|
||||
* @param date 时间
|
||||
* @param amount 时间量
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minus(@NotNull Date date, TemporalAmount amount) {
|
||||
Instant instant = date.toInstant();
|
||||
return Date.from(instant.minus(amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少天
|
||||
*
|
||||
* @param date 时间
|
||||
* @param days 减少的天数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusDays(Date date, long days) {
|
||||
return DateUtils.minus(date, Duration.ofDays(days));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少小时
|
||||
*
|
||||
* @param date 时间
|
||||
* @param hours 减少的小时数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusHours(Date date, long hours) {
|
||||
return DateUtils.minus(date, Duration.ofHours(hours));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少分钟
|
||||
*
|
||||
* @param date 时间
|
||||
* @param minutes 减少的分钟数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusMinutes(Date date, long minutes) {
|
||||
return DateUtils.minus(date, Duration.ofMinutes(minutes));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少秒
|
||||
*
|
||||
* @param date 时间
|
||||
* @param seconds 减少的秒数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusSeconds(Date date, long seconds) {
|
||||
return DateUtils.minus(date, Duration.ofSeconds(seconds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少毫秒
|
||||
*
|
||||
* @param date 时间
|
||||
* @param millis 减少的毫秒数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusMillis(Date date, long millis) {
|
||||
return DateUtils.minus(date, Duration.ofMillis(millis));
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少纳秒
|
||||
*
|
||||
* @param date 时间
|
||||
* @param nanos 减少的纳秒数
|
||||
* @return 设置后的时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date minusNanos(Date date, long nanos) {
|
||||
return DateUtils.minus(date, Duration.ofNanos(nanos));
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期时间格式化
|
||||
*
|
||||
* @param date 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String formatDateTime(Date date) {
|
||||
return DATETIME_FORMAT.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
*
|
||||
* @param date 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String formatDate(Date date) {
|
||||
return DATE_FORMAT.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间格式化
|
||||
*
|
||||
* @param date 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String formatTime(Date date) {
|
||||
return TIME_FORMAT.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* java8 日期时间格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String formatDateTime(TemporalAccessor temporal) {
|
||||
return DATETIME_FORMATTER.format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* java8 日期时间格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String formatDate(TemporalAccessor temporal) {
|
||||
return DATE_FORMATTER.format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* java8 时间格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String formatTime(TemporalAccessor temporal) {
|
||||
return TIME_FORMATTER.format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* java8 日期格式化
|
||||
*
|
||||
* @param temporal 时间
|
||||
* @param pattern 表达式
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String format(TemporalAccessor temporal, String pattern) {
|
||||
return DateTimeFormatter.ofPattern(pattern).format(temporal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse date time
|
||||
*
|
||||
* @param dateStr date str
|
||||
* @return the date
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static Date parseDateTime(String dateStr) {
|
||||
return parse(dateStr, PATTERN_DATETIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为时间
|
||||
*
|
||||
* @param dateStr 时间字符串
|
||||
* @param pattern 表达式
|
||||
* @return 时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date parse(String dateStr, String pattern) {
|
||||
Assertions.notBlank(dateStr, "参数错误, 时间字符串不能为空");
|
||||
ConcurrentDateFormat format = ConcurrentDateFormat.of(pattern);
|
||||
try {
|
||||
return format.parse(dateStr);
|
||||
} catch (ParseException e) {
|
||||
throw Exceptions.unchecked(StringUtils.format("不能将 {} 以 {} 格式转换为 Date 类型", dateStr, pattern), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为时间
|
||||
*
|
||||
* @param dateStr 时间字符串
|
||||
* @param format ConcurrentDateFormat
|
||||
* @return 时间 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Date parse(String dateStr, @NotNull ConcurrentDateFormat format) {
|
||||
try {
|
||||
return format.parse(dateStr);
|
||||
} catch (ParseException e) {
|
||||
throw Exceptions.unchecked(StringUtils.format("不能将 {} 以 {} 格式转换为 Date 类型", dateStr, format.getFormat()), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为时间
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param dateStr 时间字符串
|
||||
* @param pattern 表达式
|
||||
* @param query the query
|
||||
* @return 时间 t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T parse(String dateStr, String pattern, TemporalQuery<T> query) {
|
||||
return DateTimeFormatter.ofPattern(pattern).parse(dateStr, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instant 转 时间
|
||||
*
|
||||
* @param instant Instant
|
||||
* @return Instant local date time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static LocalDateTime toDateTime(Instant instant) {
|
||||
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成 date
|
||||
*
|
||||
* @param dateTime LocalDateTime
|
||||
* @return Date date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date toDate(LocalDateTime dateTime) {
|
||||
return Date.from(DateUtils.toInstant(dateTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间转 Instant
|
||||
*
|
||||
* @param dateTime 时间
|
||||
* @return Instant instant
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Instant toInstant(@NotNull LocalDateTime dateTime) {
|
||||
return dateTime.atZone(ZoneId.systemDefault()).toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成 date
|
||||
*
|
||||
* @param localDate LocalDate
|
||||
* @return Date date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Date toDate(@NotNull LocalDate localDate) {
|
||||
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts local date time to Calendar.
|
||||
*
|
||||
* @param localDateTime the local date time
|
||||
* @return the calendar
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static Calendar toCalendar(LocalDateTime localDateTime) {
|
||||
return GregorianCalendar.from(ZonedDateTime.of(localDateTime, ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
/**
|
||||
* localDate 转换成毫秒数
|
||||
*
|
||||
* @param localDate LocalDate
|
||||
* @return long long
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static long toMilliseconds(@NotNull LocalDate localDate) {
|
||||
return toMilliseconds(localDate.atStartOfDay());
|
||||
}
|
||||
|
||||
/**
|
||||
* localDateTime 转换成毫秒数
|
||||
*
|
||||
* @param localDateTime LocalDateTime
|
||||
* @return long long
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static long toMilliseconds(@NotNull LocalDateTime localDateTime) {
|
||||
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成java8 时间
|
||||
*
|
||||
* @param calendar 日历
|
||||
* @return LocalDateTime local date time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static LocalDateTime fromCalendar(@NotNull Calendar calendar) {
|
||||
TimeZone tz = calendar.getTimeZone();
|
||||
ZoneId zid = tz == null ? ZoneId.systemDefault() : tz.toZoneId();
|
||||
return LocalDateTime.ofInstant(calendar.toInstant(), zid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成java8 时间
|
||||
*
|
||||
* @param instant Instant
|
||||
* @return LocalDateTime local date time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static LocalDateTime fromInstant(Instant instant) {
|
||||
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成java8 时间
|
||||
*
|
||||
* @param date Date
|
||||
* @return LocalDateTime local date time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static LocalDateTime fromDate(@NotNull Date date) {
|
||||
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成java8 时间
|
||||
*
|
||||
* @param milliseconds 毫秒数
|
||||
* @return LocalDateTime local date time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static LocalDateTime fromMilliseconds(long milliseconds) {
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较2个时间差,跨度比较小
|
||||
*
|
||||
* @param startInclusive 开始时间
|
||||
* @param endExclusive 结束时间
|
||||
* @return 时间间隔 duration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Duration between(Temporal startInclusive, Temporal endExclusive) {
|
||||
return Duration.between(startInclusive, endExclusive);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较2个时间差,跨度比较大,年月日为单位
|
||||
*
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 时间间隔 period
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Period between(LocalDate startDate, LocalDate endDate) {
|
||||
return Period.between(startDate, endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较2个 时间差
|
||||
*
|
||||
* @param startDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @return 时间间隔 duration
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Duration between(@NotNull Date startDate, @NotNull Date endDate) {
|
||||
return Duration.between(startDate.toInstant(), endDate.toInstant());
|
||||
}
|
||||
|
||||
/**
|
||||
* Between
|
||||
*
|
||||
* @param startTime start time
|
||||
* @param targetDate target date
|
||||
* @param endTime end time
|
||||
* @return the boolean
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public static boolean between(Date startTime, Date targetDate, Date endTime) {
|
||||
return startTime.getTime() <= targetDate.getTime()
|
||||
&& endTime.getTime() >= targetDate.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将秒数转换为日时分秒
|
||||
*
|
||||
* @param second 秒数
|
||||
* @return 时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String secondToTime(Long second) {
|
||||
// 判断是否为空
|
||||
if (second == null || second == 0L) {
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
//转换天数
|
||||
long days = second / 86400;
|
||||
//剩余秒数
|
||||
second = second % 86400;
|
||||
//转换小时
|
||||
long hours = second / 3600;
|
||||
//剩余秒数
|
||||
second = second % 3600;
|
||||
//转换分钟
|
||||
long minutes = second / 60;
|
||||
//剩余秒数
|
||||
second = second % 60;
|
||||
if (days > 0) {
|
||||
return StringUtils.format("{}天{}小时{}分{}秒", days, hours, minutes, second);
|
||||
} else {
|
||||
return StringUtils.format("{}小时{}分{}秒", hours, minutes, second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式的时间转换为 long
|
||||
*
|
||||
* @param dateString the date string
|
||||
* @return the long
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static Long timeToSecond(String dateString) {
|
||||
return parse(dateString, PATTERN_DATETIME).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Time to millisecond
|
||||
*
|
||||
* @param dateString date string
|
||||
* @return the long
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static Long timeToMillisecond(String dateString) {
|
||||
return parse(dateString, PATTERN_MS_DATETIME).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取今天的日期
|
||||
*
|
||||
* @return 时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String today() {
|
||||
return format(new Date(), PATTERN_DATE_NO_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Now date
|
||||
*
|
||||
* @return the date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(" -> new")
|
||||
public static Date now() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
*
|
||||
* @param date 时间
|
||||
* @param pattern 表达式
|
||||
* @return 格式化后的时间 string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String format(Date date, String pattern) {
|
||||
return ConcurrentDateFormat.of(pattern).format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间到当日最后时间相差的分钟数
|
||||
*
|
||||
* @param nowTime the now time
|
||||
* @return int int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static int diffMinutesTime(Date nowTime) {
|
||||
nowTime = null == nowTime ? now() : nowTime;
|
||||
|
||||
Calendar todayLastTime = DateUtils.getCurrentCalendar();
|
||||
todayLastTime.set(Calendar.HOUR_OF_DAY, 23);
|
||||
todayLastTime.set(Calendar.MINUTE, 59);
|
||||
todayLastTime.set(Calendar.SECOND, 59);
|
||||
|
||||
return (int) ((todayLastTime.getTimeInMillis() - nowTime.getTime()) / 1000 / 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff minutes time int
|
||||
*
|
||||
* @return the int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static int diffMinutesTime() {
|
||||
return diffMinutesTime(now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current calendar *
|
||||
*
|
||||
* @return the current calendar
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static Calendar getCurrentCalendar() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
|
||||
calendar.setTimeZone(timeZone);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
}
|
||||
+777
@@ -0,0 +1,777 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import com.aos.element.basic.basic.util.Charsets;
|
||||
import com.aos.element.basic.basic.util.Exceptions;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 加密相关工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:25
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@SuppressWarnings("all")
|
||||
public class DigestUtils extends org.springframework.util.DigestUtils {
|
||||
|
||||
/**
|
||||
* HEX_VALUE
|
||||
*/
|
||||
private static final String HEX_VALUE = "0123456789abcdef";
|
||||
/**
|
||||
* HEX_CODE
|
||||
*/
|
||||
private static final char[] HEX_CODE = HEX_VALUE.toCharArray();
|
||||
|
||||
/**
|
||||
* Calculates the MD5 digest.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return MD5 digest as a hex array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] md5(byte[] data) {
|
||||
return org.springframework.util.DigestUtils.md5Digest(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the MD5 digest.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return MD5 digest as a hex array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] md5(@NotNull String data) {
|
||||
return org.springframework.util.DigestUtils.md5Digest(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hexadecimal string representation of the MD5 digest of the given bytes.
|
||||
*
|
||||
* @param bytes the bytes to calculate the digest over
|
||||
* @return a hexadecimal digest string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String md5Hex(byte[] bytes) {
|
||||
return org.springframework.util.DigestUtils.md5DigestAsHex(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha1Hex(@NotNull String data) {
|
||||
return DigestUtils.encodeHex(sha1(data.getBytes(Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* encode Hex
|
||||
*
|
||||
* @param bytes Data to Hex
|
||||
* @return bytes as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String encodeHex(byte[] bytes) {
|
||||
StringBuilder r = new StringBuilder(bytes.length * 2);
|
||||
for (byte b : bytes) {
|
||||
r.append(HEX_CODE[(b >> 4) & 0xF]);
|
||||
r.append(HEX_CODE[(b & 0xF)]);
|
||||
}
|
||||
return r.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha1(byte[] bytes) {
|
||||
return DigestUtils.digest("SHA-1", bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* digest
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param bytes Data to digest
|
||||
* @return digest byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] digest(String algorithm, byte[] bytes) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||
return md.digest(bytes);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha1Hex(byte[] bytes) {
|
||||
return DigestUtils.encodeHex(sha1(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA224
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha224(@NotNull String data) {
|
||||
return DigestUtils.sha224(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA224
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha224(byte[] bytes) {
|
||||
return DigestUtils.digest("SHA-224", bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA224Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha224Hex(@NotNull String data) {
|
||||
return DigestUtils.encodeHex(sha224(data.getBytes(Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA224Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha224Hex(byte[] bytes) {
|
||||
return DigestUtils.encodeHex(sha224(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha256(@NotNull String data) {
|
||||
return DigestUtils.sha256(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha256(byte[] bytes) {
|
||||
return DigestUtils.digest("SHA-256", bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha256Hex(@NotNull String data) {
|
||||
return DigestUtils.encodeHex(sha256(data.getBytes(Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha256Hex(byte[] bytes) {
|
||||
return DigestUtils.encodeHex(sha256(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha384
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha384(@NotNull String data) {
|
||||
return DigestUtils.sha384(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha384
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha384(byte[] bytes) {
|
||||
return DigestUtils.digest("SHA-384", bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha384Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha384Hex(@NotNull String data) {
|
||||
return DigestUtils.encodeHex(sha384(data.getBytes(Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha384Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha384Hex(byte[] bytes) {
|
||||
return DigestUtils.encodeHex(sha384(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha512Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha512(@NotNull String data) {
|
||||
return DigestUtils.sha512(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha512Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha512(byte[] bytes) {
|
||||
return DigestUtils.digest("SHA-512", bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha512Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha512Hex(@NotNull String data) {
|
||||
return DigestUtils.encodeHex(sha512(data.getBytes(Charsets.UTF_8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha512Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String sha512Hex(byte[] bytes) {
|
||||
return DigestUtils.encodeHex(sha512(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* digest Hex
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param bytes Data to digest
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String digestHex(String algorithm, byte[] bytes) {
|
||||
return DigestUtils.encodeHex(digest(algorithm, bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacMd5
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacMd5(@NotNull String data, String key) {
|
||||
return DigestUtils.hmacMd5(data.getBytes(Charsets.UTF_8), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacMd5
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacMd5(byte[] bytes, String key) {
|
||||
return DigestUtils.digestHmac("HmacMD5", bytes, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* digest Hmac
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param bytes Data to digest
|
||||
* @param key the key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] digestHmac(String algorithm, byte[] bytes, @NotNull String key) {
|
||||
SecretKey secretKey = new SecretKeySpec(key.getBytes(Charsets.UTF_8), algorithm);
|
||||
try {
|
||||
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
|
||||
mac.init(secretKey);
|
||||
return mac.doFinal(bytes);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacMd5 Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacMd5Hex(@NotNull String data, String key) {
|
||||
return DigestUtils.encodeHex(hmacMd5(data.getBytes(Charsets.UTF_8), key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacMd5 Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacMd5Hex(byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(hmacMd5(bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha1
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha1(@NotNull String data, String key) {
|
||||
return DigestUtils.hmacSha1(data.getBytes(Charsets.UTF_8), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha1
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha1(byte[] bytes, String key) {
|
||||
return DigestUtils.digestHmac("HmacSHA1", bytes, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha1 Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha1Hex(@NotNull String data, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha1(data.getBytes(Charsets.UTF_8), key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha1 Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha1Hex(byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha1(bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha224
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha224(@NotNull String data, String key) {
|
||||
return DigestUtils.hmacSha224(data.getBytes(Charsets.UTF_8), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha224
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha224(byte[] bytes, String key) {
|
||||
return DigestUtils.digestHmac("HmacSHA224", bytes, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha224 Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha224Hex(@NotNull String data, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha224(data.getBytes(Charsets.UTF_8), key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha224 Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha224Hex(byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha224(bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha256
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha256(@NotNull String data, String key) {
|
||||
return DigestUtils.hmacSha256(data.getBytes(Charsets.UTF_8), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha256
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha256(byte[] bytes, String key) {
|
||||
return DigestUtils.digestHmac("HmacSHA256", bytes, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha256 Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha256Hex(@NotNull String data, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha256(data.getBytes(Charsets.UTF_8), key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha256 Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha256Hex(byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha256(bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha384
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha384(@NotNull String data, String key) {
|
||||
return DigestUtils.hmacSha384(data.getBytes(Charsets.UTF_8), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha384
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha384(byte[] bytes, String key) {
|
||||
return DigestUtils.digestHmac("HmacSHA384", bytes, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha384 Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha384Hex(@NotNull String data, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha384(data.getBytes(Charsets.UTF_8), key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha384 Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha384Hex(byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha384(bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha512
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha512(@NotNull String data, String key) {
|
||||
return DigestUtils.hmacSha512(data.getBytes(Charsets.UTF_8), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha512
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a byte array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] hmacSha512(byte[] bytes, String key) {
|
||||
return DigestUtils.digestHmac("HmacSHA512", bytes, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha512 Hex
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha512Hex(@NotNull String data, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha512(data.getBytes(Charsets.UTF_8), key));
|
||||
}
|
||||
|
||||
/**
|
||||
* hmacSha512 Hex
|
||||
*
|
||||
* @param bytes Data to digest
|
||||
* @param key key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String hmacSha512Hex(byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(hmacSha512(bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* digest Hmac Hex
|
||||
*
|
||||
* @param algorithm 算法
|
||||
* @param bytes Data to digest
|
||||
* @param key the key
|
||||
* @return digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String digestHmacHex(String algorithm, byte[] bytes, String key) {
|
||||
return DigestUtils.encodeHex(DigestUtils.digestHmac(algorithm, bytes, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* decode Hex
|
||||
*
|
||||
* @param hexStr Hex string
|
||||
* @return decode hex to bytes
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("PMD.UndefineMagicConstantRule")
|
||||
public static byte[] decodeHex(@NotNull String hexStr) {
|
||||
int len = hexStr.length();
|
||||
if ((len & 0x01) != 0) {
|
||||
throw new IllegalArgumentException("hexBinary needs to be even-length: " + hexStr);
|
||||
}
|
||||
String hexText = hexStr.toLowerCase();
|
||||
byte[] out = new byte[len >> 1];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
int hn = HEX_VALUE.indexOf(hexText.charAt(i));
|
||||
int ln = HEX_VALUE.indexOf(hexText.charAt(i + 1));
|
||||
if (hn == -1 || ln == -1) {
|
||||
throw new IllegalArgumentException("contains illegal character for hexBinary: " + hexStr);
|
||||
}
|
||||
out[i / 2] = (byte) ((hn << 4) | ln);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较字符串,避免字符串因为过长,产生耗时
|
||||
*
|
||||
* @param a String
|
||||
* @param b String
|
||||
* @return 是否相同 boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> false; !null, null -> false")
|
||||
public static boolean slowEquals(@Nullable String a, @Nullable String b) {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
return DigestUtils.slowEquals(a.getBytes(Charsets.UTF_8), b.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较 byte 数组,避免字符串因为过长,产生耗时
|
||||
*
|
||||
* @param a byte array
|
||||
* @param b byte array
|
||||
* @return 是否相同 boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(value = "null, _ -> false; !null, null -> false", pure = true)
|
||||
public static boolean slowEquals(@Nullable byte[] a, @Nullable byte[] b) {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
if (a.length != b.length) {
|
||||
return false;
|
||||
}
|
||||
int diff = a.length ^ b.length;
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
diff |= a[i] ^ b[i];
|
||||
}
|
||||
return diff == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义加密 先MD5再SHA1
|
||||
*
|
||||
* @param data 数据
|
||||
* @return String string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String encrypt(String data) {
|
||||
return DigestUtils.encodeHex(sha1(md5Hex(data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return digest as a hex array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] sha1(@NotNull String data) {
|
||||
return DigestUtils.sha1(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the MD5 digest and returns the value as a 32 character hex string.
|
||||
*
|
||||
* @param data Data to digest
|
||||
* @return MD5 digest as a hex string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String md5Hex(@NotNull String data) {
|
||||
return org.springframework.util.DigestUtils.md5DigestAsHex(data.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,704 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
|
||||
import com.aos.element.basic.basic.asserts.Assertions;
|
||||
import com.aos.element.basic.basic.constant.ConfigKey;
|
||||
import com.aos.element.basic.basic.util.CharPool;
|
||||
import com.aos.element.basic.basic.util.Charsets;
|
||||
import com.aos.element.basic.basic.util.Exceptions;
|
||||
import com.aos.element.basic.basic.util.IoUtils;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 文件工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:26
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
@SuppressWarnings("checkstyle:MethodLimit")
|
||||
public class FileUtils extends org.springframework.util.FileCopyUtils {
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param path 路径
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<File> list(String path) {
|
||||
File file = new File(path);
|
||||
return list(file, TrueFilter.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param path 路径
|
||||
* @param fileNamePattern 文件名 * 号
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<File> list(String path, String fileNamePattern) {
|
||||
File file = new File(path);
|
||||
return list(file, pathname -> {
|
||||
String fileName = pathname.getName();
|
||||
return PatternMatchUtils.simpleMatch(fileNamePattern, fileName);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param path 路径
|
||||
* @param filter 文件过滤
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<File> list(String path, FileFilter filter) {
|
||||
File file = new File(path);
|
||||
return list(file, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param file 文件
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<File> list(File file) {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
return list(file, fileList, TrueFilter.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param file 文件
|
||||
* @param fileNamePattern Spring AntPathMatcher 规则
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<File> list(File file, String fileNamePattern) {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
return list(file, fileList, pathname -> {
|
||||
String fileName = pathname.getName();
|
||||
return PatternMatchUtils.simpleMatch(fileNamePattern, fileName);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param file 文件
|
||||
* @param filter 文件过滤
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<File> list(File file, FileFilter filter) {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
return list(file, fileList, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描目录下的文件
|
||||
*
|
||||
* @param file 文件
|
||||
* @param fileList file list
|
||||
* @param filter 文件过滤
|
||||
* @return 文件集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_, _, _ -> param2")
|
||||
private static List<File> list(@NotNull File file, List<File> fileList, FileFilter filter) {
|
||||
if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
list(f, fileList, filter);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 过滤文件
|
||||
boolean accept = filter.accept(file);
|
||||
if (file.exists() && accept) {
|
||||
fileList.add(file);
|
||||
}
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件后缀名
|
||||
*
|
||||
* @param fullName 文件全名
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String getFileExtension(String fullName) {
|
||||
Assertions.notNull(fullName, "file fullName is null.");
|
||||
String fileName = new File(fullName).getName();
|
||||
int dotIndex = fileName.lastIndexOf('.');
|
||||
return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件名,去除后缀名
|
||||
*
|
||||
* @param file 文件
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static @NotNull String getNameWithoutExtension(String file) {
|
||||
Assertions.notNull(file, "file is null.");
|
||||
String fileName = new File(file).getName();
|
||||
int dotIndex = fileName.lastIndexOf(CharPool.DOT);
|
||||
return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link File} representing the system temporary directory.
|
||||
*
|
||||
* @return the system temporary directory.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(" -> new")
|
||||
public static File getTempDir() {
|
||||
return new File(getTempDirPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the system temporary directory.
|
||||
*
|
||||
* @return the path to the system temporary directory.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String getTempDirPath() {
|
||||
return System.getProperty(ConfigKey.JvmConfigKey.TMP_DIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接临时文件目录.
|
||||
*
|
||||
* @param subDirFile sub dir file
|
||||
* @return 临时文件目录. string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String toTempDirPath(String subDirFile) {
|
||||
return FileUtils.toTempDir(subDirFile).getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接临时文件目录.
|
||||
*
|
||||
* @param subDirFile sub dir file
|
||||
* @return the system temporary directory.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static @NotNull File toTempDir(@NotNull String subDirFile) {
|
||||
String tempDirPath = FileUtils.getTempDirPath();
|
||||
// 删除子目录目录分隔符
|
||||
if (subDirFile.startsWith(File.separator)) {
|
||||
subDirFile = subDirFile.substring(1);
|
||||
}
|
||||
// 为临时目录最后添加目录分隔符
|
||||
if (!tempDirPath.endsWith(File.separator)) {
|
||||
tempDirPath += File.separator;
|
||||
}
|
||||
String fullPath = tempDirPath.concat(subDirFile);
|
||||
File fullFilePath = new File(fullPath);
|
||||
File dir = fullFilePath.getParentFile();
|
||||
if (!dir.exists() && dir.mkdirs()) {
|
||||
log.debug("{} 不存在, 创建成功", dir);
|
||||
}
|
||||
return fullFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of a file into a String.
|
||||
* The file is always closed.
|
||||
*
|
||||
* @param file the file to read, must not be {@code null}
|
||||
* @return the file contents, never {@code null}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String readToString(File file) {
|
||||
return readToString(file, Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of a file into a String.
|
||||
* The file is always closed.
|
||||
*
|
||||
* @param file the file to read, must not be {@code null}
|
||||
* @param encoding the encoding to use, {@code null} means platform default
|
||||
* @return the file contents, never {@code null}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String readToString(File file, Charset encoding) {
|
||||
try (InputStream in = Files.newInputStream(file.toPath())) {
|
||||
return IoUtils.toString(in, encoding);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of a file into a String.
|
||||
* The file is always closed.
|
||||
*
|
||||
* @param file the file to read, must not be {@code null}
|
||||
* @return the file contents, never {@code null}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static byte[] readToByteArray(File file) {
|
||||
try (InputStream in = Files.newInputStream(file.toPath())) {
|
||||
return IoUtils.toByteArray(in);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a String to a file creating the file if it does not exist.
|
||||
*
|
||||
* @param file the file to write
|
||||
* @param data the content to write to the file
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void writeToFile(File file, String data) {
|
||||
writeToFile(file, data, Charsets.UTF_8, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a String to a file creating the file if it does not exist.
|
||||
*
|
||||
* @param file the file to write
|
||||
* @param data the content to write to the file
|
||||
* @param encoding the encoding to use, {@code null} means platform default
|
||||
* @param append if {@code true}, then the String will be added to the end of the file rather than overwriting
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void writeToFile(File file, String data, Charset encoding, boolean append) {
|
||||
try (OutputStream out = new FileOutputStream(file, append)) {
|
||||
IoUtils.write(data, out, encoding);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a String to a file creating the file if it does not exist.
|
||||
*
|
||||
* @param file the file to write
|
||||
* @param data the content to write to the file
|
||||
* @param append if {@code true}, then the String will be added to the end of the file rather than overwriting
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void writeToFile(File file, String data, boolean append) {
|
||||
writeToFile(file, data, Charsets.UTF_8, append);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a String to a file creating the file if it does not exist.
|
||||
*
|
||||
* @param file the file to write
|
||||
* @param data the content to write to the file
|
||||
* @param encoding the encoding to use, {@code null} means platform default
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void writeToFile(File file, String data, Charset encoding) {
|
||||
writeToFile(file, data, encoding, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转成file
|
||||
*
|
||||
* @param multipartFile MultipartFile
|
||||
* @param file File
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void toFile(@NotNull MultipartFile multipartFile, File file) {
|
||||
try {
|
||||
FileUtils.toFile(multipartFile.getInputStream(), file);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转成file
|
||||
*
|
||||
* @param in InputStream
|
||||
* @param file File
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void toFile(InputStream in, File file) {
|
||||
try (OutputStream out = new FileOutputStream(file)) {
|
||||
FileUtils.copy(in, out);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a file.
|
||||
* <p>
|
||||
* When the destination file is on another file system, do a "copy and delete".
|
||||
*
|
||||
* @param srcFile the file to be moved
|
||||
* @param destFile the destination file
|
||||
* @throws IOException if source or destination is invalid
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void moveFile(File srcFile, File destFile) throws IOException {
|
||||
Assert.notNull(srcFile, "Source must not be null");
|
||||
Assert.notNull(destFile, "Destination must not be null");
|
||||
if (!srcFile.exists()) {
|
||||
throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
|
||||
}
|
||||
if (srcFile.isDirectory()) {
|
||||
throw new IOException("Source '" + srcFile + "' is a directory");
|
||||
}
|
||||
if (destFile.exists()) {
|
||||
throw new IOException("Destination '" + destFile + "' already exists");
|
||||
}
|
||||
if (destFile.isDirectory()) {
|
||||
throw new IOException("Destination '" + destFile + "' is a directory");
|
||||
}
|
||||
boolean rename = srcFile.renameTo(destFile);
|
||||
if (!rename) {
|
||||
FileUtils.copy(srcFile, destFile);
|
||||
if (!srcFile.delete()) {
|
||||
FileUtils.deleteQuietly(destFile);
|
||||
throw new IOException("Failed to delete original file '" + srcFile + "' after copy to '" + destFile + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
|
||||
* <p>
|
||||
* The difference between File.delete() and this method are:
|
||||
* <ul>
|
||||
* <li>A directory to be deleted does not have to be empty.</li>
|
||||
* <li>No exceptions are thrown when a file or directory cannot be deleted.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param file file or directory to delete, can be {@code null}
|
||||
* @return {@code true} if the file or directory was deleted, otherwise {@code false}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean deleteQuietly(@Nullable File file) {
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (file.isDirectory()) {
|
||||
FileSystemUtils.deleteRecursively(file);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
return file.delete();
|
||||
} catch (Exception ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NIO 按行读取文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @return 行列表 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<String> readLines(String path) {
|
||||
return readLines(Paths.get(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* NIO 按行读取文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @return 行列表 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<String> readLines(Path path) {
|
||||
return readLines(path, Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* NIO 按行读取文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param cs 字符集
|
||||
* @return 行列表 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<String> readLines(Path path, Charset cs) {
|
||||
try {
|
||||
return Files.readAllLines(path, cs);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NIO 按行读取文件
|
||||
*
|
||||
* @param file 文件
|
||||
* @return 行列表 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<String> readLines(@NotNull File file) {
|
||||
return readLines(file.toPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* NIO 按行读取文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param cs 字符集
|
||||
* @return 行列表 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<String> readLines(String path, Charset cs) {
|
||||
return readLines(Paths.get(path), cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* NIO 按行读取文件
|
||||
*
|
||||
* @param file 文件
|
||||
* @param cs 字符集
|
||||
* @return 行列表 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static List<String> readLines(@NotNull File file, Charset cs) {
|
||||
return readLines(file.toPath(), cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成不同平台的下的路径
|
||||
*
|
||||
* @param path the path
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String getRealFilePath(@NotNull String path) {
|
||||
return path.replace("/", File.separator).replace("\\", File.separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接不同平台下的文件路径, 末尾不含路径分隔符
|
||||
*
|
||||
* @param paths paths
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String appendPath(@NotNull String... paths) {
|
||||
// 删除前缀后后缀
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
paths[i] = StringUtils.removeSuffix(paths[i], File.separator);
|
||||
// 第一个路径不删除前缀
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
paths[i] = StringUtils.removePrefix(paths[i], File.separator);
|
||||
}
|
||||
|
||||
return String.join(File.separator, paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除指定目录及文件
|
||||
*
|
||||
* @param first first
|
||||
* @param more more
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static boolean deleteFiles(String first, String... more) {
|
||||
Path start = Paths.get(first, more);
|
||||
if (start.toFile().exists()) {
|
||||
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
try {
|
||||
Files.delete(file);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException e) {
|
||||
if (e == null) {
|
||||
try {
|
||||
Files.delete(dir);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
// 如果存在异常, 则说明文件不存在
|
||||
return FileVisitResult.SKIP_SUBTREE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件路径且处理 path 最后一个路径分隔符
|
||||
*
|
||||
* @param path path
|
||||
* @return the string
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public static @NotNull String toPath(String path) {
|
||||
File logFile = new File(path);
|
||||
if (!logFile.exists() && logFile.mkdirs()) {
|
||||
log.info(String.format("创建日志目录: %s", logFile.getPath()));
|
||||
}
|
||||
return logFile.getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认为true
|
||||
*
|
||||
* @author L.cm
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:26
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static class TrueFilter implements FileFilter, Serializable {
|
||||
/**
|
||||
* The constant TRUE.
|
||||
*/
|
||||
public static final TrueFilter TRUE = new TrueFilter();
|
||||
/** serialVersionUID */
|
||||
private static final long serialVersionUID = -6420452043795072619L;
|
||||
|
||||
/**
|
||||
* Accept boolean
|
||||
*
|
||||
* @param pathname pathname
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch
|
||||
*
|
||||
* @param file file
|
||||
* @throws IOException io exception
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static void touch(@NotNull File file) throws IOException {
|
||||
if (!file.exists()) {
|
||||
OutputStream out = openOutputStream(file);
|
||||
IoUtils.closeQuietly(out);
|
||||
}
|
||||
|
||||
boolean success = file.setLastModified(System.currentTimeMillis());
|
||||
if (!success) {
|
||||
throw new IOException("Unable to set the last modification time for " + file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open output stream
|
||||
*
|
||||
* @param file file
|
||||
* @return the file output stream
|
||||
* @throws IOException io exception
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static @NotNull FileOutputStream openOutputStream(File file) throws IOException {
|
||||
return openOutputStream(file, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open output stream
|
||||
*
|
||||
* @param file file
|
||||
* @param append append
|
||||
* @return the file output stream
|
||||
* @throws IOException io exception
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Contract("_, _ -> new")
|
||||
public static @NotNull FileOutputStream openOutputStream(@NotNull File file, boolean append) throws IOException {
|
||||
if (file.exists()) {
|
||||
if (file.isDirectory()) {
|
||||
throw new IOException("File '" + file + "' exists but is a directory");
|
||||
}
|
||||
|
||||
if (!file.canWrite()) {
|
||||
throw new IOException("File '" + file + "' cannot be written to");
|
||||
}
|
||||
} else {
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.mkdirs() && !parent.isDirectory()) {
|
||||
throw new IOException("Directory '" + parent + "' could not be created");
|
||||
}
|
||||
}
|
||||
|
||||
return new FileOutputStream(file, append);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 一些常用的单例对象 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:17
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public final class Holder {
|
||||
|
||||
/** RANDOM */
|
||||
public static final Random RANDOM = new Random();
|
||||
|
||||
/** SECURE_RANDOM */
|
||||
public static final SecureRandom SECURE_RANDOM = new SecureRandom();
|
||||
}
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import com.aos.element.basic.basic.util.Charsets;
|
||||
import com.aos.element.basic.basic.util.HttpsUtils;
|
||||
import com.aos.element.basic.basic.util.JsonUtils;
|
||||
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.03.04 14:02
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
public class HttpClientUtils {
|
||||
|
||||
/** 最大连接数 */
|
||||
private static final int MAX_CONNECTION_TOTAL = 300;
|
||||
/** 路由并发数 */
|
||||
private static final int ROUTE_MAX_COUNT = 200;
|
||||
/** 重试次数 */
|
||||
private static final int RETRY_COUNT = 3;
|
||||
/** 连接超时 */
|
||||
private static final int CONNECTION_TIME_OUT = 45000;
|
||||
/** 数据超时 */
|
||||
private static final int READ_TIME_OUT = 75000;
|
||||
/** 连接等待 */
|
||||
private static final int CONNECTION_REQUEST_TIME_OUT = 5000;
|
||||
/** 编码 */
|
||||
private static final String CHARSET = Charsets.UTF_8_NAME;
|
||||
|
||||
/**
|
||||
* Post for object t
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param url url
|
||||
* @param requestBody request body
|
||||
* @param contentType content type
|
||||
* @param responseType response type
|
||||
* @return the t
|
||||
* @throws Exception exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T postForObject(String url,
|
||||
Object requestBody,
|
||||
MediaType contentType,
|
||||
Class<T> responseType) throws Exception {
|
||||
return postForObjectWithHeader(url, requestBody, contentType, responseType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post for object with header t
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param url url
|
||||
* @param requestBody request body
|
||||
* @param contentType content type
|
||||
* @param responseType response type
|
||||
* @param headers headers
|
||||
* @return the t
|
||||
* @throws Exception exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T postForObjectWithHeader(String url,
|
||||
Object requestBody,
|
||||
MediaType contentType,
|
||||
Class<T> responseType,
|
||||
Map<String, String[]> headers) throws Exception {
|
||||
try (CloseableHttpClient httpClient = acceptsUntrustedCertsHttpClient()) {
|
||||
|
||||
RestTemplate restTemplate = getRestTemplate(httpClient);
|
||||
|
||||
// headers
|
||||
HttpHeaders httpHeaders = getDefaultHeader(contentType);
|
||||
if (!Objects.isNull(headers)) {
|
||||
fillHeaders(httpHeaders, headers);
|
||||
}
|
||||
|
||||
HttpEntity<Object> httpEntity = new HttpEntity<>(requestBody, httpHeaders);
|
||||
return restTemplate.postForObject(url, httpEntity, responseType);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("网络异常或请求错误.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets for object with header *
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param url url
|
||||
* @param responseType response type
|
||||
* @param headerName header name
|
||||
* @param headerValue header value
|
||||
* @return the for object with header
|
||||
* @throws Exception exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T getForObjectWithHeader(String url,
|
||||
Class<T> responseType,
|
||||
String headerName,
|
||||
String headerValue) throws Exception {
|
||||
HttpHeaders httpHeaders = getDefaultHeader(MediaType.APPLICATION_JSON);
|
||||
httpHeaders.add(headerName, headerValue);
|
||||
return getForObject(url, responseType, httpHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets for object *
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param url url
|
||||
* @param responseType response type
|
||||
* @return the for object
|
||||
* @throws Exception exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T getForObject(String url, Class<T> responseType) throws Exception {
|
||||
return getForObject(url, responseType, getDefaultHeader(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default header *
|
||||
*
|
||||
* @param contentType content type
|
||||
* @return the default header
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static HttpHeaders getDefaultHeader(MediaType contentType) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
List<MediaType> acceptableMediaTypes = new ArrayList<>();
|
||||
acceptableMediaTypes.add(MediaType.ALL);
|
||||
headers.setAccept(acceptableMediaTypes);
|
||||
headers.setContentType(contentType);
|
||||
headers.add("Connection", "Keep-Alive");
|
||||
headers.add("Content-Encoding", "gzip");
|
||||
headers.add("Vary", "Accept-Encoding");
|
||||
headers.add("Transfer-Encoding", "chunked");
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets for object *
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param url url
|
||||
* @param responseType response type
|
||||
* @param httpHeaders http headers
|
||||
* @return the for object
|
||||
* @throws Exception exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static <T> T getForObject(String url, Class<T> responseType, HttpHeaders httpHeaders) throws Exception {
|
||||
try (CloseableHttpClient httpClient = acceptsUntrustedCertsHttpClient()) {
|
||||
|
||||
RestTemplate restTemplate = getRestTemplate(httpClient);
|
||||
|
||||
HttpEntity<Object> httpEntity = new HttpEntity<>(null, httpHeaders);
|
||||
|
||||
URI uri = new URI(url);
|
||||
String responseStr = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, String.class).getBody();
|
||||
|
||||
return JsonUtils.parse(responseStr, responseType);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("网络异常或请求错误.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets rest template *
|
||||
*
|
||||
* @param httpClient http client
|
||||
* @return the rest template
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
private static RestTemplate getRestTemplate(CloseableHttpClient httpClient) {
|
||||
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
|
||||
clientHttpRequestFactory.setConnectTimeout(CONNECTION_TIME_OUT);
|
||||
clientHttpRequestFactory.setReadTimeout(READ_TIME_OUT);
|
||||
clientHttpRequestFactory.setConnectionRequestTimeout(CONNECTION_REQUEST_TIME_OUT);
|
||||
clientHttpRequestFactory.setBufferRequestBody(false);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
|
||||
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
|
||||
|
||||
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
|
||||
messageConverters.forEach(m -> {
|
||||
if (m instanceof StringHttpMessageConverter) {
|
||||
((StringHttpMessageConverter) m).setDefaultCharset(Charset.forName(CHARSET));
|
||||
}
|
||||
});
|
||||
restTemplate.setMessageConverters(messageConverters);
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受未信任的请求
|
||||
*
|
||||
* @return closeable http client
|
||||
* @throws KeyStoreException key store exception
|
||||
* @throws NoSuchAlgorithmException no such algorithm exception
|
||||
* @throws KeyManagementException key management exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static CloseableHttpClient acceptsUntrustedCertsHttpClient()
|
||||
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
|
||||
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
|
||||
SSLContext sslContext = HttpsUtils.getSslContext();
|
||||
|
||||
httpClientBuilder.setSSLContext(sslContext);
|
||||
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
|
||||
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||
.register("http", PlainConnectionSocketFactory.getSocketFactory())
|
||||
.register("https", sslSocketFactory)
|
||||
.build();
|
||||
|
||||
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
|
||||
connMgr.setMaxTotal(MAX_CONNECTION_TOTAL);
|
||||
connMgr.setDefaultMaxPerRoute(ROUTE_MAX_COUNT);
|
||||
|
||||
httpClientBuilder.setConnectionManager(connMgr);
|
||||
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(RETRY_COUNT, true));
|
||||
httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
|
||||
|
||||
return httpClientBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets for object with header *
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param url url
|
||||
* @param headers headers
|
||||
* @param responseType response type
|
||||
* @return the for object with header
|
||||
* @throws Exception exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T getForObjectWithHeader(String url, Map<String, String[]> headers, Class<T> responseType) throws Exception {
|
||||
HttpHeaders httpHeaders = getDefaultHeader(MediaType.APPLICATION_JSON);
|
||||
fillHeaders(httpHeaders, headers);
|
||||
return getForObject(url, responseType, httpHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill headers *
|
||||
*
|
||||
* @param httpHeaders http headers
|
||||
* @param headers headers
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static void fillHeaders(HttpHeaders httpHeaders, @NotNull Map<String, String[]> headers) {
|
||||
headers.forEach((key, value1) -> Stream.of(value1).forEach(value -> httpHeaders.add(key, value)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
code.default.null.data=\u6682\u65E0\u6570\u636E
|
||||
code.param.verify.error=\u53C2\u6570\u6821\u9A8C\u5931\u8D25: [{}]
|
||||
code.data.error=\u6570\u636E\u4E0D\u5B58\u5728
|
||||
code.option.failure=\u64CD\u4F5C\u5931\u8D25
|
||||
code.config.error=\u914D\u7F6E\u9519\u8BEF
|
||||
code.server.inner.error=\u670D\u52A1\u5185\u90E8\u9519\u8BEF
|
||||
code.service.invoke.error=\u670D\u52A1\u4E0D\u53EF\u7528
|
||||
code.client.invoke.error=Rest Client \u8C03\u7528\u5931\u8D25
|
||||
code.agent.disable.error=Agent Service \u4E0D\u53EF\u7528
|
||||
code.agent.not.found.error=\u672A\u627E\u5230\u6307\u5B9A\u670D\u52A1
|
||||
code.rpc.invoke.error=\u8FDC\u7A0B\u670D\u52A1\u4E0D\u53EF\u7528
|
||||
code.gateway.instances.error=\u7F51\u5173\u8DEF\u7531\u5931\u8D25, \u672A\u627E\u5230\u6307\u5B9A\u670D\u52A1
|
||||
code.gateway.router.error=\u7F51\u5173\u8DEF\u7531\u914D\u7F6E\u9519\u8BEF: 1.\u8BF7\u68C0\u67E5\u8C03\u7528\u7AEF\u914D\u7F6E fkh.gateway.enable-router \u662F\u5426\u4E3A true; 2.\u68C0\u67E5\u8DEF\u7531\u914D\u7F6E\u662F\u5426\u6B63\u786E.
|
||||
code.server.busy=\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528,\u8BF7\u7A0D\u540E\u91CD\u8BD5!
|
||||
code.server.error=\u7F51\u7EDC\u5F02\u5E38
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package ${cfg.package_dto};
|
||||
|
||||
import com.fkhwl.starter.common.base.BaseDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: $!{table.comment} 数据传输实体 (根据业务需求添加字段) </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @version ${cfg.version}
|
||||
* @email "mailto:${author}@fkhwl.com"
|
||||
* @date ${cfg.date}
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ${entity}DTO extends BaseDTO<Long> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** todo: [自动生成的字段, 避免此实体没有字段导致启动失败的问题, 可删除] */
|
||||
private String autoField;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package ${cfg.package_po};
|
||||
|
||||
#foreach($pkg in ${table.importPackages})
|
||||
import ${pkg};
|
||||
#end
|
||||
#if(${entityLombokModel})
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
#end
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: $!{table.comment} 实体类 </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @version ${cfg.version}
|
||||
* @email "mailto:${author}@fkhwl.com"
|
||||
* @date ${cfg.date}
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
#if(${entityLombokModel})
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
#if(${superEntityClass})
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
#end
|
||||
@Accessors(chain = true)
|
||||
#end
|
||||
#if(${table.convert})
|
||||
@TableName("${table.name}")
|
||||
#end
|
||||
#if(${superEntityClass})
|
||||
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<Long, ${entity}>#end {
|
||||
#elseif(${activeRecord})
|
||||
public class ${entity} extends Model<${entity}> {
|
||||
#else
|
||||
public class ${entity} implements Serializable {
|
||||
#end
|
||||
|
||||
#if(${entityColumnConstant})
|
||||
#foreach($field in ${table.fields})
|
||||
public static final String ${field.name.toUpperCase()} = "${field.name}";
|
||||
#end
|
||||
#end
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
## ---------- BEGIN 字段循环遍历 ----------
|
||||
#foreach($field in ${table.fields})
|
||||
#if(${field.keyFlag})
|
||||
#set($keyPropertyName=${field.propertyName})
|
||||
#end
|
||||
#if("$!field.comment" != "")
|
||||
/** ${field.comment} */
|
||||
#end
|
||||
#if(${field.keyFlag})
|
||||
## 主键
|
||||
#if(${field.keyIdentityFlag})
|
||||
@TableId(value = "${field.name}", type = IdType.AUTO)
|
||||
#elseif(!$null.isNull(${idType}) && "$!idType" != "")
|
||||
@TableId(value = "${field.name}", type = IdType.${idType})
|
||||
#elseif(${field.convert})
|
||||
@TableId("${field.name}")
|
||||
#end
|
||||
## 普通字段
|
||||
#elseif(${field.fill})
|
||||
## ----- 存在字段填充设置 -----
|
||||
#if(${field.convert})
|
||||
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
|
||||
#else
|
||||
@TableField(fill = FieldFill.${field.fill})
|
||||
#end
|
||||
#elseif(${field.convert})
|
||||
@TableField("${field.name}")
|
||||
#end
|
||||
## 乐观锁注解
|
||||
#if(${versionFieldName}==${field.name})
|
||||
@Version
|
||||
#end
|
||||
## 逻辑删除注解
|
||||
#if(${logicDeleteFieldName}==${field.name})
|
||||
@TableLogic
|
||||
#end
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
#end
|
||||
## ---------- END 字段循环遍历 ----------
|
||||
|
||||
#if(!${entityLombokModel})
|
||||
#foreach($field in ${table.fields})
|
||||
#if(${field.propertyType.equals("boolean")})
|
||||
#set($getprefix="is")
|
||||
#else
|
||||
#set($getprefix="get")
|
||||
#end
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
#if(${entityBuilderModel})
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
#else
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
#end
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
#if(${entityBuilderModel})
|
||||
return this;
|
||||
#end
|
||||
}
|
||||
#end
|
||||
#end
|
||||
#if(!${entityLombokModel})
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
#foreach($field in ${table.fields})
|
||||
#if($!{velocityCount}==1)
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
#else
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
#end
|
||||
#end
|
||||
"}";
|
||||
}
|
||||
#end
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package ${cfg.package_form};
|
||||
|
||||
import com.fkhwl.starter.common.base.BaseForm;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: $!{table.comment} 入参实体 (根据业务需求添加字段) </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @version ${cfg.version}
|
||||
* @email "mailto:${author}@fkhwl.com"
|
||||
* @date ${cfg.date}
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ${entity}Form extends BaseForm<Long> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** todo: [自动生成的字段, 避免此实体没有字段导致启动失败的问题, 可删除] */
|
||||
private String autoField;
|
||||
}
|
||||
Reference in New Issue
Block a user