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;
        }
    }
}
相关推荐
百锦再几秒前
Java 并发编程进阶,从线程池、锁、AQS 到并发容器与性能调优全解析
java·开发语言·jvm·spring·kafka·tomcat·maven
NGC_66112 小时前
SSM vs SpringBoot+MyBatis 对比
spring
我真会写代码4 小时前
从入门到精通:Kafka核心原理与实战避坑指南
分布式·缓存·kafka
深蓝轨迹4 小时前
@Autowired与@Resource:Spring依赖注入注解核心差异剖析
java·python·spring·注解
爱丽_5 小时前
Pinia 状态管理:模块化、持久化与“权限联动”落地
java·前端·spring
我真会写代码5 小时前
Redis高频面试题(含标准答案,覆盖基础+进阶+实战)
数据库·redis·缓存
希望永不加班6 小时前
SpringBoot 核心配置文件:application.yml 与 application.properties
java·spring boot·后端·spring
6+h6 小时前
【Redis】缓存问题及解决方案
数据库·redis·缓存
我真会写代码6 小时前
Spring面试高频题:从基础到源码,通俗拆解+避坑指南
java·spring·面试
6+h7 小时前
【Redis】高可用核心讲解
数据库·redis·缓存