ai-engineering-init 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/.claude/agents/code-reviewer.md +3 -130
  2. package/.claude/hooks/skill-forced-eval.js +46 -60
  3. package/.claude/hooks/stop.js +24 -1
  4. package/.claude/settings.json +10 -1
  5. package/.claude/skills/api-development/SKILL.md +179 -130
  6. package/.claude/skills/architecture-design/SKILL.md +102 -212
  7. package/.claude/skills/backend-annotations/SKILL.md +166 -220
  8. package/.claude/skills/bug-detective/SKILL.md +225 -186
  9. package/.claude/skills/code-patterns/SKILL.md +127 -244
  10. package/.claude/skills/codex-code-review/SKILL.md +327 -0
  11. package/.claude/skills/collaborating-with-codex/SKILL.md +96 -113
  12. package/.claude/skills/crud-development/SKILL.md +226 -307
  13. package/.claude/skills/data-permission/SKILL.md +131 -202
  14. package/.claude/skills/database-ops/SKILL.md +158 -355
  15. package/.claude/skills/error-handler/SKILL.md +224 -285
  16. package/.claude/skills/file-oss-management/SKILL.md +174 -169
  17. package/.claude/skills/git-workflow/SKILL.md +123 -341
  18. package/.claude/skills/json-serialization/SKILL.md +121 -137
  19. package/.claude/skills/leniu-report-customization/SKILL.md +82 -2
  20. package/.claude/skills/leniu-report-standard-customization/SKILL.md +65 -2
  21. package/.claude/skills/loki-log-query/SKILL.md +400 -0
  22. package/.claude/skills/mysql-debug/SKILL.md +58 -22
  23. package/.claude/skills/performance-doctor/SKILL.md +83 -89
  24. package/.claude/skills/redis-cache/SKILL.md +134 -185
  25. package/.claude/skills/scheduled-jobs/SKILL.md +187 -224
  26. package/.claude/skills/security-guard/SKILL.md +168 -276
  27. package/.claude/skills/sms-mail/SKILL.md +266 -228
  28. package/.claude/skills/social-login/SKILL.md +257 -195
  29. package/.claude/skills/sync-back-merge/SKILL.md +66 -0
  30. package/.claude/skills/tenant-management/SKILL.md +172 -188
  31. package/.claude/skills/utils-toolkit/SKILL.md +214 -222
  32. package/.claude/skills/websocket-sse/SKILL.md +251 -172
  33. package/.claude/skills/workflow-engine/SKILL.md +178 -250
  34. package/.claude/skills/yunxiao-task-management/SKILL.md +489 -0
  35. package/.codex/skills/api-development/SKILL.md +179 -130
  36. package/.codex/skills/architecture-design/SKILL.md +102 -212
  37. package/.codex/skills/backend-annotations/SKILL.md +166 -220
  38. package/.codex/skills/bug-detective/SKILL.md +225 -186
  39. package/.codex/skills/code-patterns/SKILL.md +127 -244
  40. package/.codex/skills/collaborating-with-codex/SKILL.md +96 -113
  41. package/.codex/skills/crud-development/SKILL.md +226 -307
  42. package/.codex/skills/data-permission/SKILL.md +131 -202
  43. package/.codex/skills/database-ops/SKILL.md +158 -355
  44. package/.codex/skills/error-handler/SKILL.md +224 -285
  45. package/.codex/skills/file-oss-management/SKILL.md +174 -169
  46. package/.codex/skills/git-workflow/SKILL.md +123 -341
  47. package/.codex/skills/json-serialization/SKILL.md +121 -137
  48. package/.codex/skills/leniu-report-customization/SKILL.md +82 -2
  49. package/.codex/skills/leniu-report-standard-customization/SKILL.md +65 -2
  50. package/.codex/skills/loki-log-query/SKILL.md +400 -0
  51. package/.codex/skills/loki-log-query/environments.json +45 -0
  52. package/.codex/skills/mysql-debug/SKILL.md +58 -22
  53. package/.codex/skills/performance-doctor/SKILL.md +83 -89
  54. package/.codex/skills/redis-cache/SKILL.md +134 -185
  55. package/.codex/skills/scheduled-jobs/SKILL.md +187 -224
  56. package/.codex/skills/security-guard/SKILL.md +168 -276
  57. package/.codex/skills/skill-creator/LICENSE.txt +202 -0
  58. package/.codex/skills/skill-creator/SKILL.md +479 -0
  59. package/.codex/skills/skill-creator/agents/analyzer.md +274 -0
  60. package/.codex/skills/skill-creator/agents/comparator.md +202 -0
  61. package/.codex/skills/skill-creator/agents/grader.md +223 -0
  62. package/.codex/skills/skill-creator/assets/eval_review.html +146 -0
  63. package/.codex/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  64. package/.codex/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  65. package/.codex/skills/skill-creator/references/schemas.md +430 -0
  66. package/.codex/skills/skill-creator/scripts/__init__.py +0 -0
  67. package/.codex/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  68. package/.codex/skills/skill-creator/scripts/generate_report.py +326 -0
  69. package/.codex/skills/skill-creator/scripts/improve_description.py +248 -0
  70. package/.codex/skills/skill-creator/scripts/package_skill.py +136 -0
  71. package/.codex/skills/skill-creator/scripts/quick_validate.py +103 -0
  72. package/.codex/skills/skill-creator/scripts/run_eval.py +310 -0
  73. package/.codex/skills/skill-creator/scripts/run_loop.py +332 -0
  74. package/.codex/skills/skill-creator/scripts/utils.py +47 -0
  75. package/.codex/skills/sms-mail/SKILL.md +266 -228
  76. package/.codex/skills/social-login/SKILL.md +257 -195
  77. package/.codex/skills/sync-back-merge/SKILL.md +66 -0
  78. package/.codex/skills/tenant-management/SKILL.md +172 -188
  79. package/.codex/skills/utils-toolkit/SKILL.md +214 -222
  80. package/.codex/skills/websocket-sse/SKILL.md +251 -172
  81. package/.codex/skills/workflow-engine/SKILL.md +178 -250
  82. package/.codex/skills/yunxiao-task-management/SKILL.md +489 -0
  83. package/.cursor/hooks/cursor-skill-eval.js +66 -6
  84. package/.cursor/hooks/stop.js +23 -1
  85. package/.cursor/skills/api-development/SKILL.md +179 -130
  86. package/.cursor/skills/architecture-design/SKILL.md +102 -212
  87. package/.cursor/skills/backend-annotations/SKILL.md +166 -220
  88. package/.cursor/skills/bug-detective/SKILL.md +225 -186
  89. package/.cursor/skills/code-patterns/SKILL.md +127 -244
  90. package/.cursor/skills/collaborating-with-codex/SKILL.md +96 -113
  91. package/.cursor/skills/crud-development/SKILL.md +226 -307
  92. package/.cursor/skills/data-permission/SKILL.md +131 -202
  93. package/.cursor/skills/database-ops/SKILL.md +158 -355
  94. package/.cursor/skills/error-handler/SKILL.md +224 -285
  95. package/.cursor/skills/file-oss-management/SKILL.md +174 -169
  96. package/.cursor/skills/git-workflow/SKILL.md +123 -341
  97. package/.cursor/skills/json-serialization/SKILL.md +121 -137
  98. package/.cursor/skills/leniu-report-customization/SKILL.md +82 -2
  99. package/.cursor/skills/leniu-report-standard-customization/SKILL.md +65 -2
  100. package/.cursor/skills/loki-log-query/SKILL.md +400 -0
  101. package/.cursor/skills/loki-log-query/environments.json +45 -0
  102. package/.cursor/skills/mysql-debug/SKILL.md +58 -22
  103. package/.cursor/skills/performance-doctor/SKILL.md +83 -89
  104. package/.cursor/skills/redis-cache/SKILL.md +134 -185
  105. package/.cursor/skills/scheduled-jobs/SKILL.md +187 -224
  106. package/.cursor/skills/security-guard/SKILL.md +168 -276
  107. package/.cursor/skills/skill-creator/LICENSE.txt +202 -0
  108. package/.cursor/skills/skill-creator/SKILL.md +479 -0
  109. package/.cursor/skills/skill-creator/agents/analyzer.md +274 -0
  110. package/.cursor/skills/skill-creator/agents/comparator.md +202 -0
  111. package/.cursor/skills/skill-creator/agents/grader.md +223 -0
  112. package/.cursor/skills/skill-creator/assets/eval_review.html +146 -0
  113. package/.cursor/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  114. package/.cursor/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  115. package/.cursor/skills/skill-creator/references/schemas.md +430 -0
  116. package/.cursor/skills/skill-creator/scripts/__init__.py +0 -0
  117. package/.cursor/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  118. package/.cursor/skills/skill-creator/scripts/generate_report.py +326 -0
  119. package/.cursor/skills/skill-creator/scripts/improve_description.py +248 -0
  120. package/.cursor/skills/skill-creator/scripts/package_skill.py +136 -0
  121. package/.cursor/skills/skill-creator/scripts/quick_validate.py +103 -0
  122. package/.cursor/skills/skill-creator/scripts/run_eval.py +310 -0
  123. package/.cursor/skills/skill-creator/scripts/run_loop.py +332 -0
  124. package/.cursor/skills/skill-creator/scripts/utils.py +47 -0
  125. package/.cursor/skills/sms-mail/SKILL.md +266 -228
  126. package/.cursor/skills/social-login/SKILL.md +257 -195
  127. package/.cursor/skills/sync-back-merge/SKILL.md +66 -0
  128. package/.cursor/skills/tenant-management/SKILL.md +172 -188
  129. package/.cursor/skills/utils-toolkit/SKILL.md +214 -222
  130. package/.cursor/skills/websocket-sse/SKILL.md +251 -172
  131. package/.cursor/skills/workflow-engine/SKILL.md +178 -250
  132. package/.cursor/skills/yunxiao-task-management/SKILL.md +489 -0
  133. package/AGENTS.md +49 -540
  134. package/CLAUDE.md +73 -119
  135. package/README.md +37 -6
  136. package/bin/index.js +611 -25
  137. package/package.json +1 -1
  138. package/src/platform-map.json +4 -0
  139. package/src/skills/api-development/SKILL.md +179 -130
  140. package/src/skills/architecture-design/SKILL.md +102 -212
  141. package/src/skills/backend-annotations/SKILL.md +166 -220
  142. package/src/skills/bug-detective/SKILL.md +225 -186
  143. package/src/skills/code-patterns/SKILL.md +127 -244
  144. package/src/skills/codex-code-review/SKILL.md +261 -69
  145. package/src/skills/collaborating-with-codex/SKILL.md +96 -113
  146. package/src/skills/crud-development/SKILL.md +226 -307
  147. package/src/skills/data-permission/SKILL.md +131 -202
  148. package/src/skills/database-ops/SKILL.md +158 -355
  149. package/src/skills/error-handler/SKILL.md +224 -285
  150. package/src/skills/file-oss-management/SKILL.md +174 -169
  151. package/src/skills/git-workflow/SKILL.md +123 -341
  152. package/src/skills/json-serialization/SKILL.md +121 -137
  153. package/src/skills/leniu-report-customization/SKILL.md +82 -2
  154. package/src/skills/leniu-report-standard-customization/SKILL.md +65 -2
  155. package/src/skills/loki-log-query/SKILL.md +400 -0
  156. package/src/skills/loki-log-query/environments.json +45 -0
  157. package/src/skills/mysql-debug/SKILL.md +58 -22
  158. package/src/skills/performance-doctor/SKILL.md +83 -89
  159. package/src/skills/redis-cache/SKILL.md +134 -185
  160. package/src/skills/scheduled-jobs/SKILL.md +187 -224
  161. package/src/skills/security-guard/SKILL.md +168 -276
  162. package/src/skills/skill-creator/LICENSE.txt +202 -0
  163. package/src/skills/skill-creator/SKILL.md +479 -0
  164. package/src/skills/skill-creator/agents/analyzer.md +274 -0
  165. package/src/skills/skill-creator/agents/comparator.md +202 -0
  166. package/src/skills/skill-creator/agents/grader.md +223 -0
  167. package/src/skills/skill-creator/assets/eval_review.html +146 -0
  168. package/src/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  169. package/src/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  170. package/src/skills/skill-creator/references/schemas.md +430 -0
  171. package/src/skills/skill-creator/scripts/__init__.py +0 -0
  172. package/src/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  173. package/src/skills/skill-creator/scripts/generate_report.py +326 -0
  174. package/src/skills/skill-creator/scripts/improve_description.py +248 -0
  175. package/src/skills/skill-creator/scripts/package_skill.py +136 -0
  176. package/src/skills/skill-creator/scripts/quick_validate.py +103 -0
  177. package/src/skills/skill-creator/scripts/run_eval.py +310 -0
  178. package/src/skills/skill-creator/scripts/run_loop.py +332 -0
  179. package/src/skills/skill-creator/scripts/utils.py +47 -0
  180. package/src/skills/sms-mail/SKILL.md +266 -228
  181. package/src/skills/social-login/SKILL.md +257 -195
  182. package/src/skills/sync-back-merge/SKILL.md +66 -0
  183. package/src/skills/tenant-management/SKILL.md +172 -188
  184. package/src/skills/utils-toolkit/SKILL.md +214 -222
  185. package/src/skills/websocket-sse/SKILL.md +251 -172
  186. package/src/skills/workflow-engine/SKILL.md +178 -250
  187. package/src/skills/yunxiao-task-management/SKILL.md +489 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: redis-cache
