Merge branch 'dev'
This commit is contained in:
commit
332da6f88e
@ -0,0 +1,48 @@
|
||||
package com.aizuda.trans.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 注解 构造器
|
||||
*
|
||||
* @author nn200433
|
||||
* @date 2024-01-29 01:41:01
|
||||
*/
|
||||
public class AnnotationBuilder {
|
||||
|
||||
private final Class<? extends Annotation> annotationType;
|
||||
private final Map<String, Object> values = new HashMap<String, Object>();
|
||||
|
||||
public AnnotationBuilder(Class<? extends Annotation> annotationType) {
|
||||
this.annotationType = annotationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设值
|
||||
*
|
||||
* @param methodName 方法名称
|
||||
* @param value 价值
|
||||
* @author nn200433
|
||||
*/
|
||||
public void setValue(String methodName, Object value) {
|
||||
values.put(methodName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建
|
||||
*
|
||||
* @return {@link Annotation }
|
||||
* @author nn200433
|
||||
*/
|
||||
public Annotation build() {
|
||||
return (Annotation) Proxy.newProxyInstance(
|
||||
annotationType.getClassLoader(),
|
||||
new Class[]{annotationType},
|
||||
new AnnotationProxyBuilder(values)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.aizuda.trans.annotation;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 注解代理生成器
|
||||
*
|
||||
* @author nn200433
|
||||
* @date 2024-01-29 01:41:17
|
||||
*/
|
||||
public class AnnotationProxyBuilder implements InvocationHandler {
|
||||
|
||||
private final Map<String, Object> values;
|
||||
|
||||
public AnnotationProxyBuilder(Map<String, Object> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
String methodName = method.getName();
|
||||
if (values.containsKey(methodName)) {
|
||||
return values.get(methodName);
|
||||
}
|
||||
return method.getDefaultValue();
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,11 @@ package com.aizuda.trans.annotation;
|
||||
|
||||
import com.aizuda.trans.constants.DesensitizedTypeConstants;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 【字典翻译注解】标识在需要翻译的字段上
|
||||
@ -79,6 +83,11 @@ public @interface Translate {
|
||||
*/
|
||||
String desensitizedModel() default DesensitizedTypeConstants.EMPTY;
|
||||
|
||||
/**
|
||||
* 在将json字符串数据转为对象时,将字符串数据置空(默认开启)
|
||||
*/
|
||||
boolean setFieldEmpty() default true;
|
||||
|
||||
/**
|
||||
* 最大长度限制
|
||||
* 适用于以下翻译
|
||||
|
@ -1,9 +1,13 @@
|
||||
package com.aizuda.trans.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 【字典翻译注解】指定在方法上,对方法返回值进行翻译
|
||||
* 【字典翻译注解】指定在方法上或字段上,对方法返回值或者嵌套字段进行翻译
|
||||
*
|
||||
* @author luozhan
|
||||
* @date 2020-04
|
||||
|
@ -0,0 +1,27 @@
|
||||
package com.aizuda.trans.service;
|
||||
|
||||
import com.aizuda.trans.annotation.Translate;
|
||||
import com.aizuda.trans.enums.FormatType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 写入字段名服务
|
||||
*
|
||||
* @author nn200433
|
||||
* @date 2024-01-29 01:50:54
|
||||
*/
|
||||
public interface WriteFieldNameService {
|
||||
|
||||
/**
|
||||
* 获取领域名称列表
|
||||
*
|
||||
* @param translateConfig 翻译配置
|
||||
* @param originFieldName 原点字段名称
|
||||
* @param fieldFormatType 字段格式类型
|
||||
* @return {@link List }<{@link String }>
|
||||
* @author nn200433
|
||||
*/
|
||||
public List<String> getFieldNameList(Translate translateConfig, String originFieldName, FormatType fieldFormatType);
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ public class People3 {
|
||||
|
||||
private String name;
|
||||
|
||||
@Translate(dictClass = JSONConvert.class, translateField = "jsonObj")
|
||||
@Translate(dictClass = JSONConvert.class, translateField = "jsonObj", setFieldEmpty = true)
|
||||
private String json;
|
||||
|
||||
private Object jsonObj;
|
||||
|
@ -4,7 +4,12 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.aizuda.trans.demo.DemoService;
|
||||
import com.aizuda.trans.entity.*;
|
||||
import com.aizuda.trans.entity.Device;
|
||||
import com.aizuda.trans.entity.People;
|
||||
import com.aizuda.trans.entity.People2;
|
||||
import com.aizuda.trans.entity.People3;
|
||||
import com.aizuda.trans.entity.People4;
|
||||
import com.aizuda.trans.entity.Result;
|
||||
import com.aizuda.trans.util.TranslatorUtil;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -2,8 +2,10 @@ package com.aizuda.trans.config;
|
||||
|
||||
import com.aizuda.trans.service.DictTranslateService;
|
||||
import com.aizuda.trans.service.SummaryExtractService;
|
||||
import com.aizuda.trans.service.WriteFieldNameService;
|
||||
import com.aizuda.trans.service.impl.DefaultDictTranslateServiceImpl;
|
||||
import com.aizuda.trans.service.impl.DefaultSummaryExtractServiceImpl;
|
||||
import com.aizuda.trans.service.impl.defaults.DefaultWriteFieldNameServiceImpl;
|
||||
import com.aizuda.trans.service.impl.wrapper.IPageUnWrapper;
|
||||
import com.aizuda.trans.util.TranslatorUtil;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@ -46,6 +48,18 @@ public class TranslatorConfig {
|
||||
return new DefaultSummaryExtractServiceImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册写入字段服务默认实现
|
||||
*
|
||||
* @return {@link WriteFieldNameService }
|
||||
* @author nn200433
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public WriteFieldNameService writeFieldNameService() {
|
||||
return new DefaultWriteFieldNameServiceImpl();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 注册IPage解包器
|
||||
|
@ -6,9 +6,17 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Opt;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.hutool.core.map.WeakConcurrentMap;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.DesensitizedUtil;
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.aizuda.trans.annotation.AnnotationBuilder;
|
||||
import com.aizuda.trans.annotation.Dictionary;
|
||||
import com.aizuda.trans.annotation.Translate;
|
||||
import com.aizuda.trans.annotation.Translator;
|
||||
@ -19,19 +27,29 @@ import com.aizuda.trans.enums.FormatType;
|
||||
import com.aizuda.trans.enums.IEnum;
|
||||
import com.aizuda.trans.json.IJsonConvert;
|
||||
import com.aizuda.trans.service.Translatable;
|
||||
import com.aizuda.trans.service.impl.*;
|
||||
import com.aizuda.trans.service.WriteFieldNameService;
|
||||
import com.aizuda.trans.service.impl.DataBaseTranslator;
|
||||
import com.aizuda.trans.service.impl.DesensitizedTranslator;
|
||||
import com.aizuda.trans.service.impl.DictCacheTranslator;
|
||||
import com.aizuda.trans.service.impl.EnumTranslator;
|
||||
import com.aizuda.trans.service.impl.JsonConvertTranslator;
|
||||
import com.aizuda.trans.service.impl.SummaryExtractTranslator;
|
||||
import com.aizuda.trans.summary.ISummaryExtract;
|
||||
import com.aizuda.trans.util.NameUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import sun.reflect.annotation.AnnotationType;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -49,9 +67,11 @@ import static com.aizuda.trans.util.LambdaUtil.uncheck;
|
||||
public class TranslatorHandle {
|
||||
|
||||
/** 条件字段是否为常量值的前缀 */
|
||||
private static String CONDITION_FIELD_IS_VALUE_PREFIX = "V:";
|
||||
private static String CONDITION_FIELD_IS_VALUE_PREFIX = "V:";
|
||||
/** 循环遍历缓存 */
|
||||
private static Cache<String, List<Field>> LOOP_FIELD_CACHE = CacheUtil.newLFUCache(100);
|
||||
private static Cache<String, List<Field>> LOOP_FIELD_CACHE = CacheUtil.newLFUCache(100);
|
||||
/** 方法缓存 */
|
||||
private static final WeakConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 翻译Map或Entity或Page
|
||||
@ -77,7 +97,11 @@ public class TranslatorHandle {
|
||||
if (ObjUtil.isNull(value)) {
|
||||
continue;
|
||||
}
|
||||
value = CollUtil.getFirst(parse(Collections.singletonList(value)));
|
||||
if (value instanceof Collection) {
|
||||
value = parse((Collection) value);
|
||||
} else {
|
||||
value = CollUtil.getFirst(parse(Collections.singletonList(value)));
|
||||
}
|
||||
}
|
||||
return (T) m;
|
||||
}
|
||||
@ -153,13 +177,14 @@ public class TranslatorHandle {
|
||||
// 2.获取每个待翻译属性的配置
|
||||
final Translate translateConfig = field.getAnnotation(Translate.class);
|
||||
final Class<?> dictClass = getDictClass(translateConfig);
|
||||
final List<String> writeFieldList = NameUtil.parseCamelTo(getTranslateFieldName(translateConfig, fName), fieldFormatType);
|
||||
final List<String> writeFieldList = getWriteFieldNameSrv().getFieldNameList(translateConfig, fName, fieldFormatType);
|
||||
final String groupValue = translateConfig.groupValue();
|
||||
final String conditionField = translateConfig.conditionField();
|
||||
final String desensitizedModel = translateConfig.desensitizedModel();
|
||||
final int maxLen = translateConfig.maxLen();
|
||||
final Dictionary dictionaryConfig = handle(dictClass, translateConfig);
|
||||
final boolean isJsonConvert = IJsonConvert.class.isAssignableFrom(dictClass);
|
||||
final boolean isSetFieldEmpty = translateConfig.setFieldEmpty();
|
||||
|
||||
// 获取未翻译的原值,如果值为空则跳过
|
||||
String originValue = Convert.toStr(getProperty(origin, fieldName));
|
||||
@ -181,7 +206,7 @@ public class TranslatorHandle {
|
||||
}
|
||||
|
||||
// 将翻译结果填入翻译展示字段
|
||||
setProperty(origin, isJsonConvert, fieldName, writeFieldList, translateValList);
|
||||
setProperty(origin, (isJsonConvert && isSetFieldEmpty), fieldName, writeFieldList, translateValList);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,8 +262,8 @@ public class TranslatorHandle {
|
||||
/**
|
||||
* 将注解属性填充到另一个相同类型的注解中,目标注解中已经存在属性值的不会被覆盖
|
||||
*
|
||||
* @param annotationFrom
|
||||
* @param annotationTo
|
||||
* @param annotationFrom 用户自定义的注解值
|
||||
* @param annotationTo 默认的注解值
|
||||
* @return 返回annotationTo,如果annotationTo为空,返回annotationFrom
|
||||
*/
|
||||
private static Annotation joinAnnotationValue(Annotation annotationFrom, Annotation annotationTo) {
|
||||
@ -249,70 +274,51 @@ public class TranslatorHandle {
|
||||
if (annotationFrom == null) {
|
||||
return annotationTo;
|
||||
}
|
||||
|
||||
Object handlerFrom = Proxy.getInvocationHandler(annotationFrom);
|
||||
Object handlerTo = Proxy.getInvocationHandler(annotationTo);
|
||||
Field fieldFrom = uncheck(() -> ReflectUtil.getField(handlerFrom.getClass(), "memberValues"));
|
||||
Field fieldTo = uncheck(() -> ReflectUtil.getField(handlerTo.getClass(), "memberValues"));
|
||||
|
||||
fieldFrom.setAccessible(true);
|
||||
fieldTo.setAccessible(true);
|
||||
|
||||
Map<String, Object> memberValuesFrom = uncheck(() -> (Map) fieldFrom.get(handlerFrom));
|
||||
Map<String, Object> memberValuesTo = uncheck(() -> (Map) fieldTo.get(handlerTo));
|
||||
|
||||
// 注解默认值,注意不会包含没有默认值的属性
|
||||
Map<String, Object> defaultValueMap = AnnotationType.getInstance(annotationTo.annotationType())
|
||||
.memberDefaults();
|
||||
// 若目标注解中全都是默认值(代表没有设置),则直接返回原注解
|
||||
// 否则属性填充后会直接改变目标注解的默认值,影响其他引用的地方
|
||||
if (defaultValueMap.equals(memberValuesTo)) {
|
||||
return annotationFrom;
|
||||
}
|
||||
// 如果目标注解属性未设置,则往目标里填充值
|
||||
memberValuesTo.forEach((field, value) -> {
|
||||
if (value.equals(defaultValueMap.get(field))) {
|
||||
memberValuesTo.put(field, memberValuesFrom.get(field));
|
||||
final Class<? extends Annotation> annotationType = annotationTo.annotationType();
|
||||
Method[] methods = METHODS_CACHE.computeIfAbsent(annotationType, () -> annotationType.getDeclaredMethods());
|
||||
AnnotationBuilder builder = new AnnotationBuilder(annotationType);
|
||||
for (Method method : methods) {
|
||||
try {
|
||||
final String name = method.getName();
|
||||
final Object defaultValue = method.getDefaultValue();
|
||||
final Object valueFrom = method.invoke(annotationFrom);
|
||||
final Object valueTo = method.invoke(annotationTo);
|
||||
Object newV = defaultValue;
|
||||
if (valueTo == null || valueTo.equals(defaultValue) || ArrayUtil.equals(valueTo, defaultValue)) {
|
||||
// 如果目标注解中的值为空或者等于默认值,则使用来源注解的值
|
||||
newV = valueFrom;
|
||||
}
|
||||
builder.setValue(name, newV);
|
||||
} catch (Exception e) {
|
||||
// 处理异常,具体情况可以根据实际需求进行调整
|
||||
log.error("", e);
|
||||
}
|
||||
});
|
||||
|
||||
return annotationTo;
|
||||
}
|
||||
Annotation build = builder.build();
|
||||
return build;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 若注解中未配置translateField,则默认将原属性名的Id或Code字样替换成Name
|
||||
* <p>
|
||||
* 如: resTypeId / resTypeCode -> staffName
|
||||
* 注解成员默认值
|
||||
*
|
||||
* @param translateConfig 转换配置
|
||||
* @param originFieldName 原始字段名称
|
||||
* @return {@link List }<{@link String }>
|
||||
* @param annotationTo 注释转换为
|
||||
* @return {@link Map }<{@link String }, {@link Object }>
|
||||
* @author nn200433
|
||||
*/
|
||||
private static List<String> getTranslateFieldName(Translate translateConfig, String originFieldName) {
|
||||
final Class<?> dictClass = translateConfig.dictClass();
|
||||
final String newName = originFieldName.replaceFirst("(Id|Code)$|$", "Name");
|
||||
String[] translateFieldArray = translateConfig.translateField();
|
||||
final int translateFieldLen = translateFieldArray.length;
|
||||
if (translateFieldLen == 0) {
|
||||
if (IDesensitized.class.isAssignableFrom(dictClass) || ISummaryExtract.class.isAssignableFrom(dictClass)) {
|
||||
// 脱敏与摘要提取功能,没配置翻译字段,直接返回原字段(即替换原始数据)
|
||||
translateFieldArray = new String[]{originFieldName};
|
||||
} else {
|
||||
// 否则返回额外提供的翻译字段
|
||||
translateFieldArray = new String[]{newName};
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < translateFieldLen; i++) {
|
||||
final String translateField = translateFieldArray[i];
|
||||
if (StrUtil.isBlank(translateField)) {
|
||||
translateFieldArray[i] = newName + i;
|
||||
}
|
||||
private static Map<String, Object> annotationMemberDefaults (Annotation annotationTo) {
|
||||
final Class<? extends Annotation> annotationType = annotationTo.annotationType();
|
||||
final Method[] methods = METHODS_CACHE.computeIfAbsent(annotationType, () -> annotationType.getDeclaredMethods());
|
||||
Map<String, Object> defaultValueMap = new HashMap<String, Object>(methods.length);
|
||||
for (Method method : methods) {
|
||||
try {
|
||||
defaultValueMap.put(method.getName(), method.getDefaultValue());
|
||||
} catch (Exception e) {
|
||||
defaultValueMap.put(method.getName(), null);
|
||||
}
|
||||
}
|
||||
return CollUtil.newArrayList(translateFieldArray);
|
||||
return defaultValueMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据对象获取属性
|
||||
*
|
||||
@ -362,6 +368,10 @@ public class TranslatorHandle {
|
||||
} else {
|
||||
// 此处不会抛异常
|
||||
uncheck(() -> getMethod(o.getClass(), writeFieldName, "set").invoke(o, value));
|
||||
if (isRemoveOriginField) {
|
||||
// 字段内容置空
|
||||
uncheck(() -> getMethod(o.getClass(), originFieldName, "set").invoke(o, StrUtil.EMPTY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -485,5 +495,15 @@ public class TranslatorHandle {
|
||||
return resultFieldList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取翻译结果写入字段名称服务
|
||||
*
|
||||
* @return {@link WriteFieldNameService }
|
||||
* @author nn200433
|
||||
*/
|
||||
private static WriteFieldNameService getWriteFieldNameSrv() {
|
||||
return SpringUtil.getBean(WriteFieldNameService.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
package com.aizuda.trans.service.impl.defaults;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.aizuda.trans.annotation.Translate;
|
||||
import com.aizuda.trans.desensitized.IDesensitized;
|
||||
import com.aizuda.trans.enums.FormatType;
|
||||
import com.aizuda.trans.service.WriteFieldNameService;
|
||||
import com.aizuda.trans.summary.ISummaryExtract;
|
||||
import com.aizuda.trans.util.NameUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 默认写入字段名称服务实现
|
||||
*
|
||||
* @author nn200433
|
||||
* @date 2024-01-29 02:04:36
|
||||
*/
|
||||
public class DefaultWriteFieldNameServiceImpl implements WriteFieldNameService {
|
||||
|
||||
@Override
|
||||
public List<String> getFieldNameList(Translate translateConfig, String originFieldName,
|
||||
FormatType fieldFormatType) {
|
||||
return NameUtil.parseCamelTo(getTranslateFieldName(translateConfig, originFieldName), fieldFormatType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 若注解中未配置translateField,则默认将原属性名的Id或Code字样替换成Name
|
||||
* <p>
|
||||
* 如: resTypeId / resTypeCode -> staffName
|
||||
*
|
||||
* @param translateConfig 转换配置
|
||||
* @param originFieldName 原始字段名称
|
||||
* @return {@link List }<{@link String }>
|
||||
* @author nn200433
|
||||
*/
|
||||
private List<String> getTranslateFieldName(Translate translateConfig, String originFieldName) {
|
||||
final Class<?> dictClass = translateConfig.dictClass();
|
||||
final String newName = originFieldName.replaceFirst("(Id|Code)$|$", "Name");
|
||||
String[] translateFieldArray = translateConfig.translateField();
|
||||
final int translateFieldLen = translateFieldArray.length;
|
||||
if (translateFieldLen == 0) {
|
||||
if (IDesensitized.class.isAssignableFrom(dictClass) || ISummaryExtract.class.isAssignableFrom(dictClass)) {
|
||||
// 脱敏与摘要提取功能,没配置翻译字段,直接返回原字段(即替换原始数据)
|
||||
translateFieldArray = new String[]{originFieldName};
|
||||
} else {
|
||||
// 否则返回额外提供的翻译字段
|
||||
translateFieldArray = new String[]{newName};
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < translateFieldLen; i++) {
|
||||
final String translateField = translateFieldArray[i];
|
||||
if (StrUtil.isBlank(translateField)) {
|
||||
translateFieldArray[i] = newName + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return CollUtil.newArrayList(translateFieldArray);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
com.aizuda.trans.config.TranslatorConfig
|
4
pom.xml
4
pom.xml
@ -24,9 +24,9 @@
|
||||
<!-- 版本 -->
|
||||
<revision>0.5</revision>
|
||||
<!-- 数据库操作 -->
|
||||
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
|
||||
<mybatis-plus.version>3.5.4.1</mybatis-plus.version>
|
||||
<!-- hutool -->
|
||||
<hutool.version>5.8.21</hutool.version>
|
||||
<hutool.version>5.8.24</hutool.version>
|
||||
<!-- mysql -->
|
||||
<mysql.version>5.1.49</mysql.version>
|
||||
<!-- maven插件 -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user