[新增功能](dev): 增加摘要提取功能(顺带修改了下 Translatable 接口)

This commit is contained in:
song_jx 2023-06-07 17:26:18 +08:00
parent dfe5154b06
commit 3b7ba0a004
15 changed files with 222 additions and 62 deletions

View File

@ -23,13 +23,20 @@ public @interface Translate {
* <li>IDict实现类枚举翻译</li>
* <li>Desensitized: 脱敏翻译</li>
* <li>JSONConvert: json字符串翻译</li>
* <li>SummaryExtract: 摘要提取</li>
* <li>其他: 数据库翻译</li>
* </ul>
*/
Class<?> dictClass() default void.class;
/**
* 翻译后的属性名注意使用驼峰命名 默认为原属性名去除末尾的"Id""Code"再接上"Name"
* 翻译后的属性名注意使用驼峰命名
* <ul>
* <li>1. 不填时默认为原属性名去除末尾的"Id""Code"再接上"Name"</li>
* <li>2. Desensitized脱敏 SummaryExtract摘要提取不填时默认为原字段</li>
* </ul>
*
*
*/
String[] translateField() default {};
@ -64,5 +71,14 @@ public @interface Translate {
* </ul>
*/
String desensitizedModel() default DesensitizedTypeConstants.EMPTY;
/**
* 最大长度限制
* 适用于以下翻译
* <ul>
* <li>1. 摘要提取长度限制</li>
* </ul>
*/
int maxLen() default Integer.MAX_VALUE;
}

View File

@ -0,0 +1,28 @@
package com.aizuda.trans.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 扩展参数
*
* @author song_jx
* @date 2023-06-07 007 10:04:27
*/
@Data
@AllArgsConstructor
public class ExtendParam {
/** 字典group值不用可忽略如静态字典需要先通过group值确定范围再根据code值得到对应的value */
private String groupValue;
/** 条件字段值(仅限用户自定义时生效) */
private String conditionValue;
/** 字典class */
private Class dictClass;
/** 最大长度限制 */
private int maxLen;
}

View File

@ -0,0 +1,21 @@
package com.aizuda.trans.service;
/**
* 摘要提取服务
*
* @author song_jx
* @date 2022-08-18 018 16:31:43
*/
public interface SummaryExtractService {
/**
* 提取
*
* @param content 内容
* @param maxLen 最大长度
* @return {@link String }
* @author song_jx
*/
public String extract(String content, int maxLen);
}

View File

@ -1,6 +1,7 @@
package com.aizuda.trans.service;
import com.aizuda.trans.annotation.Dictionary;
import com.aizuda.trans.entity.ExtendParam;
import java.util.List;
@ -13,19 +14,16 @@ import java.util.List;
* @create 2020-04
*/
public interface Translatable {
/**
* 自定义翻译方法需要自己实现
*
* @param groupValue 字典group值不用可忽略如静态字典需要先通过group值确定范围再根据code值得到对应的value
* @param conditionValue 条件字段值仅限用户自定义时生效
* @param origin 待翻译的原始值对应字典code属性
* @param dictConfig 字典注解可获取属性配置
* @param dictClass 字典class
* @return {@link List }<{@link Object }> 字典value可以返回null值翻译时会处理如果为null则显示原始值
* @author nn200433
* @param origin 待翻译的原始值对应字典code属性
* @param dictConfig 字典注解可获取属性配置
* @param extendParam 扩展参数
* @return {@link List }<{@link Object }>
* @author song_jx
*/
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
Class dictClass);
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam);
}

View File

@ -0,0 +1,11 @@
package com.aizuda.trans.summary;
/**
* 摘要提取接口
*
* @author song_jx
* @date 2022-12-08 008 10:47:22
*/
public interface ISummaryExtract {
}

View File

@ -0,0 +1,11 @@
package com.aizuda.trans.summary;
/**
* 摘要提取
*
* @author song_jx
* @date 2022-12-08 008 10:50:37
*/
public class SummaryExtract implements ISummaryExtract {
}

View File