3
3
  description: |
4
- 当需要使用Redis缓存、分布式锁、限流等功能时自动使用此Skill。包含RedisUtils工具类、CacheUtils工具类、缓存注解使用规范、分布式锁实现、缓存key命名规范等。
4
+ 当需要使用Redis缓存、分布式锁、限流等功能时自动使用此Skill。包含 Redisson API、Spring Cache 注解使用规范、分布式锁实现、缓存key命名规范等。
5
5
 
6
6
  触发场景:
7
7
  - 使用Redis缓存数据
@@ -12,265 +12,245 @@ description: |
12
12
  - 缓存key设计和命名
13
13
  - 缓存清理和刷新
14
14
 
15
- 触发词:Redis、缓存、Cache、@Cacheable、@CacheEvict、@CachePut、RedisUtils、CacheUtils、分布式锁、RLock、限流、RateLimiter、发布订阅、缓存key、缓存过期
15
+ 触发词:Redis、缓存、Cache、@Cacheable、@CacheEvict、@CachePut、Redisson、分布式锁、RLock、限流、RateLimiter、发布订阅、缓存key、缓存过期
16
16
 
17
17
  核心警告:
18
18
  - @Cacheable返回值不能使用不可变集合(List.of()、Set.of()、Map.of())
19
- - 分布式锁必须在finally中释放,且需注入RedissonClient(RedisUtils无getLock)
20
- - keys()和deleteKeys()会忽略租户隔离
19
+ - 分布式锁必须在finally中释放,且需注入RedissonClient
21
20
  ---
