refactor(cache): 缓存操作接口化,支持 Redis/Caffeine 双实现切换

将系统所有缓存操作从 `RedisUtil` 迁移至 `CacheOperations` 接口,
通过 `gym.cache.type` 配置选择 Redis 或 Caffeine 实现。

变更内容:
- 新增 CacheOperations 接口,定义 get/set/delete/hasKey/expire/deleteByPattern 等标准方法
- 新增 RedisCacheOperations 实现(基于 ReactiveRedisTemplate,默认实现)
- 新增 CaffeineCacheOperations 实现(基于 Caffeine 本地缓存)
- 新增 CacheProperties 配置类,支持 Caffeine 容量/过期等参数配置
- 新增 CacheAutoConfiguration 自动装配,通过 AutoConfiguration.imports 注册
- 全系统 17 个业务服务 + 18 个测试文件从 RedisUtil 迁移至 CacheOperations
- manage-gateway 配置 caffeine 实现(无需 Redis),manage-app 配置 redis 实现
- 分布式锁等 Redis 独有特性保持直接使用 ReactiveRedisTemplate

测试:202 通过,0 失败,0 错误
This commit was merged in pull request #56.
This commit is contained in:
2026-08-02 18:26:15 +08:00
parent eb33755f23
commit 4ba4af2f53
45 changed files with 798 additions and 476 deletions
@@ -3,7 +3,7 @@ package cn.novalon.gym.manage.auth.service.impl;
import cn.novalon.gym.manage.auth.config.SmsProperties;
import cn.novalon.gym.manage.auth.service.SmsService;
import cn.novalon.gym.manage.common.constant.RedisKeyConstants;
import cn.novalon.gym.manage.common.util.RedisUtil;
import cn.novalon.gym.manage.common.cache.CacheOperations;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
@@ -31,7 +31,7 @@ public class SmsServiceImpl implements SmsService {
private static final long CODE_EXPIRE_SECONDS = 300;
private final SmsProperties smsProperties;
private final RedisUtil redisUtil;
private final CacheOperations cacheOperations;
private final ObjectMapper objectMapper;
@Override
@@ -40,7 +40,7 @@ public class SmsServiceImpl implements SmsService {
String rateLimitKey = RedisKeyConstants.SMS_CODE + phone + ":rate_limit";
return redisUtil.get(rateLimitKey, Long.class)
return cacheOperations.get(rateLimitKey, Long.class)
.defaultIfEmpty(0L)
.flatMap(lastSendTime -> {
long currentTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
@@ -97,7 +97,7 @@ public class SmsServiceImpl implements SmsService {
if (verifyCodeNode != null) {
String verifyCode = verifyCodeNode.asText();
String smsCodeKey = RedisKeyConstants.SMS_CODE + phone;
redisUtil.setWithExpire(smsCodeKey, verifyCode, CODE_EXPIRE_SECONDS).subscribe();
cacheOperations.setWithExpire(smsCodeKey, verifyCode, CODE_EXPIRE_SECONDS).subscribe();
log.info("验证码已存入Redis, phone: {}, key: {}, expire: {}秒", phone, smsCodeKey, CODE_EXPIRE_SECONDS);
} else {
log.warn("响应中未找到Model.VerifyCode字段, 原始响应: {}", responseData);
@@ -106,7 +106,7 @@ public class SmsServiceImpl implements SmsService {
log.warn("响应中未找到Model字段, 原始响应: {}", responseData);
}
redisUtil.setWithExpire(rateLimitKey, currentTime, SEND_INTERVAL_SECONDS).subscribe();
cacheOperations.setWithExpire(rateLimitKey, currentTime, SEND_INTERVAL_SECONDS).subscribe();
return true;
}
@@ -180,7 +180,7 @@ public class SmsServiceImpl implements SmsService {
public Mono<String> getVerificationCode(String phone) {
try {
String cacheKey = RedisKeyConstants.SMS_CODE + phone;
return redisUtil.get(cacheKey, String.class);
return cacheOperations.get(cacheKey, String.class);
} catch (Exception e) {
log.error("获取验证码异常, phone: {}", phone, e);
return Mono.empty();