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;
        }
    }
}
相关推荐
Spring AI学习5 小时前
Spring AI深度解析(9/50):可观测性与监控体系实战
java·人工智能·spring
java1234_小锋6 小时前
Spring IoC的实现机制是什么?
java·后端·spring
小小8程序员7 小时前
Redis-10
数据库·redis·缓存
前端小端长7 小时前
Vue 中 keep-alive 组件的原理与实践详解
前端·vue.js·spring
YDS8299 小时前
SpringCould —— 网关详解
后端·spring·spring cloud
老华带你飞10 小时前
列车售票|基于springboot 列车售票系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习·spring
猿与禅11 小时前
Spring Boot 4.0 完整核心特性及实践指南
java·spring boot·后端·spring·重大升级·springboot4.0
运维@小兵11 小时前
Spring-AI系列——Tool Calling获取当前时间
java·后端·spring