22
21
 
23
22
  # Redis 缓存开发指南
24
23
 
25
- > 模块位置:`ruoyi-common/ruoyi-common-redis`
26
-
27
24
  ## 快速索引
28
25
 
29
26
  | 功能 | 工具类/注解 | 说明 |
30
27
  |------|-------------|------|
31
- | 对象缓存 | `RedisUtils.setCacheObject()` | 基于 Redisson |
32
- | 集合缓存 | `RedisUtils.setCacheList/Set/Map()` | List/Set/Map 操作 |
33
- | Spring Cache | `CacheUtils.get/put/evict()` | Spring Cache 封装 |
34
- | 缓存注解 | `@Cacheable/@CachePut/@CacheEvict` | 声明式缓存 |
28
+ | 对象缓存 | `RedissonClient` / `[你的RedisUtils]` | 基于 Redisson |
29
+ | Spring Cache | `@Cacheable/@CachePut/@CacheEvict` | 声明式缓存 |
35
30
  | 分布式锁 | `redissonClient.getLock()` | 需注入 RedissonClient |
36
- | 限流控制 | `RedisUtils.rateLimiter()` | 基于 Redisson |
37
- | 原子操作 | `RedisUtils.incrAtomicValue()` | 原子递增/递减 |
38
- | 发布订阅 | `RedisUtils.publish/subscribe()` | 消息通信 |
31
+ | 限流控制 | Redisson `RRateLimiter` | 基于 Redisson |
32
+ | 原子操作 | Redisson `RAtomicLong` | 原子递增/递减 |
33
+ | 发布订阅 | Redisson `RTopic` | 消息通信 |
39
34
 