@ -1,7 +1,9 @@
package com.aizuda.trans.config;
import com.aizuda.trans.service.DictTranslateService;
import com.aizuda.trans.service.SummaryExtractService;
import com.aizuda.trans.service.impl.DefaultDictTranslateServiceImpl;
import com.aizuda.trans.service.impl.DefaultSummaryExtractServiceImpl;
import com.aizuda.trans.service.impl.wrapper.IPageUnWrapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@ -30,6 +32,19 @@ public class TranslatorConfig {
return new DefaultDictTranslateServiceImpl();
}
/**
* 注册摘要提取服务默认实现
*
* @return {@link DictTranslateService }
* @author song_jx
*/
@Bean
@ConditionalOnMissingBean
public SummaryExtractService summaryExtractService() {
return new DefaultSummaryExtractServiceImpl();
}
/**
* 注册IPage解包器
*

View File

@ -12,11 +12,13 @@ import com.aizuda.trans.annotation.Translate;
import com.aizuda.trans.annotation.Translator;
import com.aizuda.trans.desensitized.IDesensitized;
import com.aizuda.trans.dict.DictTranslate;
import com.aizuda.trans.entity.ExtendParam;
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.summary.ISummaryExtract;
import com.aizuda.trans.util.NameUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -113,20 +115,16 @@ public class TranslatorHandle {
*
* @param originValue 原始值
* @param dictionaryConfig 字典配置
* @param dictClass 字典class包含组别属性字典code属性字典值属性三个信息
* @param groupValue 组别的值由使用者指定
* @param conditionValue 条件字段值
* @param extendParam 扩展参数
* @return {@link List }<{@link Object }>
* @author nn200433
*/
public static List<Object> parse(String originValue, Dictionary dictionaryConfig, Class<?> dictClass, String groupValue,
String conditionValue) {
public static List<Object> parse(String originValue, Dictionary dictionaryConfig, ExtendParam extendParam) {
if (originValue == null) {
return null;
}
final Translatable translator = getTranslatable(dictClass, dictionaryConfig.translator());
return CollUtil.defaultIfEmpty(translator.translate(groupValue, conditionValue, originValue, dictionaryConfig, dictClass),
Collections.emptyList());
final Translatable translator = getTranslatable(extendParam.getDictClass(), dictionaryConfig.translator());
return CollUtil.defaultIfEmpty(translator.translate(originValue, dictionaryConfig, extendParam), Collections.emptyList());
}
/**
@ -148,6 +146,7 @@ public class TranslatorHandle {
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);
@ -164,7 +163,8 @@ public class TranslatorHandle {
}
// 获取翻译结果并脱敏处理
List<Object> translateValList = parse(originValue, dictionaryConfig, dictClass, groupValue, conditionFieldValue);
final ExtendParam extendParam = new ExtendParam(groupValue, conditionFieldValue, dictClass, maxLen);
List<Object> translateValList = parse(originValue, dictionaryConfig, extendParam);
if (!isJsonConvert) {
// 不是 JsonConvert.class 时可进行脱敏
translateValList = desensitizedHandle(desensitizedModel, translateValList);
@ -280,11 +280,18 @@ public class TranslatorHandle {
* @author nn200433
*/
private static List<String> getTranslateFieldName(Translate translateConfig, String originFieldName) {
String[] translateFieldArray = translateConfig.translateField();
final int translateFieldLen = translateFieldArray.length;
final String newName = originFieldName.replaceFirst("(Id|Code)$|$", "Name");
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) {
translateFieldArray = new String[]{newName};
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];
@ -424,6 +431,9 @@ public class TranslatorHandle {
} else if (IJsonConvert.class.isAssignableFrom(dictClass)) {
// 4.dictClass是JSON类采用JSON翻译
translatorClass = JsonConvertTranslator.class;
} else if (ISummaryExtract.class.isAssignableFrom(dictClass)) {
// 5.dictClass是JSON类采用JSON翻译
translatorClass = SummaryExtractTranslator.class;
} else {
// 5.否则使用数据库翻译
translatorClass = DataBaseTranslator.class;

View File

@ -1,5 +1,6 @@
package com.aizuda.trans.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
@ -9,6 +10,7 @@ import cn.hutool.db.Entity;
import cn.hutool.db.handler.EntityHandler;
import cn.hutool.db.handler.EntityListHandler;
import com.aizuda.trans.annotation.Dictionary;
import com.aizuda.trans.entity.ExtendParam;
import com.aizuda.trans.enums.FormatType;
import com.aizuda.trans.service.Translatable;
import com.aizuda.trans.util.NameUtil;
@ -16,7 +18,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import javax.sql.DataSource;
import java.sql.SQLException;
@ -43,23 +44,22 @@ public class DataBaseTranslator implements Translatable {
private DataSource dataSource;
@Override
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
Class dictClass) {
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam) {
// 获取参数
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());
final String codeColumn = dictConfig.codeColumn();
final String[] textColumnArray = dictConfig.textColumn();
final String groupColumn = dictConfig.groupColumn();
final Class dictClass = extendParam.getDictClass();
final String groupValue = extendParam.getGroupValue();
final String simpleName = dictClass.getSimpleName();
final String tableName = getTableName(dictConfig, dictClass);
Assert.isTrue(StrUtil.isNotBlank(codeColumn), "@Dictionary注解codeColumn配置有误找不到指定的属性名class: {}", simpleName);
Assert.isTrue(ArrayUtil.isNotEmpty(textColumnArray), "@Dictionary注解textColumn配置有误找不到指定的属性名class: {}", simpleName);
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)) {
@ -117,8 +117,7 @@ public class DataBaseTranslator implements Translatable {
// 类名转表名
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);

View File

@ -0,0 +1,26 @@
package com.aizuda.trans.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.aizuda.trans.service.SummaryExtractService;
/**
* 摘要提取服务默认实现
*
* @author song_jx
* @date 2022-08-18 018 16:31:43
*/
public class DefaultSummaryExtractServiceImpl implements SummaryExtractService {
@Override
public String extract(String content, int maxLen) {
/*
1. 先还原标签比如&ldquo;再通过正则删除html标签
2. 删除空白符包括空格制表符全角空格和不间断空格
3. 删除换行符
3. 限制长度
*/
return StrUtil.maxLength(StrUtil.removeAllLineBreaks(StrUtil.cleanBlank(HtmlUtil.cleanHtmlTag(HtmlUtil.unescape(content)))), maxLen);
}
}

View File

@ -1,6 +1,7 @@
package com.aizuda.trans.service.impl;
import com.aizuda.trans.annotation.Dictionary;
import com.aizuda.trans.entity.ExtendParam;
import com.aizuda.trans.service.Translatable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -19,8 +20,7 @@ import java.util.List;
public class DesensitizedTranslator implements Translatable {
@Override
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
Class dictClass) {
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam) {
// 直接返回原值
return Collections.singletonList(origin);
}

View File

@ -1,6 +1,7 @@
package com.aizuda.trans.service.impl;
import com.aizuda.trans.annotation.Dictionary;
import com.aizuda.trans.entity.ExtendParam;
import com.aizuda.trans.service.DictTranslateService;
import com.aizuda.trans.service.Translatable;
import lombok.extern.slf4j.Slf4j;
@ -22,12 +23,10 @@ public class DictCacheTranslator implements Translatable {
@Autowired
private DictTranslateService dictTranslateService;
@Override
@SuppressWarnings("unchecked")
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
Class dictClass) {
return Collections.singletonList(dictTranslateService.findDictLabel(groupValue, origin));
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam) {
return Collections.singletonList(dictTranslateService.findDictLabel(extendParam.getGroupValue(), origin));
}
}

