|
@@ -0,0 +1,155 @@
|
|
|
+package org.jeecg.common.util;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import lombok.extern.log4j.Log4j2;
|
|
|
+import org.apache.commons.lang3.reflect.FieldUtils;
|
|
|
+import org.jeecg.common.api.CommonAPI;
|
|
|
+import org.jeecg.common.aspect.annotation.Dict;
|
|
|
+import org.springframework.cache.Cache;
|
|
|
+import org.springframework.cache.CacheManager;
|
|
|
+import org.springframework.util.ConcurrentReferenceHashMap;
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.ConcurrentMap;
|
|
|
+@Log4j2
|
|
|
+public class DictAnnotationUtil {
|
|
|
+ // 缓存字典项(Key: dictCode, Value: Map<itemValue, itemText>)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private static final ConcurrentMap<String, Map<String, String>> DICT_CACHE =
|
|
|
+ new ConcurrentReferenceHashMap<>(512);
|
|
|
+
|
|
|
+ // Spring CacheManager(用于二级缓存,如Redis)
|
|
|
+ private static CacheManager cacheManager;
|
|
|
+
|
|
|
+
|
|
|
+ private static CommonAPI commonAPI;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 注入CacheManager(需在Spring容器初始化后调用)
|
|
|
+ */
|
|
|
+ public static void setCacheManager(CacheManager manager) {
|
|
|
+ cacheManager = manager;
|
|
|
+ }
|
|
|
+ public static void setCommonAPI(CommonAPI common) {
|
|
|
+ commonAPI = common;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量翻译集合中的字典字段
|
|
|
+ */
|
|
|
+ public static void translateDictList(Collection<?> list) {
|
|
|
+ if (list == null || list.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ System.out.println(JSONObject.toJSONString(list));
|
|
|
+ try {
|
|
|
+ list.forEach(DictAnnotationUtil::translateDict);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 生产环境打印警告日志,避免中断主流程
|
|
|
+ log.warn("字典翻译异常: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 翻译单个对象的字典字段
|
|
|
+ */
|
|
|
+ private static void translateDict(Object obj) {
|
|
|
+ if (obj == null) return;
|
|
|
+
|
|
|
+ System.out.println(JSONObject.toJSONString(obj));
|
|
|
+ Class<?> clazz = obj.getClass();
|
|
|
+ // 缓存类字段信息,避免重复反射
|
|
|
+ Field[] fields = getCachedFields(clazz);
|
|
|
+
|
|
|
+ for (Field field : fields) {
|
|
|
+ Dict dictAnnotation = field.getAnnotation(Dict.class);
|
|
|
+ if (dictAnnotation == null) continue;
|
|
|
+
|
|
|
+ try {
|
|
|
+ String dictCode = dictAnnotation.dicCode();
|
|
|
+ Object fieldValue = FieldUtils.readField(field, obj, true);
|
|
|
+ if (fieldValue == null) continue;
|
|
|
+
|
|
|
+ // 获取字典文本
|
|
|
+ String dictText = getDictText(dictCode, String.valueOf(fieldValue));
|
|
|
+ if (dictText == null) continue;
|
|
|
+
|
|
|
+ // 写入目标字段
|
|
|
+ String targetField = field.getName() + "_dictText";
|
|
|
+ FieldUtils.writeField(obj, targetField, dictText, true);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("字段翻译失败: {}.{}", clazz.getSimpleName(), field.getName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取字典文本(多级缓存策略)
|
|
|
+ */
|
|
|
+ private static String getDictText(String dictCode, String itemValue) {
|
|
|
+ // 1. 优先从本地缓存查询
|
|
|
+ Map<String, String> dictMap = DICT_CACHE.get(dictCode);
|
|
|
+ if (dictMap != null && dictMap.containsKey(itemValue)) {
|
|
|
+ return dictMap.get(itemValue);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 从Redis等分布式缓存查询
|
|
|
+ if (cacheManager != null) {
|
|
|
+ Cache cache = cacheManager.getCache("dictCache");
|
|
|
+ if (cache != null) {
|
|
|
+ String cacheKey = dictCode + ":" + itemValue;
|
|
|
+ String cachedText = cache.get(cacheKey, String.class);
|
|
|
+ if (cachedText != null) {
|
|
|
+ return cachedText;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 从数据库查询并更新缓存
|
|
|
+ String dictText = queryFromDatabase(dictCode, itemValue);
|
|
|
+ if (dictText != null) {
|
|
|
+ updateCache(dictCode, itemValue, dictText);
|
|
|
+ }
|
|
|
+ return dictText;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从数据库查询字典项
|
|
|
+ */
|
|
|
+ private static String queryFromDatabase(String dictCode, String itemValue) {
|
|
|
+ // 伪代码:实际需替换为MyBatis/JDBC查询
|
|
|
+
|
|
|
+ return commonAPI.selectDictText(dictCode, itemValue);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新多级缓存
|
|
|
+ */
|
|
|
+ private static void updateCache(String dictCode, String itemValue, String itemText) {
|
|
|
+ // 更新本地缓存
|
|
|
+ DICT_CACHE.computeIfAbsent(dictCode, k -> new HashMap<>())
|
|
|
+ .put(itemValue, itemText);
|
|
|
+
|
|
|
+ // 更新分布式缓存
|
|
|
+ if (cacheManager != null) {
|
|
|
+ Cache cache = cacheManager.getCache("dictCache");
|
|
|
+ if (cache != null) {
|
|
|
+ cache.put(dictCode + ":" + itemValue, itemText);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 缓存类字段信息(减少反射开销)
|
|
|
+ */
|
|
|
+ private static final Map<Class<?>, Field[]> FIELD_CACHE = new ConcurrentReferenceHashMap<>();
|
|
|
+ private static Field[] getCachedFields(Class<?> clazz) {
|
|
|
+ return FIELD_CACHE.computeIfAbsent(clazz, FieldUtils::getAllFields);
|
|
|
+ }
|
|
|
+}
|