40
35
  ---
41
36
 
42
- ## 一、RedisUtils 工具类
43
-
44
- ```java
45
- import org.dromara.common.redis.utils.RedisUtils;
46
- ```
37
+ ## 一、Redisson 基础操作
47
38
 
48
39
  ### 1.1 基础缓存操作
49
40
 
50
41
  ```java
51
- RedisUtils.setCacheObject("user:123", userObj); // 永不过期
52
- RedisUtils.setCacheObject("user:123", userObj, Duration.ofMinutes(30)); // 带过期时间
53
- RedisUtils.setCacheObject("user:123", userObj, true); // 保留原有TTL(Redis 6.0+)
54
- boolean ok = RedisUtils.setObjectIfAbsent("user:123", userObj, Duration.ofMinutes(30)); // 不存在时设置
55
- boolean ok = RedisUtils.setObjectIfExists("user:123", userObj, Duration.ofMinutes(30)); // 存在时设置
56
-
57
- User user = RedisUtils.getCacheObject("user:123"); // 获取
58
- long ttl = RedisUtils.getTimeToLive("user:123"); // TTL毫秒(-1永不过期,-2不存在)
59
- boolean deleted = RedisUtils.deleteObject("user:123"); // 删除
60
- RedisUtils.deleteObject(Arrays.asList("user:123", "user:456")); // 批量删除
61
- boolean exists = RedisUtils.isExistsObject("user:123"); // 是否存在
62
- RedisUtils.expire("user:123", Duration.ofMinutes(30)); // 设置过期
42
+ import org.redisson.api.RedissonClient;
43
+ import org.redisson.api.RBucket;
44
+
45
+ @Service
46
+ @RequiredArgsConstructor
47
+ public class CacheService {
48
+
49
+ private final RedissonClient redissonClient;
50
+
51
+ // 设置缓存
52
+ public void set(String key, Object value, Duration ttl) {
53
+ RBucket<Object> bucket = redissonClient.getBucket(key);
54
+ bucket.set(value, ttl);
55
+ }
56
+
57
+ // 获取缓存
58
+ public <T> T get(String key) {
59
+ RBucket<T> bucket = redissonClient.getBucket(key);
60
+ return bucket.get();
61
+ }
62
+
63
+ // 删除缓存
64
+ public boolean delete(String key) {
65
+ return redissonClient.getBucket(key).delete();
66
+ }
67
+
68
+ // 判断是否存在
69
+ public boolean exists(String key) {
70
+ return redissonClient.getBucket(key).isExists();
71
+ }
72
+
73
+ // 不存在时设置(原子操作)
74
+ public boolean setIfAbsent(String key, Object value, Duration ttl) {
75
+ RBucket<Object> bucket = redissonClient.getBucket(key);
76
+ return bucket.trySet(value, ttl);
77
+ }
78
+ }
63
79
  ```
