springboot3 + redis 缓存整合 支持@Cacheable 设置Json序列化,并支持按缓存设置缓存时间

springboot3默认的整合下,缓存时间未指定(默认永不失效),且序列化方式为Jdk的Serializable序列化方式,使用起来略有不便。Serializable序列化方式在序列化ID有变化,或者未指定序列化ID时,类的字段一变化,就会报错反序列化失败。

下面是一个可以指定指定缓存时间,指定默认缓存时间,并且使用JSON序列化方式的集成代码。

引入依赖

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

设置默认的RedisTemplate

如果项目中是直接使用RedisTmplate来进行缓存的,需要指定RestTemplate的序列化方式,代码如下:

java 复制代码
@UtilityClass
public class JacksonJsonSerializerUtil {
    public static GenericJackson2JsonRedisSerializer getJackson2JsonRedisSerializer() {
        var jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        jackson2JsonRedisSerializer.configure(objectMapper -> {
            // add java8 time module
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.activateDefaultTyping(new LaissezFaireSubTypeValidator(),
                    ObjectMapper.DefaultTyping.EVERYTHING);
            JavaTimeModule javaTimeModule = new JavaTimeModule();
            objectMapper.registerModule(javaTimeModule);
        });
        return jackson2JsonRedisSerializer;
    }
}
java 复制代码
    @Bean("redisTemplate")
    RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        var jackson2JsonRedisSerializer = JacksonJsonSerializerUtil.getJackson2JsonRedisSerializer();

        // 设置value的序列化规则和key的序列化规则
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

设置@Cacheable的序列化方式

@Cacheable不使用RedisTemplate,因此上面的定义是无效的,它直接使用CacheManager,因此我们需要自定义。spring提供了自定义的RedisCacheManagerBuilderCustomizer来支持自定义,我们实现它,并将它注入到spring容器中就可以了。

java 复制代码
public class MyRedisCacheManagerBuilderSerialCustomizer implements RedisCacheManagerBuilderCustomizer {
    @Override
    public void customize(RedisCacheManager.RedisCacheManagerBuilder builder) {
        RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();

        var jackson2JsonRedisSerializer = getJackson2JsonRedisSerializer();
        var configuration = builder.cacheDefaults()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));

        builder.cacheDefaults(configuration);
        var configuredCaches = builder.getConfiguredCaches();

        // 针对有的缓存存在自定义配置的情况,读取所有缓存的配置,设置序列化方法
        for (String configuredCache : configuredCaches) {
            var cacheConfig = builder.getCacheConfigurationFor(configuredCache);
            cacheConfig.ifPresent(config -> {
                var newConfig = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
                builder.withCacheConfiguration(configuredCache, newConfig);
            });
        }
    }
}
java 复制代码
// 注入到spring容器中
    @Bean
    MyRedisCacheManagerBuilderSerialCustomizer myRedisCacheManagerBuilderSerialCustomizer() {
        return new MyRedisCacheManagerBuilderSerialCustomizer();
    }

自定义缓存的过期时间,以及默认过期时间

我们自定义一个配置来支持设置过期时间,配置如下:

yaml 复制代码
myservice:
  redis:
    # 采用ISO-8601时间格式。格式为:PnDTnHnMnS   (n为个数)
    #例如:P1Y2M3DT4H5M6.7S = 1年2个月3天4小时5分钟6.7秒
    default-expire-time: PT30M
    cache-and-expires:
      - cache-name: test
        expire-time: PT10M
java 复制代码
@Data
public class CacheAndExpire {
    private String cacheName;
    private Duration expireTime;
}
java 复制代码
@Slf4j
public class MyRedisCacheManagerBuilderCustomizer implements RedisCacheManagerBuilderCustomizer {
    private final MyRedisConfig myRedisConfig;

    public MyRedisCacheManagerBuilderCustomizer(MyRedisConfig myRedisConfig) {
        this.myRedisConfig = myRedisConfig;
    }

    @Override
    public void customize(RedisCacheManager.RedisCacheManagerBuilder builder) {
        log.info("my redis expire-time config!");
        var configuration = builder.cacheDefaults()
                .entryTtl(myRedisConfig.getDefaultExpireTime());

        builder.cacheDefaults(configuration);

        log.info("my redis expire-time cacheAndExpire has {} configs!", myRedisConfig.getCacheAndExpires().size());
        for (CacheAndExpire cacheAndExpire : myRedisConfig.getCacheAndExpires()) {
            var cacheConfig = builder.getCacheConfigurationFor(cacheAndExpire.getCacheName()).orElse(configuration);
            builder.withCacheConfiguration(cacheAndExpire.getCacheName(), cacheConfig.entryTtl(cacheAndExpire.getExpireTime()));
        }
    }
}

将bean注入到Spring容器中

java 复制代码
@EnableConfigurationProperties({MyRedisConfig.class})
public class RedisConfig {

    @Bean
    MyRedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer(MyRedisConfig myRedisConfig) {
        return new MyRedisCacheManagerBuilderCustomizer(myRedisConfig);
    }
}
相关推荐
特立独行的猫a27 分钟前
redis客户端库redis++在嵌入式Linux下的交叉编译及使用
linux·数据库·c++·redis·redis客户端库
Pasregret1 小时前
缓存与数据库一致性深度解析与解决方案
数据库·缓存·wpf
大家都说我身材好2 小时前
Spring缓存注解深度实战:3大核心注解解锁高并发系统性能优化‌
spring·缓存·性能优化
爱吃泡芙的小白白2 小时前
爬虫学习——使用HTTP服务代理、redis使用、通过Scrapy实现分布式爬取
redis·分布式·爬虫·http代理·学习记录
纪元A梦2 小时前
Redis最佳实践——性能优化技巧之监控与告警详解
数据库·redis·性能优化
沉迷...4 小时前
详解.vscode 下的json .vscode文件夹下各个文件的作用
ide·vscode·json
hnlucky5 小时前
redis 数据类型新手练习系列——Hash类型
数据库·redis·学习·哈希算法
Pasregret6 小时前
多级缓存架构深度解析:从设计原理到生产实践
缓存·架构
AnsenZhu6 小时前
2025年Redis分片存储性能优化指南
数据库·redis·性能优化·分片
李菠菜7 小时前
非SpringBoot环境下Jedis集群操作Redis实战指南
java·redis