spring cache 支持多结构的 Redis 缓存管理器

需求背景:spring cache 使用多级缓存,缓存实现方式用redis时,默认存储的结构是string,结果,但项目中需要使用其他结果,于是想到自己定义一个实现类,然后根据类型进行切换不同的实现方式,于是乎有了下面多结构缓存管理器,核心方法是createRedisCache

复制代码
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import java.util.Map;
import java.util.Objects;

/**
 * 支持多结构的 Redis 缓存管理器
 * 可根据缓存名前缀自动选择缓存结构(Hash/ZSet/普通字符串)
 */
public class StructRedisCacheManager extends RedisCacheManager {

    // 缓存结构类型枚举
    public enum CacheStructType {
        HASH,   // Hash 结构
        ZSET,   // ZSet 结构
        STRING  // 普通字符串结构(默认)
    }

    // 结构前缀(用于标识缓存类型,例如 "hash:userCache" 表示 Hash 结构)
    private static final String HASH_PREFIX = "hash:";
    private static final String ZSET_PREFIX = "zset:";

    private final RedisConnectionFactory connectionFactory;
    // 各结构的默认配置(是否允许覆盖/重复)
    private final boolean hashAllowOverwrite;  // Hash 是否允许覆盖
    private final boolean zsetAllowDuplicate; // ZSet 是否允许重复元素

    public StructRedisCacheManager(
            RedisCacheWriter cacheWriter,
            RedisCacheConfiguration defaultCacheConfig,
            RedisConnectionFactory connectionFactory,
            boolean hashAllowOverwrite,
            boolean zsetAllowDuplicate
    ) {
        super(cacheWriter, defaultCacheConfig);
        this.connectionFactory = connectionFactory;
        this.hashAllowOverwrite = hashAllowOverwrite;
        this.zsetAllowDuplicate = zsetAllowDuplicate;
    }

    /**
     * 重载构造器(支持自定义缓存配置)
     */
    public StructRedisCacheManager(
            RedisCacheWriter cacheWriter,
            RedisCacheConfiguration defaultCacheConfig,
            Map<String, RedisCacheConfiguration> initialCacheConfigurations,
            RedisConnectionFactory connectionFactory,
            boolean hashAllowOverwrite,
            boolean zsetAllowDuplicate
    ) {
        super(cacheWriter, defaultCacheConfig, initialCacheConfigurations);
        this.connectionFactory = connectionFactory;
        this.hashAllowOverwrite = hashAllowOverwrite;
        this.zsetAllowDuplicate = zsetAllowDuplicate;
    }

    /**
     * 核心:根据缓存名选择对应的缓存结构实现
     */
    @Override
    protected RedisCache createRedisCache(String cacheName, RedisCacheConfiguration config) {
        // 解析缓存结构类型
        CacheStructType structType = parseStructType(cacheName);
        // 提取业务缓存名(去除结构前缀)
        String bizName = extractBizName(cacheName, structType);

        // 根据类型创建对应缓存实例
        switch (structType) {
            case HASH:
                // 创建 Hash 结构缓存
                return new HashRedisCache(
                        bizName,
                        getCacheWriter(),
                        config != null ? config : getDefaultCacheConfiguration(),
                        connectionFactory,
                        hashAllowOverwrite
                );
            case ZSET:
                // 创建 ZSet 结构缓存
                return new ZSetRedisCache(
                        bizName,
                        getCacheWriter(),
                        config != null ? config : getDefaultCacheConfiguration(),
                        connectionFactory,
                        zsetAllowDuplicate
                );
            default:
                // 默认使用普通字符串缓存(Spring 原生实现)
                return super.createRedisCache(bizName, config);
        }
    }

    /**
     * 解析缓存名对应的结构类型(通过前缀判断)
     */
    private CacheStructType parseStructType(String cacheName) {
        if (cacheName.startsWith(HASH_PREFIX)) {
            return CacheStructType.HASH;
        } else if (cacheName.startsWith(ZSET_PREFIX)) {
            return CacheStructType.ZSET;
        } else {
            return CacheStructType.STRING;
        }
    }

    /**
     * 提取业务缓存名(去除结构前缀)
     */
    private String extractBizName(String cacheName, CacheStructType structType) {
        switch (structType) {
            case HASH:
                return cacheName.substring(HASH_PREFIX.length());
            case ZSET:
                return cacheName.substring(ZSET_PREFIX.length());
            default:
                return cacheName;
        }
    }
}
相关推荐
咖啡八杯17 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
Flittly2 天前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
咖啡八杯3 天前
GoF设计模式——中介者模式
java·后端·spring·设计模式
Flittly4 天前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
唐青枫8 天前
Java Spring WebFlux 实战指南:用 Mono、Flux 和 WebClient 写响应式接口
java·spring
小七-七牛开发者9 天前
TokenPilot:让 LLM Agent 长会话成本降 60%+ 的上下文管理
缓存·agent·token·context·上下文·推理成本
咖啡八杯10 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
Flittly11 天前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
dunky11 天前
Spring 的三级缓存与循环依赖
后端·spring
码云数智-园园16 天前
C++20 Modules 模块详解
java·开发语言·spring