64
80
 
65
81
  ### 1.2 集合操作
66
82
 
67
83
  ```java
68
84
  // List
69
- RedisUtils.setCacheList("myList", dataList);
70
- RedisUtils.addCacheList("myList", "item3");
71
- List<String> result = RedisUtils.getCacheList("myList");
72
- List<String> range = RedisUtils.getCacheListRange("myList", 0, 10);
85
+ RList<String> list = redissonClient.getList("myList");
86
+ list.addAll(dataList);
87
+ List<String> result = list.readAll();
73
88
 
74
89
  // Set
75
- RedisUtils.setCacheSet("mySet", dataSet);
76
- boolean added = RedisUtils.addCacheSet("mySet", "value3");
77
- Set<String> result = RedisUtils.getCacheSet("mySet");
90
+ RSet<String> set = redissonClient.getSet("mySet");
91
+ set.addAll(dataSet);
92
+ Set<String> result = set.readAll();
78
93
 
79
94
  // Map
80
- RedisUtils.setCacheMap("myMap", dataMap);
81
- RedisUtils.setCacheMapValue("myMap", "key3", "value3");
82
- String value = RedisUtils.getCacheMapValue("myMap", "key1");
83
- Map<String, Object> result = RedisUtils.getCacheMap("myMap");
84
- Set<String> keys = RedisUtils.getCacheMapKeySet("myMap");
85
- RedisUtils.delCacheMapValue("myMap", "key1");
86
- RedisUtils.delMultiCacheMapValue("myMap", new HashSet<>(Arrays.asList("key1", "key2")));
87
- Map<String, Object> values = RedisUtils.getMultiCacheMapValue("myMap", keySet);
95
+ RMap<String, Object> map = redissonClient.getMap("myMap");
96
+ map.putAll(dataMap);
97
+ map.put("key3", "value3");
98
+ Object value = map.get("key1");
88
99
  ```
89
100
 
90
101
  ### 1.3 发布订阅
91
102
 
92
103
  ```java
93
- RedisUtils.publish("notification:channel", messageObj);
94
- RedisUtils.publish("notification:channel", messageObj, msg -> { log.info("已发布: {}", msg); });
95
- RedisUtils.subscribe("notification:channel", MessageDTO.class, msg -> { /* 处理消息 */ });
104
+ // 发布消息
105
+ RTopic topic = redissonClient.getTopic("notification:channel");
106
+ topic.publish(messageObj);
107
+
108
+ // 订阅消息
109
+ RTopic topic = redissonClient.getTopic("notification:channel");
110
+ topic.addListener(MessageDTO.class, (channel, msg) -> {
111
+ // 处理消息
112
+ });
96
113
  ```
