[代码完善](dev):
1. 主要增加json字符串翻译 2. 代码格式化 + 文档补充
This commit is contained in:
parent
2fba3b25ed
commit
f2305c3543
19
README.md
19
README.md
@ -41,16 +41,21 @@ EasyTranslate
|
||||
│ │ ├── EnumPool.java
|
||||
│ │ ├── FormatType.java
|
||||
│ │ └── IEnum.java
|
||||
│ ├── handler 主要操作类
|
||||
│ │ └── TranslatorHandle.java
|
||||
│ ├── json json相关
|
||||
│ │ ├── IJsonConvert.java
|
||||
│ │ └── JSONConvert.java
|
||||
│ ├── service
|
||||
│ │ ├── DictTranslateService.java 字典翻译接口
|
||||
│ │ ├── impl
|
||||
│ │ │ ├── DefaultDictTranslateServiceImpl.java 默认数据字典翻译实现(实现字典翻译接口。仿照该方法,实现自己的业务)
|
||||
│ │ │ ├── DictCacheTranslator.java 数据字典翻译实现(调用 字典翻译接口实现)
|
||||
│ │ │ ├── DataBaseTranslator.java 数据库翻译服务
|
||||
│ │ │ ├── DesensitizedTranslator.java 脱敏实现(没啥操作,就返回原值)
|
||||
│ │ │ ├── EnumTranslator.java 枚举翻译实现
|
||||
│ │ │ └── TranslatorHandle.java 翻译操作类
|
||||
│ │ └── Translatable.java 翻译接口(字典、枚举、....接实现该接口)
|
||||
│ │ │ └── JsonConvertTranslator.java json翻译实现
|
||||
│ │ ├── Translatable.java 翻译接口(字典、枚举、....接实现该接口)
|
||||
│ │ └── DictTranslateService.java 字典翻译接口
|
||||
│ ├── TranslatorBootApplication.java
|
||||
│ └── util 一些工具类
|
||||
│ ├── LambdaUtil.java
|
||||
@ -68,7 +73,7 @@ EasyTranslate
|
||||
<dependency>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>dict-trans</artifactId>
|
||||
<version>${latestVersion}</version>
|
||||
<version>0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool工具类 -->
|
||||
@ -309,7 +314,13 @@ private String id;
|
||||
private String zh;
|
||||
|
||||
private String zsxm;
|
||||
|
||||
// =========================== 示例7 json字符串翻译为json对象 ===========================
|
||||
|
||||
@Translate(dictClass = JSONConvert.class, translateField = "jsonObj")
|
||||
private String json;
|
||||
|
||||
private Object jsonObj;
|
||||
```
|
||||
|
||||
#### @Translator
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 122 KiB |
2
pom.xml
2
pom.xml
@ -11,7 +11,7 @@
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>dict-trans</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>0.1</version>
|
||||
<version>0.2</version>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<properties>
|
||||
|
@ -15,46 +15,45 @@ import java.lang.annotation.*;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Dictionary {
|
||||
|
||||
|
||||
/**
|
||||
* 字典表名
|
||||
* <p>
|
||||
* 为空时取 {@link TableName#value()},取不到则取 类名(驼峰转大写下划线)
|
||||
* 为空时取 {@link TableName#value()},取不到则取 类名(驼峰转大写下划线)
|
||||
* </p>
|
||||
*/
|
||||
String table() default "";
|
||||
|
||||
|
||||
/**
|
||||
* 字典编码的属性
|
||||
* <p>
|
||||
* 查询条件的列字段(需要的是表字段)
|
||||
* 查询条件的列字段(需要的是表字段)
|
||||
* </p>
|
||||
*/
|
||||
String codeColumn() default "";
|
||||
|
||||
|
||||
/**
|
||||
* 字典值的列名
|
||||
* <p>
|
||||
* 要查询的字段(需要的是表字段)
|
||||
* 要查询的字段(需要的是表字段)
|
||||
* </p>
|
||||
*/
|
||||
String[] textColumn() default {};
|
||||
|
||||
|
||||
/**
|
||||
* 字典组别属性
|
||||
* (某些字典可能会需要根据某个类别划分,再进行翻译,如静态字典中的DICT_ID)
|
||||
* 字典组别属性 (某些字典可能会需要根据某个类别划分,再进行翻译,如静态字典中的DICT_ID)
|
||||
*/
|
||||
String groupColumn() default "";
|
||||
|
||||
|
||||
/**
|
||||
* 自定义翻译方法
|
||||
* <p>
|
||||
* 1.不配置默认使用DataBaseTranslator翻译
|
||||
* 2.遇到特殊的翻译场景可自定义翻译实现,需要自行编写实现类实现Translatable接口并实现翻译方法,
|
||||
* 程序将使用该方法进行翻译,该注解中的所有配置信息将传递到实现方法中
|
||||
* <ul>
|
||||
* <li>1.不配置默认使用DataBaseTranslator翻译</li>
|
||||
* <li>2.遇到特殊的翻译场景可自定义翻译实现,需要自行编写实现类实现Translatable接口并实现翻译方法,程序将使用该方法进行翻译,该注解中的所有配置信息将传递到实现方法中</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see Translatable
|
||||
*/
|
||||
Class<? extends Translatable> translator() default Translatable.class;
|
||||
|
||||
|
||||
}
|
||||
|
@ -19,9 +19,10 @@ public @interface Translate {
|
||||
* 字典配置类 指定的class上必须有@Dictionary注解或者是IDictEnum接口的实现类 注:一般情况下,本属性必须指定(或者使用别名value属性)
|
||||
*
|
||||
* <ul>
|
||||
* <li>DictTranslate 实现类:字典翻译</li>
|
||||
* <li>IEnum 实现类:枚举翻译</li>
|
||||
* <li>Dict:字典翻译</li>
|
||||
* <li>IDict实现类:枚举翻译</li>
|
||||
* <li>Desensitized: 脱敏翻译</li>
|
||||
* <li>JSONConvert: json字符串翻译</li>
|
||||
* <li>其他: 数据库翻译</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
@ -12,10 +12,10 @@ import java.lang.annotation.*;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Translator {
|
||||
|
||||
|
||||
/**
|
||||
* 指定翻译配置类,可传多个,一般为实体class
|
||||
*/
|
||||
Class<?>[] value() default void.class;
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.aizuda.trans.aspect;
|
||||
|
||||
import com.aizuda.trans.annotation.Translator;
|
||||
import com.aizuda.trans.service.impl.TranslatorHandle;
|
||||
import com.aizuda.trans.handler.TranslatorHandle;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
@ -22,19 +22,19 @@ import org.springframework.stereotype.Component;
|
||||
@Aspect
|
||||
@Component
|
||||
public class TranslateAspect {
|
||||
|
||||
|
||||
@Pointcut("@annotation(com.aizuda.trans.annotation.Translator)")
|
||||
public void pointCut() {
|
||||
}
|
||||
|
||||
|
||||
@AfterReturning(pointcut = "pointCut()", returning = "object")
|
||||
public void doAfter(JoinPoint joinPoint, Object object) {
|
||||
if (null == object) {
|
||||
return;
|
||||
}
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Translator config = signature.getMethod().getAnnotation(Translator.class);
|
||||
Translator config = signature.getMethod().getAnnotation(Translator.class);
|
||||
TranslatorHandle.parse(object, config.value());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -14,11 +14,11 @@ import org.springframework.context.annotation.Configuration;
|
||||
*/
|
||||
@Configuration
|
||||
public class TranslatorConfig {
|
||||
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DictTranslateService dictTranslateService() {
|
||||
return new DefaultDictTranslateServiceImpl();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ package com.aizuda.trans.desensitized;
|
||||
* @date 2022-12-08 008 10:50:37
|
||||
*/
|
||||
public class Desensitized implements IDesensitized {
|
||||
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ package com.aizuda.trans.desensitized;
|
||||
* @date 2022-12-08 008 10:47:22
|
||||
*/
|
||||
public interface IDesensitized {
|
||||
|
||||
}
|
||||
|
@ -10,17 +10,17 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* @create 2020-04
|
||||
*/
|
||||
class EnumPool {
|
||||
|
||||
|
||||
private static final Map<IEnum, EnumBean> DICT_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
static void putDict(IEnum dict, String code, String text) {
|
||||
DICT_MAP.put(dict, new EnumBean(code, text));
|
||||
}
|
||||
|
||||
|
||||
static EnumBean getDict(IEnum dict) {
|
||||
return DICT_MAP.get(dict);
|
||||
}
|
||||
|
||||
|
||||
static class EnumBean implements IEnum {
|
||||
private String code;
|
||||
private String text;
|
||||
@ -29,16 +29,16 @@ class EnumPool {
|
||||
this.code = code;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -52,6 +52,9 @@ public interface IEnum {
|
||||
|
||||
/**
|
||||
* 获取code
|
||||
*
|
||||
* @return {@link String }
|
||||
* @author song_jx
|
||||
*/
|
||||
default String getCode() {
|
||||
return EnumPool.getDict(this).getCode();
|
||||
@ -59,6 +62,9 @@ public interface IEnum {
|
||||
|
||||
/**
|
||||
* 获取text
|
||||
*
|
||||
* @return {@link String }
|
||||
* @author song_jx
|
||||
*/
|
||||
default String getText() {
|
||||
return EnumPool.getDict(this).getText();
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.aizuda.trans.service.impl;
|
||||
package com.aizuda.trans.handler;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
@ -12,8 +12,9 @@ import com.aizuda.trans.desensitized.IDesensitized;
|
||||
import com.aizuda.trans.dict.DictTranslate;
|
||||
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.util.LambdaUtil;
|
||||
import com.aizuda.trans.service.impl.*;
|
||||
import com.aizuda.trans.util.NameUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@ -29,15 +30,17 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.aizuda.trans.util.LambdaUtil.uncheck;
|
||||
|
||||
|
||||
/**
|
||||
* 翻译工具 结合注解使用
|
||||
*
|
||||
* @author luozhan
|
||||
* @see Translate
|
||||
* @see com.aizuda.trans.annotation.Dictionary
|
||||
* @see Dictionary
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TranslatorHandle {
|
||||
|
||||
/**
|
||||
@ -94,81 +97,86 @@ public class TranslatorHandle {
|
||||
return origins;
|
||||
}
|
||||
|
||||
// 源数据中属性的格式(大写下划线,小写下划线,驼峰)
|
||||
final FormatType fieldFormatType = getFieldType(origins);
|
||||
// 获取数据类型
|
||||
classes = (classes.length != 0 && classes[0] != void.class) ? classes : new Class[]{origins.get(0).getClass()};
|
||||
|
||||
// 获取bo中需要翻译的属性
|
||||
List<Field> translateFieldList = Arrays.stream(classes)
|
||||
.map(Class::getDeclaredFields)
|
||||
// 获取类中需要翻译的属性
|
||||
final List<Field> translateFieldList = Stream.of(classes)
|
||||
.map(c -> ReflectUtil.getFields(c))
|
||||
.flatMap(Stream::of)
|
||||
.filter(field -> field.isAnnotationPresent(Translate.class))
|
||||
.collect(Collectors.toList());
|
||||
// 源数据中属性的格式(大写下划线,小写下划线,驼峰)
|
||||
FormatType fieldFormatType = getFieldType(origins);
|
||||
|
||||
for (Field field : translateFieldList) {
|
||||
// 1.获取要翻译的属性名
|
||||
String fieldName = NameUtil.parseCamelTo(field.getName(), fieldFormatType);
|
||||
final String fName = field.getName();
|
||||
final String fieldName = NameUtil.parseCamelTo(fName, fieldFormatType);
|
||||
// 2.获取每个待翻译属性的配置
|
||||
Translate translateConfig = field.getAnnotation(Translate.class);
|
||||
// 配置的字典class
|
||||
Class<?> dictClass = getDictClass(translateConfig);
|
||||
// 获取翻译值写入的字段名
|
||||
List<String> translateFields = NameUtil.parseCamelTo(
|
||||
getTranslateFieldName(translateConfig, field.getName()), fieldFormatType);
|
||||
// 字典组字段值
|
||||
String groupValue = translateConfig.groupValue();
|
||||
// 判断条件字段
|
||||
String conditionField = translateConfig.conditionField();
|
||||
// 获取敏感词模型
|
||||
String desensitizedModel = translateConfig.desensitizedModel();
|
||||
// 字典注解配置
|
||||
com.aizuda.trans.annotation.Dictionary dictionaryConfig = handle(translateConfig);
|
||||
final Translate translateConfig = field.getAnnotation(Translate.class);
|
||||
final Class<?> dictClass = getDictClass(translateConfig);
|
||||
final List<String> writeFieldList = NameUtil.parseCamelTo(getTranslateFieldName(translateConfig, fName),
|
||||
fieldFormatType);
|
||||
final String groupValue = translateConfig.groupValue();
|
||||
final String conditionField = translateConfig.conditionField();
|
||||
final String desensitizedModel = translateConfig.desensitizedModel();
|
||||
final Dictionary dictionaryConfig = handle(dictClass, translateConfig);
|
||||
final boolean isJsonConvert = IJsonConvert.class.isAssignableFrom(dictClass);
|
||||
|
||||
for (T origin : origins) {
|
||||
// 获取未翻译的原值,如果值为空则跳过
|
||||
String originValue = Convert.toStr(getProperty(origin, fieldName));
|
||||
if (originValue == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取条件字段值
|
||||
String conditionFieldValue = null;
|
||||
if (StrUtil.isNotBlank(conditionField)) {
|
||||
conditionFieldValue = Convert.toStr(getProperty(origin, conditionField));
|
||||
}
|
||||
|
||||
// 翻译
|
||||
List<String> translateValues = parse(originValue, dictionaryConfig, dictClass, groupValue, conditionFieldValue);
|
||||
|
||||
// 如果敏感词模型不为空,则将结果进行敏感词处理
|
||||
if (StrUtil.isNotBlank(desensitizedModel)) {
|
||||
final DesensitizedUtil.DesensitizedType desensitizedType = EnumUtil.fromString(
|
||||
DesensitizedUtil.DesensitizedType.class, desensitizedModel, null);
|
||||
if (null == desensitizedType && StrUtil.isWrap(desensitizedModel, StrUtil.DELIM_START, StrUtil.DELIM_END)) {
|
||||
// 找不到匹配脱敏模型时,用hide解析
|
||||
final String model = StrUtil.unWrap(desensitizedModel, StrUtil.DELIM_START, StrUtil.DELIM_END);
|
||||
final int[] indexArray = StrUtil.splitToInt(model, StrUtil.COMMA);
|
||||
Assert.isTrue(indexArray.length == 2, "自定义敏感词模型格式:{含开始位置,含结束位置}。举例:{1,2}");
|
||||
translateValues = translateValues.stream()
|
||||
.map(s -> StrUtil.hide(s, indexArray[0], indexArray[1]))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
translateValues = translateValues.stream()
|
||||
.map(s -> StrUtil.desensitized(s, desensitizedType))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
// 获取翻译结果并脱敏处理
|
||||
List<Object> translateValueList = parse(originValue, dictionaryConfig, dictClass, groupValue, conditionFieldValue);
|
||||
if (!isJsonConvert) {
|
||||
// 不是 JsonConvert.class 时可进行脱敏
|
||||
translateValueList = desensitizedHandle(desensitizedModel, translateValueList);
|
||||
}
|
||||
|
||||
// 填值
|
||||
setProperty(origin, translateFields, translateValues);
|
||||
// 将翻译结果填入翻译展示字段
|
||||
setProperty(origin, isJsonConvert, fieldName, writeFieldList, translateValueList);
|
||||
}
|
||||
}
|
||||
return origins;
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译单值
|
||||
*
|
||||
* @param originValue 原始值
|
||||
* @param dictionaryConfig 字典配置
|
||||
* @param dictClass 字典class(包含组别属性、字典code属性、字典值属性三个信息)
|
||||
* @param groupValue 组别的值,由使用者指定
|
||||
* @param conditionValue 条件字段值
|
||||
* @return {@link List }<{@link Object }>
|
||||
* @author song_jx
|
||||
*/
|
||||
public static List<Object> parse(String originValue, Dictionary dictionaryConfig, Class<?> dictClass, String groupValue,
|
||||
String conditionValue) {
|
||||
if (originValue == null) {
|
||||
return null;
|
||||
}
|
||||
final Translatable translator = getTranslatable(dictClass, dictionaryConfig.translator());
|
||||
return CollUtil.defaultIfEmpty(translator.translate(groupValue, conditionValue, originValue, dictionaryConfig, dictClass),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断源数据中的属性格式类型
|
||||
*
|
||||
* @param origins 对象数组
|
||||
* @return {@link FormatType }
|
||||
* @author nn200433
|
||||
* @author song_jx
|
||||
*/
|
||||
private static <T> FormatType getFieldType(List<T> origins) {
|
||||
T element = origins.get(0);
|
||||
@ -191,7 +199,7 @@ public class TranslatorHandle {
|
||||
*
|
||||
* @param translateConfig 转换配置
|
||||
* @return {@link Class }<{@link ? }>
|
||||
* @author nn200433
|
||||
* @author song_jx
|
||||
*/
|
||||
private static Class<?> getDictClass(Translate translateConfig) {
|
||||
final Class<?> classType = translateConfig.dictClass();
|
||||
@ -201,15 +209,16 @@ public class TranslatorHandle {
|
||||
/**
|
||||
* 将dictClass类上的Dictionary的配置填充到Translate注解中的dictionary属性中 此步骤将合并两个注解中的配置,且Translate注解中的配置优先级更高
|
||||
*
|
||||
* @param dictClass 字典配置类
|
||||
* @param translateConfig 转换配置
|
||||
* @return {@link com.aizuda.trans.annotation.Dictionary }
|
||||
* @author nn200433
|
||||
* @return {@link Dictionary }
|
||||
* @author song_jx
|
||||
*/
|
||||
private static com.aizuda.trans.annotation.Dictionary handle(Translate translateConfig) {
|
||||
Class<?> dictClass = getDictClass(translateConfig);
|
||||
com.aizuda.trans.annotation.Dictionary dictionaryConfigOnDictClass = dictClass.getAnnotation(com.aizuda.trans.annotation.Dictionary.class);
|
||||
com.aizuda.trans.annotation.Dictionary dictionaryConfigInTranslateConfig = translateConfig.dictionary();
|
||||
return (com.aizuda.trans.annotation.Dictionary) joinAnnotationValue(dictionaryConfigOnDictClass, dictionaryConfigInTranslateConfig);
|
||||
private static Dictionary handle(Class<?> dictClass, Translate translateConfig) {
|
||||
// Class<?> dictClass = getDictClass(translateConfig);
|
||||
Dictionary dictionaryConfigOnDictClass = dictClass.getAnnotation(Dictionary.class);
|
||||
Dictionary dictionaryConfigInTranslateConfig = translateConfig.dictionary();
|
||||
return (Dictionary) joinAnnotationValue(dictionaryConfigOnDictClass, dictionaryConfigInTranslateConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,22 +230,23 @@ public class TranslatorHandle {
|
||||
*/
|
||||
private static Annotation joinAnnotationValue(Annotation annotationFrom, Annotation annotationTo) {
|
||||
if (annotationTo == null) {
|
||||
// 这条似乎永远不成立(不知道原作者为何这样写,先留着吧)... dictionary 属性有默认值
|
||||
return annotationFrom;
|
||||
}
|
||||
if (annotationFrom == null) {
|
||||
return annotationTo;
|
||||
}
|
||||
|
||||
Object handlerFrom = Proxy.getInvocationHandler(annotationFrom);
|
||||
Object handlerTo = Proxy.getInvocationHandler(annotationTo);
|
||||
|
||||
Field fieldFrom = LambdaUtil.uncheck(() -> handlerFrom.getClass().getDeclaredField("memberValues"));
|
||||
Field fieldTo = LambdaUtil.uncheck(() -> handlerTo.getClass().getDeclaredField("memberValues"));
|
||||
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 = LambdaUtil.uncheck(() -> (Map) fieldFrom.get(handlerFrom));
|
||||
Map<String, Object> memberValuesTo = LambdaUtil.uncheck(() -> (Map) fieldTo.get(handlerTo));
|
||||
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())
|
||||
@ -256,69 +266,28 @@ public class TranslatorHandle {
|
||||
return annotationTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译单值
|
||||
*
|
||||
* @param originValue 原始值
|
||||
* @param dictConfig 字典配置
|
||||
* @param dictClass 字典class(包含组别属性、字典code属性、字典值属性三个信息)
|
||||
* @param groupValue 组别的值,由使用者指定
|
||||
* @param conditionValue 条件字段值
|
||||
* @return 翻译后的值,如果字典中找不到翻译值返回原始值
|
||||
* @author nn200433
|
||||
*/
|
||||
public static List<String> parse(String originValue, Dictionary dictConfig, Class<?> dictClass, String groupValue,
|
||||
String conditionValue) {
|
||||
if (originValue == null) {
|
||||
return null;
|
||||
}
|
||||
Class<? extends Translatable> translatorClass = dictConfig.translator();
|
||||
if (translatorClass == Translatable.class) {
|
||||
if (DictTranslate.class.isAssignableFrom(dictClass)) {
|
||||
// 1.dictClass是字典类,采用字典翻译
|
||||
translatorClass = DictCacheTranslator.class;
|
||||
} else if (IEnum.class.isAssignableFrom(dictClass)) {
|
||||
// 2.dictClass是枚举类,采用枚举翻译
|
||||
translatorClass = EnumTranslator.class;
|
||||
} else if (IDesensitized.class.isAssignableFrom(dictClass)) {
|
||||
// 3.dictClass是脱敏类,采用脱敏翻译
|
||||
translatorClass = DesensitizedTranslator.class;
|
||||
} else {
|
||||
// 4.否则使用数据库翻译
|
||||
translatorClass = DataBaseTranslator.class;
|
||||
}
|
||||
}
|
||||
|
||||
// 调用翻译方法
|
||||
Translatable translator;
|
||||
if (translatorClass.isAnnotationPresent(Component.class)) {
|
||||
// 实现类上配置了@Component则使用Spring容器获取
|
||||
translator = SpringUtil.getBean(translatorClass);
|
||||
} else {
|
||||
translator = LambdaUtil.uncheck(translatorClass::newInstance);
|
||||
}
|
||||
List<String> translateResult = translator.translate(groupValue, conditionValue, originValue, dictConfig,
|
||||
dictClass);
|
||||
return CollUtil.defaultIfEmpty(translateResult, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 若注解中未配置translateField,则默认将原属性名的Id或Code字样替换成Name
|
||||
* <p>
|
||||
* 如: resTypeId -> resTypeCode staff -> staffName
|
||||
* 如: resTypeId / resTypeCode -> staffName
|
||||
*
|
||||
* @param translateConfig 转换配置
|
||||
* @param originFieldName 原始字段名称
|
||||
* @return {@link List }<{@link String }>
|
||||
* @author nn200433
|
||||
* @author song_jx
|
||||
*/
|
||||
private static List<String> getTranslateFieldName(Translate translateConfig, String originFieldName) {
|
||||
String[] translateFieldArray = translateConfig.translateField();
|
||||
String newName = originFieldName.replaceFirst("(Id|Code)$|$", "Name");
|
||||
for (int i = 0; i < translateFieldArray.length; i++) {
|
||||
final String translateField = translateFieldArray[i];
|
||||
if (StrUtil.isBlank(translateField)) {
|
||||
translateFieldArray[i] = newName + i;
|
||||
String[] translateFieldArray = translateConfig.translateField();
|
||||
final int translateFieldLen = translateFieldArray.length;
|
||||
final String newName = originFieldName.replaceFirst("(Id|Code)$|$", "Name");
|
||||
if (translateFieldLen == 0) {
|
||||
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);
|
||||
@ -330,44 +299,49 @@ public class TranslatorHandle {
|
||||
* @param o 对象
|
||||
* @param fieldName 字段名称
|
||||
* @return {@link Object }
|
||||
* @author nn200433
|
||||
* @author song_jx
|
||||
*/
|
||||
private static Object getProperty(Object o, String fieldName) {
|
||||
if (o instanceof Map) {
|
||||
return ((Map) o).get(fieldName);
|
||||
} else {
|
||||
Method getMethod = getMethod(o.getClass(), fieldName, "get");
|
||||
// 此处不会抛异常
|
||||
return LambdaUtil.uncheck(() -> getMethod.invoke(o));
|
||||
return uncheck(() -> getMethod(o.getClass(), fieldName, "get").invoke(o));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置属性
|
||||
*
|
||||
* @param o 对象
|
||||
* @param fieldNameList 字段名称列表
|
||||
* @param valueList 值列表
|
||||
* @author nn200433
|
||||
* @param o 对象
|
||||
* @param isRemoveOriginField 是否删除未翻译的字段
|
||||
* @param originFieldName 未翻译的字段名
|
||||
* @param writeFieldList 待写入翻译的字段名称列表
|
||||
* @param valueList 待写入翻译的值的列表
|
||||
* @author song_jx
|
||||
*/
|
||||
private static void setProperty(Object o, List<String> fieldNameList, List<String> valueList) {
|
||||
if (fieldNameList.size() > valueList.size()) {
|
||||
private static void setProperty(Object o, boolean isRemoveOriginField, String originFieldName, List<String> writeFieldList,
|
||||
List<Object> valueList) {
|
||||
if (writeFieldList.size() > valueList.size()) {
|
||||
log.error(
|
||||
"字典翻译查询结果不够翻译,导致翻译异常。\n ---> 当前翻译数据:{} \n ---> 翻译结果需设置 {} 个字段({})\n ---> 实际翻译出 {} 个字段({})",
|
||||
JSONUtil.toJsonStr(o), fieldNameList.size(), fieldNameList, valueList.size(), valueList);
|
||||
JSONUtil.toJsonStr(o), writeFieldList.size(), writeFieldList, valueList.size(), valueList);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < fieldNameList.size(); i++) {
|
||||
final String fieldName = fieldNameList.get(i);
|
||||
final String value = valueList.get(i);
|
||||
|
||||
// 往属性写入数据
|
||||
for (int i = 0; i < writeFieldList.size(); i++) {
|
||||
final String writeFieldName = writeFieldList.get(i);
|
||||
final Object value = valueList.get(i);
|
||||
if (o instanceof Map) {
|
||||
((Map) o).put(fieldName, value);
|
||||
Map rMap = (Map) o;
|
||||
rMap.put(writeFieldName, value);
|
||||
if (isRemoveOriginField) {
|
||||
// 删除字段(这辈子都不会触发到的样子...但是下方的对象又没法操作...)
|
||||
rMap.remove(originFieldName);
|
||||
}
|
||||
} else {
|
||||
Method setMethod = getMethod(o.getClass(), fieldName, "set");
|
||||
// 此处不会抛异常
|
||||
LambdaUtil.uncheck(() -> setMethod.invoke(o, value));
|
||||
uncheck(() -> getMethod(o.getClass(), writeFieldName, "set").invoke(o, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,16 +353,83 @@ public class TranslatorHandle {
|
||||
* @param fieldName 字段名称
|
||||
* @param prefix 前缀
|
||||
* @return {@link Method }
|
||||
* @author nn200433
|
||||
* @author song_jx
|
||||
*/
|
||||
private static Method getMethod(Class<?> clazz, String fieldName, String prefix) {
|
||||
String methodName = prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
||||
return Stream.of(clazz.getDeclaredMethods())
|
||||
.filter(method -> method.getName().equals(methodName))
|
||||
.findAny()
|
||||
final String methodName = prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
||||
return Stream.of(ReflectUtil.getMethods(clazz, m -> m.getName().equals(methodName))).findAny()
|
||||
.orElseThrow(() -> new IllegalArgumentException(
|
||||
clazz.getSimpleName() + ".class中未添加翻译属性" + fieldName + "或其对应get/set方法"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 脱敏处理
|
||||
*
|
||||
* @param desensitizedModel 脱敏模型
|
||||
* @param translateValueList 翻译值
|
||||
* @return {@link List }<{@link Object }>
|
||||
* @author song_jx
|
||||
*/
|
||||
private static List<Object> desensitizedHandle(String desensitizedModel, List<Object> translateValueList) {
|
||||
// 如果敏感词模型为空,则将返回默认翻译值
|
||||
List<Object> newValueList = translateValueList;
|
||||
if (StrUtil.isBlank(desensitizedModel)) {
|
||||
return newValueList;
|
||||
}
|
||||
|
||||
// 否则进行脱敏操作
|
||||
final DesensitizedUtil.DesensitizedType desensitizedType = EnumUtil.fromString(
|
||||
DesensitizedUtil.DesensitizedType.class, desensitizedModel, null);
|
||||
if (null == desensitizedType && StrUtil.isWrap(desensitizedModel, StrUtil.DELIM_START, StrUtil.DELIM_END)) {
|
||||
// 找不到匹配脱敏模型时,用hide解析
|
||||
final String model = StrUtil.unWrap(desensitizedModel, StrUtil.DELIM_START, StrUtil.DELIM_END);
|
||||
final int[] indexArray = StrUtil.splitToInt(model, StrUtil.COMMA);
|
||||
Assert.isTrue(indexArray.length == 2, "自定义敏感词模型格式:{含开始位置,含结束位置}。举例:{1,2}");
|
||||
newValueList = translateValueList.stream()
|
||||
.map(s -> StrUtil.hide(Convert.toStr(s), indexArray[0], indexArray[1]))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
newValueList = translateValueList.stream()
|
||||
.map(s -> StrUtil.desensitized(Convert.toStr(s), desensitizedType))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return newValueList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取翻译实现
|
||||
*
|
||||
* @param dictClass 字典class
|
||||
* @param translatorClass 实际翻译类
|
||||
* @return {@link Translatable }
|
||||
* @author song_jx
|
||||
*/
|
||||
private static Translatable getTranslatable(Class<?> dictClass, Class<? extends Translatable> translatorClass) {
|
||||
// 没这样写(dictionary = @Dictionary(translator = UserInfoTranslatorImpl.class))一律认为是默认的 Translatable
|
||||
// 因为注解定义了 Dictionary dictionary() default @Dictionary;
|
||||
if (translatorClass == Translatable.class) {
|
||||
if (DictTranslate.class.isAssignableFrom(dictClass)) {
|
||||
// 1.dictClass是字典类,采用字典翻译
|
||||
translatorClass = DictCacheTranslator.class;
|
||||
} else if (IEnum.class.isAssignableFrom(dictClass)) {
|
||||
// 2.dictClass是枚举类,采用枚举翻译
|
||||
translatorClass = EnumTranslator.class;
|
||||
} else if (IDesensitized.class.isAssignableFrom(dictClass)) {
|
||||
// 3.dictClass是脱敏类,采用脱敏翻译
|
||||
translatorClass = DesensitizedTranslator.class;
|
||||
} else if (IJsonConvert.class.isAssignableFrom(dictClass)) {
|
||||
// 4.dictClass是JSON类,采用JSON翻译
|
||||
translatorClass = JsonConvertTranslator.class;
|
||||
} else {
|
||||
// 5.否则使用数据库翻译
|
||||
translatorClass = DataBaseTranslator.class;
|
||||
}
|
||||
}
|
||||
|
||||
// Translatable 实现类上配置了 @Component 则使用 Spring 容器获取 否者 new 一个实现类
|
||||
return translatorClass.isAnnotationPresent(Component.class) ? SpringUtil.getBean(translatorClass) : uncheck(translatorClass::newInstance);
|
||||
}
|
||||
|
||||
}
|
||||
|
11
src/main/java/com/aizuda/trans/json/IJsonConvert.java
Normal file
11
src/main/java/com/aizuda/trans/json/IJsonConvert.java
Normal file
@ -0,0 +1,11 @@
|
||||
package com.aizuda.trans.json;
|
||||
|
||||
/**
|
||||
* JSON接口
|
||||
*
|
||||
* @author song_jx
|
||||
* @date 2022-12-08 008 10:47:22
|
||||
*/
|
||||
public interface IJsonConvert {
|
||||
|
||||
}
|
11
src/main/java/com/aizuda/trans/json/JSONConvert.java
Normal file
11
src/main/java/com/aizuda/trans/json/JSONConvert.java
Normal file
@ -0,0 +1,11 @@
|
||||
package com.aizuda.trans.json;
|
||||
|
||||
/**
|
||||
* JSON 转换
|
||||
*
|
||||
* @author song_jx
|
||||
* @date 2022-12-08 008 10:50:37
|
||||
*/
|
||||
public class JSONConvert implements IJsonConvert {
|
||||
|
||||
}
|
@ -7,15 +7,15 @@ package com.aizuda.trans.service;
|
||||
* @date 2022-08-18 018 16:31:43
|
||||
*/
|
||||
public interface DictTranslateService {
|
||||
|
||||
|
||||
/**
|
||||
* 获取字典标签
|
||||
*
|
||||
* @param dictCode 分组
|
||||
* @param dictCode 分组
|
||||
* @param dictValue 值
|
||||
* @return {@link String }
|
||||
* @author nn200433
|
||||
*/
|
||||
public String findDictLabel(String dictCode, String dictValue);
|
||||
|
||||
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import java.util.List;
|
||||
* @create 2020-04
|
||||
*/
|
||||
public interface Translatable {
|
||||
|
||||
|
||||
/**
|
||||
* 自定义翻译方法,需要自己实现
|
||||
*
|
||||
@ -22,8 +22,10 @@ public interface Translatable {
|
||||
* @param origin 待翻译的原始值(对应字典code属性)
|
||||
* @param dictConfig 字典注解,可获取属性配置
|
||||
* @param dictClass 字典class
|
||||
* @return 字典value,可以返回null值,翻译时会处理(如果为null则显示原始值)
|
||||
* @return {@link List }<{@link Object }> 字典value,可以返回null值,翻译时会处理(如果为null则显示原始值)
|
||||
* @author nn200433
|
||||
*/
|
||||
public List<String> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig, Class dictClass);
|
||||
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass);
|
||||
|
||||
}
|
||||
|
@ -42,31 +42,35 @@ public class DataBaseTranslator implements Translatable {
|
||||
private static DataSource dataSource = SpringUtil.getBean(DataSource.class);
|
||||
|
||||
@Override
|
||||
public List<String> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig, Class dictClass) {
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass) {
|
||||
// 获取参数
|
||||
String codeColumn = dictConfig.codeColumn();
|
||||
String codeColumn = dictConfig.codeColumn();
|
||||
String[] textColumnArray = dictConfig.textColumn();
|
||||
String groupColumn = dictConfig.groupColumn();
|
||||
String tableName = getTableName(dictConfig, dictClass);
|
||||
|
||||
Assert.isTrue(StrUtil.isNotEmpty(codeColumn), "@Dictionary注解codeColumn配置有误,找不到指定的属性名,class:" + dictClass.getSimpleName());
|
||||
Assert.isTrue(ArrayUtil.isNotEmpty(textColumnArray), "@Dictionary注解textColumn配置有误,找不到指定的属性名,class:" + dictClass.getSimpleName());
|
||||
|
||||
List<String> rsList = new ArrayList<String>(textColumnArray.length);
|
||||
String groupColumn = dictConfig.groupColumn();
|
||||
String tableName = getTableName(dictConfig, dictClass);
|
||||
|
||||
Assert.isTrue(StrUtil.isNotEmpty(codeColumn),
|
||||
"@Dictionary注解codeColumn配置有误,找不到指定的属性名,class:" + dictClass.getSimpleName());
|
||||
Assert.isTrue(ArrayUtil.isNotEmpty(textColumnArray),
|
||||
"@Dictionary注解textColumn配置有误,找不到指定的属性名,class:" + dictClass.getSimpleName());
|
||||
|
||||
List<Object> rsList = new ArrayList<Object>(textColumnArray.length);
|
||||
try {
|
||||
log.debug("---> 触发字典翻译:查询表 {} 中的字段 {} ,查询条件 {} = {}", tableName, textColumnArray, codeColumn, origin);
|
||||
|
||||
log.debug("---> 触发字典翻译:查询表 {} 中的字段 {} ,查询条件 {} = {}", tableName, textColumnArray, codeColumn,
|
||||
origin);
|
||||
|
||||
// 查询条件为空时直接返回相对应个数的空数组
|
||||
if (ObjectUtil.isNull(origin) || StrUtil.isBlank(origin)) {
|
||||
log.debug("---> 触发字典翻译:查询条件为空,直接返回对应个数的空数组");
|
||||
return Opt.ofNullable(textColumnArray).stream().map(s -> StrUtil.EMPTY).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
Entity where = Entity.create(tableName);
|
||||
if (StrUtil.isNotEmpty(groupColumn)) {
|
||||
where.set(groupColumn, groupValue);
|
||||
}
|
||||
|
||||
|
||||
if (StrUtil.contains(origin, StrUtil.COMMA)) {
|
||||
// 多条记录取单列(查询结果为多条记录,循环后转为单条)
|
||||
// 传入数据:1,2,3
|
||||
@ -93,7 +97,7 @@ public class DataBaseTranslator implements Translatable {
|
||||
} catch (SQLException e) {
|
||||
log.error("---> DataBaseTranslator 字典翻译,SQL查询异常", e);
|
||||
}
|
||||
|
||||
|
||||
return rsList;
|
||||
}
|
||||
|
||||
@ -109,18 +113,19 @@ public class DataBaseTranslator implements Translatable {
|
||||
if (StrUtil.isNotEmpty(dictConfig.table())) {
|
||||
return dictConfig.table();
|
||||
}
|
||||
|
||||
|
||||
// 类名转表名
|
||||
final String className = dictClass.getSimpleName();
|
||||
String tName = className.substring(0, 1) + NameUtil.parseCamelTo(className.substring(1), FormatType.UPPERCASE_UNDERLINE);
|
||||
|
||||
String tName = className.substring(0, 1) + NameUtil.parseCamelTo(className.substring(1),
|
||||
FormatType.UPPERCASE_UNDERLINE);
|
||||
|
||||
// 获取mp注解上的表名
|
||||
TableName tableName = (TableName) dictClass.getAnnotation(TableName.class);
|
||||
if (null != tableName) {
|
||||
tName = tableName.value();
|
||||
}
|
||||
|
||||
|
||||
return tName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import com.aizuda.trans.service.DictTranslateService;
|
||||
* @date 2022-08-18 018 16:32:24
|
||||
*/
|
||||
public class DefaultDictTranslateServiceImpl implements DictTranslateService {
|
||||
|
||||
|
||||
@Override
|
||||
public String findDictLabel(String dictCode, String dictValue) {
|
||||
return dictValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -17,11 +17,12 @@ import java.util.List;
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DesensitizedTranslator implements Translatable {
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig, Class dictClass) {
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass) {
|
||||
// 直接返回原值
|
||||
return Collections.singletonList(origin);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -19,14 +19,15 @@ import java.util.List;
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DictCacheTranslator implements Translatable {
|
||||
|
||||
|
||||
@Autowired
|
||||
private DictTranslateService dictTranslateService;
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig, Class dictClass) {
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass) {
|
||||
return Collections.singletonList(dictTranslateService.findDictLabel(groupValue, origin));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,16 +18,18 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
@Component
|
||||
public class EnumTranslator implements Translatable {
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig, Class dictClass) {
|
||||
Assert.isTrue(IEnum.class.isAssignableFrom(dictClass), dictClass.getSimpleName() + "不是IDictEnum的实现类,无法使用EnumTranslator进行翻译");
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass) {
|
||||
Assert.isTrue(IEnum.class.isAssignableFrom(dictClass),
|
||||
dictClass.getSimpleName() + "不是IDictEnum的实现类,无法使用EnumTranslator进行翻译");
|
||||
final String s = Stream.of(((Class<IEnum>) dictClass).getEnumConstants())
|
||||
.filter((IEnum e) -> e.getCode().equals(origin))
|
||||
.map(IEnum::getText)
|
||||
.findAny().orElse(null);
|
||||
return Collections.singletonList(s);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
package com.aizuda.trans.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.aizuda.trans.annotation.Dictionary;
|
||||
import com.aizuda.trans.service.Translatable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* JSON 翻译
|
||||
*
|
||||
* @author luozhan
|
||||
* @create 2020-04
|
||||
*/
|
||||
@Component
|
||||
public class JsonConvertTranslator implements Translatable {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass) {
|
||||
Assert.isTrue(JSONUtil.isTypeJSON(origin), "该数据不是 JSON 字符串,JSON 字符串应为 “{}” 或 “[]” 包裹的数据。");
|
||||
Object rObj = null;
|
||||
if (JSONUtil.isTypeJSONObject(origin)) {
|
||||
rObj = JSONUtil.toBean(origin, JSONObject.class);
|
||||
} else {
|
||||
rObj = JSONUtil.toList(origin, JSONObject.class);
|
||||
}
|
||||
return Collections.singletonList(rObj);
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ import java.util.function.*;
|
||||
* @link <a>https://github.com/Robot-L/LambdaExceptionUtil</a>觉得不错的话请给个Star,thx! :D
|
||||
*/
|
||||
public final class LambdaUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 包装普通函数(Function)
|
||||
* <p>
|
||||
@ -18,7 +18,8 @@ public final class LambdaUtil {
|
||||
* 1.外层代码中编译器将无法提示有异常需要处理
|
||||
* 2.也无法主动在外层捕获具体的异常,如果尝试try一个具体的异常,编译器将提示:在try语句体中永远不会抛出相应异常(Exception 'XXX' is never thrown in the corresponding try block)
|
||||
*/
|
||||
public static <T, R, E extends Exception> Function<T, R> wrapFunction(FunctionWithExceptions<T, R, E> function) throws E {
|
||||
public static <T, R, E extends Exception> Function<T, R> wrapFunction(FunctionWithExceptions<T, R, E> function)
|
||||
throws E {
|
||||
return t -> {
|
||||
try {
|
||||
return function.apply(t);
|
||||
@ -28,11 +29,13 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装双入参普通函数(BiFunction)
|
||||
*/
|
||||
public static <T, U, R, E extends Exception> BiFunction<T, U, R> wrapBiFunction(BiFunctionWithExceptions<T, U, R, E> biFunction) throws E {
|
||||
public static <T, U, R, E extends Exception> BiFunction<T, U, R> wrapBiFunction(
|
||||
BiFunctionWithExceptions<T, U, R, E> biFunction)
|
||||
throws E {
|
||||
return (t, u) -> {
|
||||
try {
|
||||
return biFunction.apply(t, u);
|
||||
@ -42,11 +45,12 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装消费函数(Consumer)
|
||||
*/
|
||||
public static <T, E extends Exception> Consumer<T> wrapConsumer(ConsumerWithExceptions<T, E> consumer) throws E {
|
||||
public static <T, E extends Exception> Consumer<T> wrapConsumer(ConsumerWithExceptions<T, E> consumer)
|
||||
throws E {
|
||||
return t -> {
|
||||
try {
|
||||
consumer.accept(t);
|
||||
@ -55,11 +59,12 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装双重消费函数(BiConsumer)
|
||||
*/
|
||||
public static <T, U, E extends Exception> BiConsumer<T, U> wrapBiConsumer(BiConsumerWithExceptions<T, U, E> biConsumer) throws E {
|
||||
public static <T, U, E extends Exception> BiConsumer<T, U> wrapBiConsumer(BiConsumerWithExceptions<T, U, E> biConsumer)
|
||||
throws E {
|
||||
return (t, u) -> {
|
||||
try {
|
||||
biConsumer.accept(t, u);
|
||||
@ -68,11 +73,12 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装生产函数(Supplier)
|
||||
*/
|
||||
public static <T, E extends Exception> Supplier<T> wrapSupplier(SupplierWithExceptions<T, E> function) throws E {
|
||||
public static <T, E extends Exception> Supplier<T> wrapSupplier(SupplierWithExceptions<T, E> function)
|
||||
throws E {
|
||||
return () -> {
|
||||
try {
|
||||
return function.get();
|
||||
@ -82,11 +88,12 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装条件函数(Predicate)
|
||||
*/
|
||||
public static <T, E extends Exception> Predicate<T> wrapPredicate(PredicateWithExceptions<T, E> predicate) throws E {
|
||||
public static <T, E extends Exception> Predicate<T> wrapPredicate(PredicateWithExceptions<T, E> predicate)
|
||||
throws E {
|
||||
return t -> {
|
||||
try {
|
||||
return predicate.test(t);
|
||||
@ -96,11 +103,12 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装双入参条件函数(BiPredicate)
|
||||
*/
|
||||
public static <T, U, E extends Exception> BiPredicate<T, U> wrapBiPredicate(BiPredicateWithExceptions<T, U, E> predicate) throws E {
|
||||
public static <T, U, E extends Exception> BiPredicate<T, U> wrapBiPredicate(BiPredicateWithExceptions<T, U, E> predicate)
|
||||
throws E {
|
||||
return (t, u) -> {
|
||||
try {
|
||||
return predicate.test(t, u);
|
||||
@ -110,18 +118,19 @@ public final class LambdaUtil {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 包装纯执行函数(Runnable)
|
||||
*/
|
||||
public static <E extends Exception> void wrapRunnable(RunnableWithExceptions<E> runnable) throws E {
|
||||
public static <E extends Exception> void wrapRunnable(RunnableWithExceptions<E> runnable)
|
||||
throws E {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception exception) {
|
||||
throwAsUnchecked(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 如果一个方法绝对不会抛出所申明的异常,可以使用该方法进行包装
|
||||
* 如:new String(byteArr, "UTF-8")申明了UnsupportedEncodingException,
|
||||
@ -136,55 +145,64 @@ public final class LambdaUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
|
||||
public static <E extends Throwable> void throwAsUnchecked(Exception exception)
|
||||
throws E {
|
||||
throw (E) exception;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ConsumerWithExceptions<T, E extends Exception> {
|
||||
void accept(T t) throws E;
|
||||
void accept(T t)
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiConsumerWithExceptions<T, U, E extends Exception> {
|
||||
void accept(T t, U u) throws E;
|
||||
void accept(T t, U u)
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FunctionWithExceptions<T, R, E extends Exception> {
|
||||
static <T> FunctionWithExceptions<T, T, Exception> identity() {
|
||||
return t -> t;
|
||||
}
|
||||
|
||||
R apply(T t) throws E;
|
||||
|
||||
R apply(T t)
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiFunctionWithExceptions<T, U, R, E extends Exception> {
|
||||
R apply(T t, U u) throws E;
|
||||
R apply(T t, U u)
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SupplierWithExceptions<T, E extends Exception> {
|
||||
T get() throws E;
|
||||
T get()
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RunnableWithExceptions<E extends Exception> {
|
||||
void run() throws E;
|
||||
void run()
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PredicateWithExceptions<T, E extends Exception> {
|
||||
boolean test(T t) throws E;
|
||||
boolean test(T t)
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiPredicateWithExceptions<T, U, E extends Exception> {
|
||||
boolean test(T t, U u) throws E;
|
||||
boolean test(T t, U u)
|
||||
throws E;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -12,21 +12,21 @@ import java.util.List;
|
||||
* @date 2023-04-17 04:30:20
|
||||
*/
|
||||
public class NameUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 解析驼峰
|
||||
*
|
||||
* @param param 参数
|
||||
* @param type 类型
|
||||
* @return {@link String }
|
||||
* @author nn200433
|
||||
* @author song_jx
|
||||
*/
|
||||
public static String parseCamelTo(String param, FormatType type) {
|
||||
if (type == FormatType.CAMEL) {
|
||||
return param;
|
||||
}
|
||||
int len = param.length();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
int len = param.length();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = param.charAt(i);
|
||||
if (Character.isUpperCase(c)) {
|
||||
@ -38,7 +38,7 @@ public class NameUtil {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析驼峰
|
||||
*
|
||||
@ -53,5 +53,5 @@ public class NameUtil {
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.aizuda.trans.demo.DemoService;
|
||||
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 org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -29,19 +30,25 @@ public class TranslatorTest {
|
||||
@Test
|
||||
public void demo1() {
|
||||
List<People> peopleList = demoService.dictDemo();
|
||||
Console.log("---> 翻译结果:{}", peopleList);
|
||||
Console.log("---> 字典 & 脱敏 翻译结果:{}", peopleList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void demo2() {
|
||||
List<Device> deviceList = demoService.enumDemo();
|
||||
Console.log("---> 翻译结果:{}", deviceList);
|
||||
Console.log("---> 枚举 翻译结果:{}", deviceList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void demo3() {
|
||||
List<People2> peopleList = demoService.dbDemo();
|
||||
Console.log("---> 翻译结果:{}", peopleList);
|
||||
Console.log("---> 数据库 翻译结果:{}", peopleList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void demo4() {
|
||||
List<People3> peopleList = demoService.jsonDemo();
|
||||
Console.log("---> json 翻译结果:{}", peopleList);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.aizuda.trans.demo;
|
||||
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 java.util.List;
|
||||
|
||||
@ -38,4 +39,12 @@ public interface DemoService {
|
||||
*/
|
||||
public List<People2> dbDemo();
|
||||
|
||||
/**
|
||||
* json演示
|
||||
*
|
||||
* @return {@link List }<{@link People3 }>
|
||||
* @author song_jx
|
||||
*/
|
||||
public List<People3> jsonDemo();
|
||||
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ import java.util.List;
|
||||
public class CustomerTranslateServiceImpl implements Translatable {
|
||||
|
||||
@Override
|
||||
public List<String> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
|
||||
Class dictClass) {
|
||||
List<String> rList = new ArrayList<String>(1);
|
||||
List<Object> rList = new ArrayList<Object>(1);
|
||||
if (StrUtil.equals(origin, "1")) {
|
||||
rList.add("结果1");
|
||||
} else {
|
||||
|
@ -6,6 +6,7 @@ import com.aizuda.trans.demo.DemoService;
|
||||
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 org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
@ -43,4 +44,12 @@ public class DemoServiceImpl implements DemoService {
|
||||
return CollUtil.newArrayList(man, woman);
|
||||
}
|
||||
|
||||
@Translator
|
||||
@Override
|
||||
public List<People3> jsonDemo() {
|
||||
People3 man = People3.builder().id("1").json("{\"abc\":\"def\", \"eg\":3}").build();
|
||||
People3 woman = People3.builder().id("2").json("[{\"a\":\"b\",\"c\":6},{\"d\":\"f\",\"e\":{\"a\":\"6\"}}]").build();
|
||||
return CollUtil.newArrayList(man, woman);
|
||||
}
|
||||
|
||||
}
|
||||
|
33
src/test/java/com/aizuda/trans/entity/People3.java
Normal file
33
src/test/java/com/aizuda/trans/entity/People3.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.aizuda.trans.entity;
|
||||
|
||||
import com.aizuda.trans.annotation.Translate;
|
||||
import com.aizuda.trans.json.JSONConvert;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 人3
|
||||
*
|
||||
* @author nn200433
|
||||
* @date 2022-12-16 016 11:40:30
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class People3 {
|
||||
|
||||
/** 数据库翻译 */
|
||||
@Translate(dictClass = UserDB.class, translateField = "name")
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Translate(dictClass = JSONConvert.class, translateField = "jsonObj")
|
||||
private String json;
|
||||
|
||||
private Object jsonObj;
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user