소스 검색

Merge branch 'master' of http://192.168.1.25:3000/lbyzx123/huimv-baqing

xsh_1997 1 주 전
부모
커밋
0912160bc1

+ 65 - 0
baqing-admin/src/test/java/com/ruoyi/framework/config/SysDictDataRedisSerializerTest.java

@@ -0,0 +1,65 @@
1
+package com.ruoyi.framework.config;
2
+
3
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
4
+import static org.junit.jupiter.api.Assertions.assertFalse;
5
+import static org.junit.jupiter.api.Assertions.assertNotNull;
6
+import static org.junit.jupiter.api.Assertions.assertTrue;
7
+
8
+import java.util.Collections;
9
+import java.util.List;
10
+
11
+import org.junit.jupiter.api.DisplayName;
12
+import org.junit.jupiter.api.Test;
13
+
14
+import com.alibaba.fastjson2.JSONArray;
15
+import com.ruoyi.common.core.domain.entity.SysDictData;
16
+
17
+/**
18
+ * 复现 sys_normal_disable 字典 Redis 缓存 Fastjson2 反序列化失败。
19
+ */
20
+@DisplayName("SysDictData Redis 序列化")
21
+class SysDictDataRedisSerializerTest
22
+{
23
+    @Test
24
+    @DisplayName("Object.class 序列化字典列表不含 default 布尔字段")
25
+    void dictListRoundTripAsObjectClass()
26
+    {
27
+        SysDictData row = new SysDictData();
28
+        row.setDictCode(1L);
29
+        row.setDictSort(1L);
30
+        row.setDictLabel("正常");
31
+        row.setDictValue("0");
32
+        row.setDictType("sys_normal_disable");
33
+        row.setListClass("primary");
34
+        row.setIsDefault("Y");
35
+        row.setStatus("0");
36
+        List<SysDictData> list = Collections.singletonList(row);
37
+
38
+        FastJson2JsonRedisSerializer<Object> serializer = new FastJson2JsonRedisSerializer<>(Object.class);
39
+        byte[] bytes = serializer.serialize(list);
40
+        String json = new String(bytes, FastJson2JsonRedisSerializer.DEFAULT_CHARSET);
41
+        assertFalse(json.contains("\"default\":"), () -> "不应序列化 getDefault() 为 default 字段:" + json);
42
+
43
+        Object raw = assertDoesNotThrow(() -> serializer.deserialize(bytes));
44
+        assertNotNull(raw);
45
+        JSONArray array = (JSONArray) raw;
46
+        assertTrue(array.size() > 0);
47
+        SysDictData restored = array.getObject(0, SysDictData.class);
48
+        assertNotNull(restored);
49
+        assertTrue("正常".equals(restored.getDictLabel()));
50
+    }
51
+
52
+    @Test
53
+    @DisplayName("兼容含 legacy default:false 的历史缓存")
54
+    void deserializeLegacyDictCacheWithDefaultField()
55
+    {
56
+        String legacyJson =
57
+                "[{\"@type\":\"com.ruoyi.common.core.domain.entity.SysDictData\",\"dictCode\":1,"
58
+                        + "\"dictLabel\":\"正常\",\"dictValue\":\"0\",\"dictType\":\"sys_normal_disable\","
59
+                        + "\"isDefault\":\"Y\",\"default\":false,\"listClass\":\"primary\",\"status\":\"0\"}]";
60
+        FastJson2JsonRedisSerializer<Object> serializer = new FastJson2JsonRedisSerializer<>(Object.class);
61
+        Object raw = assertDoesNotThrow(
62
+                () -> serializer.deserialize(legacyJson.getBytes(FastJson2JsonRedisSerializer.DEFAULT_CHARSET)));
63
+        assertNotNull(raw);
64
+    }
65
+}

+ 11 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java

@@ -4,6 +4,8 @@ import javax.validation.constraints.NotBlank;
4 4
 import javax.validation.constraints.Size;
5 5
 import org.apache.commons.lang3.builder.ToStringBuilder;
6 6
 import org.apache.commons.lang3.builder.ToStringStyle;
7
+import com.alibaba.fastjson2.annotation.JSONField;
8
+import com.fasterxml.jackson.annotation.JsonIgnore;
7 9
 import com.ruoyi.common.annotation.Excel;
8 10
 import com.ruoyi.common.annotation.Excel.ColumnType;
9 11
 import com.ruoyi.common.constant.UserConstants;
@@ -129,11 +131,20 @@ public class SysDictData extends BaseEntity
129 131
         this.listClass = listClass;
130 132
     }
131 133
 
134
+    @JSONField(serialize = false, deserialize = false)
135
+    @JsonIgnore
132 136
     public boolean getDefault()
133 137
     {
134 138
         return UserConstants.YES.equals(this.isDefault);
135 139
     }
136 140
 
141
+    /** 兼容历史 Redis 缓存中的 default 字段,反序列化时忽略 */
142
+    @JSONField(serialize = false, deserialize = false)
143
+    @JsonIgnore
144
+    public void setDefault(boolean ignored)
145
+    {
146
+    }
147
+
137 148
     public String getIsDefault()
138 149
     {
139 150
         return isDefault;

+ 16 - 3
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java

@@ -4,6 +4,8 @@ import java.util.Collection;
4 4
 import java.util.HashMap;
5 5
 import java.util.List;
6 6
 import java.util.Map;
7
+import org.slf4j.Logger;
8
+import org.slf4j.LoggerFactory;
7 9
 import com.alibaba.fastjson2.JSONArray;
8 10
 import com.ruoyi.common.constant.CacheConstants;
9 11
 import com.ruoyi.common.core.domain.entity.SysDictData;
@@ -17,6 +19,8 @@ import com.ruoyi.common.utils.spring.SpringUtils;
17 19
  */
18 20
 public class DictUtils
19 21
 {
22
+    private static final Logger log = LoggerFactory.getLogger(DictUtils.class);
23
+
20 24
     /**
21 25
      * 分隔符
22 26
      */
@@ -41,10 +45,19 @@ public class DictUtils
41 45
      */
42 46
     public static List<SysDictData> getDictCache(String key)
43 47
     {
44
-        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
45
-        if (StringUtils.isNotNull(arrayCache))
48
+        String cacheKey = getCacheKey(key);
49
+        try
50
+        {
51
+            JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(cacheKey);
52
+            if (StringUtils.isNotNull(arrayCache))
53
+            {
54
+                return arrayCache.toList(SysDictData.class);
55
+            }
56
+        }
57
+        catch (RuntimeException ex)
46 58
         {
47
-            return arrayCache.toList(SysDictData.class);
59
+            log.warn("字典缓存反序列化失败,已清除并回源数据库:key={}, cause={}", cacheKey, ex.getMessage());
60
+            SpringUtils.getBean(RedisCache.class).deleteObject(cacheKey);
48 61
         }
49 62
         return null;
50 63
     }