97
114
 
98
115
  ### 1.4 限流控制
99
116
 
100
117
  ```java
118
+ import org.redisson.api.RRateLimiter;
101
119
  import org.redisson.api.RateType;
120
+ import org.redisson.api.RateIntervalUnit;
102
121
 
122
+ RRateLimiter limiter = redissonClient.getRateLimiter("api:limit:user:" + userId);
103
123
  // 每10秒最多100个请求
104
- long remaining = RedisUtils.rateLimiter("api:limit:user:123", RateType.OVERALL, 100, 10);
105
- if (remaining == -1) {
106
- throw new ServiceException("请求过于频繁");
107
- }
124
+ limiter.trySetRate(RateType.OVERALL, 100, 10, RateIntervalUnit.SECONDS);
108
125
 
109
- // 带超时版本(5秒超时)
110
- long remaining = RedisUtils.rateLimiter("api:limit:user:123", RateType.OVERALL, 100, 10, 5);
126
+ if (!limiter.tryAcquire()) {
127
+ throw new [你的异常类]("请求过于频繁");
128
+ }
111
129
  ```
112
130
 
113
131
  ### 1.5 原子操作
114
132
 
115
133
  ```java
116
- RedisUtils.setAtomicValue("counter:view", 0L);
117
- long value = RedisUtils.getAtomicValue("counter:view");
118
- long newVal = RedisUtils.incrAtomicValue("counter:view");
119
- long newVal = RedisUtils.decrAtomicValue("counter:view");
134
+ RAtomicLong counter = redissonClient.getAtomicLong("counter:view");
135
+ counter.set(0L);
136
+ long value = counter.get();
137
+ long newVal = counter.incrementAndGet();
138
+ long newVal = counter.decrementAndGet();
120
139
  ```
121
140
 
122
- ### 1.6 Key 操作
141
+ ---
123
142
 
124
- ```java
125
- // ⚠️ keys() 和 deleteKeys() 会忽略租户隔离
126
- Collection<String> keys = RedisUtils.keys("user:*");
143
+ ## 二、Spring Cache 注解使用规范
127
144
 
128
- KeysScanOptions options = KeysScanOptions.defaults().pattern("user:*").chunkSize(1000).limit(100);
129
- Collection<String> keys = RedisUtils.keys(options);
145
+ ### @Cacheable - 查询缓存
130
146
 
131
- RedisUtils.deleteKeys("temp:*");
132
- Boolean exists = RedisUtils.hasKey("user:123");
147
+ ```java
148
+ @Cacheable(value = "dictData", key = "#dictType")
149
+ @Override
150
+ public List<DictDataVo> listDictDataByType(String dictType) {
151
+ if (dictType == null || dictType.isBlank()) {
152
+ return Collections.emptyList();
153
+ }
154
+ List<DictData> dictDataList = dictDataMapper.selectByType(dictType);
155
+ if (dictDataList.isEmpty()) {
156
+ return Collections.emptyList(); // 返回空列表防止缓存穿透
157
+ }
158
+ return dictDataList.stream()
159
+ .map(d -> BeanUtil.copyProperties(d, DictDataVo.class))
160
+ .toList();
161
+ }
133
162
  ```
134
163
 
135
- ### 1.7 监听机制
164
+ ### @CachePut / @CacheEvict
165
+
166
+ ```java
167
+ @CachePut(value = "dictData", key = "#bo.dictType")
168
+ public List<DictDataVo> insertDictType(DictTypeBo bo) { ... }
136
169
 
137
- 详见 [references/listeners.md](references/listeners.md)
170
+ @CacheEvict(value = "dictData", key = "#dictType")
171
+ public void deleteDictType(String dictType) { ... }
138
172
 
139
- ---
173
+ @CacheEvict(value = "dictData", allEntries = true)
174
+ public void clearAllDictCache() { ... }
175
+ ```
140
176
 
141
- ## 二、CacheUtils 工具类
177
+ ### 返回值禁止使用不可变集合
142
178
 
143
179
  ```java
144
- import org.dromara.common.redis.utils.CacheUtils;
180
+ // ❌ 禁止! @Cacheable 返回值序列化失败
181
+ return List.of(data1, data2);
182
+ return Set.of("admin", "user");
183
+ return Map.of("key1", "value1");
145
184
 