View File

@ -1,10 +1,11 @@
package com.aizuda.trans.service.impl;
import cn.hutool.core.lang.Assert;
import com.aizuda.trans.annotation.Dictionary;
import com.aizuda.trans.entity.ExtendParam;
import com.aizuda.trans.enums.IEnum;
import com.aizuda.trans.service.Translatable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.Collections;
import java.util.List;
@ -20,15 +21,11 @@ import java.util.stream.Stream;
public class EnumTranslator implements Translatable {
@Override
@SuppressWarnings("unchecked")
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);
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam) {
final Class dictClass = extendParam.getDictClass();
Assert.isTrue(IEnum.class.isAssignableFrom(dictClass), "{} 不是IDictEnum的实现类无法使用EnumTranslator进行翻译", dictClass.getSimpleName());
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);
}

View File

@ -4,6 +4,7 @@ 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.entity.ExtendParam;
import com.aizuda.trans.service.Translatable;
import org.springframework.stereotype.Component;
@ -20,9 +21,7 @@ import java.util.List;
public class JsonConvertTranslator implements Translatable {
@Override
@SuppressWarnings("unchecked")
public List<Object> translate(String groupValue, String conditionValue, String origin, Dictionary dictConfig,
Class dictClass) {
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam) {
Assert.isTrue(JSONUtil.isTypeJSON(origin), "该数据不是 JSON 字符串JSON 字符串应为 “{}” 或 “[]” 包裹的数据。");
Object rObj = null;
if (JSONUtil.isTypeJSONObject(origin)) {

View File

@ -0,0 +1,30 @@
package com.aizuda.trans.service.impl;
import com.aizuda.trans.annotation.Dictionary;
import com.aizuda.trans.entity.ExtendParam;
import com.aizuda.trans.service.SummaryExtractService;
import com.aizuda.trans.service.Translatable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
/**
* 摘要提取翻译
*
* @author song_jx
* @date 2023-06-07 09:32:49
*/
@Component
public class SummaryExtractTranslator implements Translatable {
@Autowired
private SummaryExtractService summaryExtractService;
@Override
public List<Object> translate(String origin, Dictionary dictConfig, ExtendParam extendParam) {
return Collections.singletonList(summaryExtractService.extract(origin, extendParam.getMaxLen()));
}
}