package com.fkxinli.zxyy.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fkxinli.zxyy.common.core.annotation.TranslateField;
import com.fkxinli.zxyy.common.core.service.TranslateService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 静态翻译工具类
* 功能:将对象字段值翻译为目标字段值,支持多种数据结构
*
* @author 84595
*/
@Component
public class TranslateUtils1 {
// Redis模板和翻译服务静态引用
private static RedisTemplate<String, Object> redisTemplate;
private static TranslateService translateService;
private static final String CACHE_PREFIX = "translate:";
private static final long CACHE_EXPIRE = 24 * 3600L;
@Autowired
private RedisTemplate<String, Object> staticRedisTemplate;
@Autowired
private TranslateService staticTranslateService;
@PostConstruct
public void init() {
redisTemplate = this.staticRedisTemplate;
translateService = this.staticTranslateService;
}
/**
* 通过Spring自动注入初始化静态依赖
*/
// static {
// redisTemplate = SpringContextUtil.getBean("redisCacheTemplate");
// translateService = SpringContextUtil.getBean(TranslateService.class);
// }
/**
* 翻译IPage对象
*/
public static void translate(IPage<?> page, String... fieldPairs) {
if (page != null) translate(page.getRecords(), fieldPairs);
}
/**
* 翻译集合对象
*/
public static void translate(Collection<?> targets, String... fieldPairs) {
if (CollectionUtils.isEmpty(targets)) return;
// 1. 收集需要翻译的键
Map<TranslateKey, TranslationTarget> translationMap = new HashMap<>();
targets.forEach(target -> collectKeys(target, fieldPairs, translationMap));
// 2. 批量查询缓存
Map<TranslateKey, Object> cachedValues = batchGetCache(translationMap.keySet());
// 3. 查询数据库获取缺失的翻译值
Set<TranslateKey> missingKeys = translationMap.keySet().stream()
.filter(k -> !cachedValues.containsKey(k))
.collect(Collectors.toSet());
if (!missingKeys.isEmpty()) {
Map<TranslateKey, Object> dbValues = batchQueryDB(missingKeys);
cachedValues.putAll(dbValues);
batchSetCache(dbValues);
}
// 4. 应用翻译结果到目标对象
applyTranslations(translationMap, cachedValues);
}
/**
* 收集需要翻译的键
*/
private static void collectKeys(Object obj, String[] fieldPairs,
Map<TranslateKey, TranslationTarget> map) {
if (obj instanceof Map) {
processMap((Map<?, ?>) obj, fieldPairs, map);
} else {
processObject(obj, fieldPairs, map);
}
}
/**
* 处理Map类型对象的翻译键收集
*/
private static void processMap(Map<?, ?> map, String[] fieldPairs,
Map<TranslateKey, TranslationTarget> result) {
map.forEach((k, v) -> {
if (v != null && !isSimpleValue(v.getClass())) {
collectKeys(v, fieldPairs, result);
} else if (fieldPairs != null) {
Arrays.stream(fieldPairs)
.map(pair -> pair.split("\\|"))
.filter(parts -> parts.length == 2)
.forEach(parts -> {
Object value = map.get(parts[0].trim());
if (value != null) {
String type = parts[1].trim().toLowerCase();
String targetField = parts[0] + "Name";
result.put(new TranslateKey(value.toString(), type),
new TranslationTarget(map, targetField));
}
});
}
});
}
/**
* 处理普通对象的翻译键收集
*/
private static void processObject(Object obj, String[] fieldPairs,
Map<TranslateKey, TranslationTarget> result) {
// 处理注解字段
Arrays.stream(obj.getClass().getDeclaredFields())
.filter(f -> f.isAnnotationPresent(TranslateField.class))
.forEach(f -> {
try {
f.setAccessible(true);
Object value = f.get(obj);
if (value != null) {
TranslateField anno = f.getAnnotation(TranslateField.class);
String targetField = anno.targetField().isEmpty() ?
f.getName() + "Name" : anno.targetField();
result.put(new TranslateKey(value.toString(), anno.type()),
new TranslationTarget(obj, targetField));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
});
// 处理参数指定字段
if (fieldPairs != null) {
Arrays.stream(fieldPairs)
.map(pair -> pair.split("\\|"))
.filter(parts -> parts.length == 2)
.forEach(parts -> {
try {
Field f = obj.getClass().getDeclaredField(parts[0].trim());
f.setAccessible(true);
Object value = f.get(obj);
if (value != null) {
String type = parts[1].trim().toLowerCase();
String targetField = parts[0] + "Name";
result.put(new TranslateKey(value.toString(), type),
new TranslationTarget(obj, targetField));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
/**
* 批量从缓存获取翻译值
*/
private static Map<TranslateKey, Object> batchGetCache(Set<TranslateKey> keys) {
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptyMap();
}
// 构建缓存键列表
List<String> cacheKeys = keys.stream()
.map(k -> String.format("%s%s:%s", CACHE_PREFIX, k.type(), k.value()))
.collect(Collectors.toList());
// 批量获取缓存值
List<Object> cachedValues = redisTemplate.opsForValue().multiGet(cacheKeys);
if (CollectionUtils.isEmpty(cachedValues)) {
return Collections.emptyMap();
}
// 构建结果映射
Map<TranslateKey, Object> result = new HashMap<>(keys.size());
Iterator<TranslateKey> keyIterator = keys.iterator();
Iterator<Object> valueIterator = cachedValues.iterator();
while (keyIterator.hasNext() && valueIterator.hasNext()) {
TranslateKey key = keyIterator.next();
Object value = valueIterator.next();
if (value != null) {
result.put(key, value);
}
}
return result;
}
/**
* 批量从数据库查询翻译值
*/
private static Map<TranslateKey, Object> batchQueryDB(Set<TranslateKey> keys) {
Map<TranslateKey, Object> result = new HashMap<>();
Map<String, List<String>> groupedKeys = keys.stream()
.collect(Collectors.groupingBy(
k -> k.type,
Collectors.mapping(k -> k.value, Collectors.toList())
));
Map<String, Map<String, String>> stringMapMap = translateService.batchTranslate(groupedKeys);
if (CollUtil.isNotEmpty(stringMapMap)) {
stringMapMap.forEach((type, map) -> {
map.forEach((id, name) -> {
result.put(new TranslateKey(id, type), name);
});
});
}
// groupedKeys.forEach((type, ids) -> {
// if ("person".equals(type)) {
// translateService.batchGetUserNames(ids)
// .forEach((id, name) ->
// result.put(new TranslateKey(id, type), name));
// } else if ("org".equals(type)) {
// translateService.batchGetOrgNames(ids)
// .forEach((id, name) ->
// result.put(new TranslateKey(id, type), name));
// }
// });
return result;
}
/**
* 批量设置缓存值(使用管道)
*/
private static void batchSetCache(Map<TranslateKey, Object> values) {
redisTemplate.executePipelined((RedisCallback<?>) connection -> {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
values.forEach((key, value) -> {
String cacheKey = CACHE_PREFIX + key.type + ":" + key.value;
// 使用RedisTemplate的set方法替代过时的connection.setEx
ops.set(cacheKey, value, CACHE_EXPIRE, TimeUnit.SECONDS);
});
return null;
});
}
/**
* 应用翻译结果到目标对象
*/
private static void applyTranslations(Map<TranslateKey, TranslationTarget> targets,
Map<TranslateKey, Object> values) {
targets.forEach((key, target) -> {
Object translatedValue = values.get(key);
if (translatedValue != null) {
setFieldValue(target.target, target.fieldName, translatedValue);
}
});
}
/**
* 设置字段值
*/
private static void setFieldValue(Object target, String fieldName, Object value) {
try {
if (target instanceof Map) {
((Map) target).put(fieldName, value);
} else {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
}
} catch (Exception e) {
throw new RuntimeException("Set field failed: " + fieldName, e);
}
}
/**
* 判断是否为简单值类型
*/
private static boolean isSimpleValue(Class<?> clazz) {
return clazz.isPrimitive() || CharSequence.class.isAssignableFrom(clazz)
|| Number.class.isAssignableFrom(clazz) || clazz == Boolean.class;
}
/**
* 翻译键记录
*/
private record TranslateKey(String value, String type) {
}
/**
* 翻译目标记录
*/
private record TranslationTarget(Object target, String fieldName) {
}
}
优化代码,要求能够使其他springboot3服务使用
最新发布