146
- CacheUtils.put("userCache", "user:123", userObj); // 保存
147
- User user = CacheUtils.get("userCache", "user:123"); // 获取
148
- CacheUtils.evict("userCache", "user:123"); // 删除
149
- CacheUtils.clear("userCache"); // 清空整组
185
+ // 正确:使用可变集合
186
+ List<DictDataVo> result = new ArrayList<>();
187
+ result.add(data1);
188
+ return result;
150
189
  ```
151
190
 
152
191
  ---
153
192
 
154
- ## 三、CacheNames 缓存名称常量
193
+ ## 三、CacheNames 命名规范
155
194
 
156
- > 位置:`ruoyi-common/ruoyi-common-core/.../constant/CacheNames.java`
157
-
158
- ### 命名格式
195
+ ### 推荐格式
159
196
 
160
197
  ```
161
- cacheNames#ttl#maxIdleTime#maxSize#local
198
+ cacheNames#ttl#maxIdleTime#maxSize
162
199
  - ttl: 过期时间(0=不过期,默认0)
163
200
  - maxIdleTime: 最大空闲时间(0=不检测,默认0)
164
201
  - maxSize: 最大条数(0=无限,默认0)
165
- - local: 本地缓存(1开启,0关闭,默认1)
166
202
  ```
167
203
 
168
204
  ```java
169
205
  "test#60s" // 60秒过期
170
206
  "test#0#60s" // 不过期,60秒空闲清理
171
207
  "test#0#1m#1000" // 不过期,1分钟空闲,最大1000条
172
- "test#1h#0#500#0" // 1小时过期,最大500条,关闭本地缓存
208
+ "test#1h#0#500" // 1小时过期,最大500
173
209
  ```
174
210
 
175
- ### 已定义常量
211
+ ### 常量定义示例
176
212
 
177
213
  ```java
178
214
  public interface CacheNames {
179
- String DEMO_CACHE = "demo:cache#60s#10m#20";
180
215
  String SYS_CONFIG = "sys_config";
181
216
  String SYS_DICT = "sys_dict";
182
- String SYS_DICT_TYPE = "sys_dict_type";
183
- String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d";
184
- String SYS_CLIENT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_client#30d";
185
217
  String SYS_USER_NAME = "sys_user_name#30d";
186
- String SYS_NICKNAME = "sys_nickname#30d";
187
218
  String SYS_DEPT = "sys_dept#30d";
188
- String SYS_OSS = "sys_oss#30d";
189
- String SYS_ROLE_CUSTOM = "sys_role_custom#30d";
190
- String SYS_DEPT_AND_CHILD = "sys_dept_and_child#30d";
191
- String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config";
192
- String ONLINE_TOKEN = "online_tokens";
193
219
  }
194
220
  ```
195
221
 
196
222
  ---
197
223
 
198
- ## 四、缓存注解使用规范
224
+ ## 四、分布式锁
199
225
 
200
- ### @Cacheable - 查询缓存
201
-
202
- ```java
203
- @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
204
- @Override
205
- public List<SysDictDataVo> listDictDataByType(String dictType) {
206
- if (StringUtils.isBlank(dictType)) {
207
- return Collections.emptyList();
208
- }
209
- List<SysDictData> dictDataList = dictDataMapper.selectByType(dictType);
210
- if (CollUtil.isEmpty(dictDataList)) {
211
- return Collections.emptyList(); // 返回空列表防止缓存穿透
212
- }
213
- return MapstructUtils.convert(dictDataList, SysDictDataVo.class);
214
- }
215
- ```
216
-
217
- ### @CachePut / @CacheEvict
218
-
219
- ```java
220
- @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#bo.dictType")
221
- public List<SysDictDataVo> insertDictType(SysDictTypeBo bo) { ... }
222
-
223
- @CacheEvict(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
224
- public void deleteDictType(String dictType) { ... }
225
-
226
- @CacheEvict(cacheNames = CacheNames.SYS_DICT, allEntries = true)
227
- public void clearAllDictCache() { ... }
228
- ```
229
-
230
- ### 返回值禁止使用不可变集合
231
-
232
- ```java
233
- // ❌ 禁止!@Cacheable 返回值序列化失败
234
- return List.of(data1, data2);
235
- return Set.of("admin", "user");
236
- return Map.of("key1", "value1");
237
-
238
- // ✅ 正确:使用可变集合
239
- List<SysDictDataVo> result = new ArrayList<>();
240
- result.add(data1);
241
- return result;
242
- ```
243
-
244
- ---
245
-
246
- ## 五、分布式锁
247
-
248
- > RedisUtils **不提供** `getLock()`,需直接注入 `RedissonClient`。
226
+ > 直接注入 `RedissonClient` 使用。
249
227
 
250
228
  ```java
251
229
  @Service
252
230
  @RequiredArgsConstructor
253
- public class OrderServiceImpl implements IOrderService {
231
+ public class OrderServiceImpl {
254
232
 
255
233
  private final RedissonClient redissonClient;
256
234
 
257
235
  public void submitOrder(OrderBo orderBo) {
258
- String lockKey = "lock:submit:order:" + LoginHelper.getUserId();
236
+ String lockKey = "lock:submit:order:" + orderBo.getUserId();
259
237
  RLock lock = redissonClient.getLock(lockKey);
260
238
 
261
239
  try {
262
240
  boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
263
241
  if (!locked) {
264
- throw new ServiceException("请勿重复提交订单");
242
+ throw new [你的异常类]("请勿重复提交订单");
265
243
  }
266
244
  try {
267
245
  orderMapper.insert(orderBo);
268
246
  } finally {
269
- lock.unlock(); // 必须在 finally 中释放
247
+ if (lock.isLocked() && lock.isHeldByCurrentThread()) {
248
+ lock.unlock(); // 必须在 finally 中释放
249
+ }
270
250
  }
271
251
  } catch (InterruptedException e) {
272
252
  Thread.currentThread().interrupt();
273
- throw new ServiceException("订单提交被中断");
253
+ throw new [你的异常类]("订单提交被中断");
274
254
  }
275
255
  }
276
256
  }
@@ -278,7 +258,7 @@ public class OrderServiceImpl implements IOrderService {
278
258
 
279
259
  ---
280
260
 
281
- ## 六、缓存 Key 命名规范
261
+ ## 五、缓存 Key 命名规范
282
262
 
283
263
  ```
284
264
  格式:{业务模块}:{功能}:{具体标识}
@@ -292,42 +272,11 @@ limit:api:user:123 limit:sms:18888888888
292
272
 
293
273
  ---
294
274
 
295
- ## 七、租户隔离注意
296
-
297
- ```java
298
- // ⚠️ keys() 和 deleteKeys() 会忽略租户隔离,需手动拼接
299
- String tenantId = LoginHelper.getTenantId();
300
- Collection<String> keys = RedisUtils.keys(tenantId + ":user:*");
301
-
302
- // CacheUtils 会自动处理租户隔离
303
- CacheUtils.clear(CacheNames.SYS_USER_NAME);
304
- ```
305
-
306
- ---
307
-
308
- ## 八、注意事项速查
275
+ ## 六、注意事项速查
309
276
 
310
277
  1. **@Cacheable 返回值不能使用不可变集合**(List.of()、Set.of()、Map.of())
311
278
  2. **分布式锁必须在 finally 中释放**
312
- 3. **keys() 和 deleteKeys() 会忽略租户隔离**
313
- 4. **返回空列表而不是 null**,防止缓存穿透
314
- 5. **设置随机过期时间偏移**,避免缓存雪崩
315
- 6. **热点数据用分布式锁 + 双重检查**,防止缓存击穿
316
-
317
- ---
318
-
319
- ## 九、核心文件位置
320
-
321
- | 文件 | 位置 |
322
- |------|------|
323
- | RedisUtils | `ruoyi-common/ruoyi-common-redis/.../utils/RedisUtils.java` |
324
- | CacheUtils | `ruoyi-common/ruoyi-common-redis/.../utils/CacheUtils.java` |
325
- | CacheNames | `ruoyi-common/ruoyi-common-core/.../constant/CacheNames.java` |
326
- | GlobalConstants | `ruoyi-common/ruoyi-common-core/.../constant/GlobalConstants.java` |
327
-
328
- ---
329
-
330
- ## 多项目适配说明
331
-
332
- - 如果需要 leniu-tengyun-core 项目的 Redis 开发规范,请使用 `leniu-redis-cache` skill
333
- - leniu-tengyun-core 的 RedisUtil 工具类方法名与 RuoYi-Vue-Plus 的 RedisUtils 不同
279
+ 3. **返回空列表而不是 null**,防止缓存穿透
280
+ 4. **设置随机过期时间偏移**,避免缓存雪崩
281
+ 5. **热点数据用分布式锁 + 双重检查**,防止缓存击穿
282
+ 6. **keys() 模式匹配要谨慎**,生产环境避免大范围扫描