springboot集成redis使用@Cacheable存入值,但redisTemplate取值时始终为null

项目场景:

springboot2.x集成了redis时,使用@Cacheable注解进行缓存,同时自定义了一个RedisUtils(使用到了自定义的RedisTemplate)方便获取缓存值


问题描述:

单独使用缓存注解时可以正常存取值,单独使用RedisUtils也可以正常存取值,但通过注解存值,RedisUtils获取值时始终为null


原因分析:

有两点原因:

  1. RedisUtils中的RedisTemplate并不是配置时注入的bean(因为SpringBoot中也提供了RedisTemplate),这样可能会造成拿不到值的情况(不常见)
  2. RedisTemplate和RedisCacheManager序列化方式不一样,这个问题需要明确@Cacheable和RedisTemplate调用的方式(下面有提到),在配置中如果两个类序列化的方式不一样,那么混用时也就拿不到数据
  • @Cacheable是spring cache提供的,实现方式也是通过CacheManager进行缓存的读写
  • RedisTemplate则是springboot提供的一个关于读写redis数据的类

解决方案:

针对第一个原因,可以在自定义RedisTemplate时添加一个@Primary注解,这样就相当于告诉spring容器,如果容器中有多个RedisTemplate,这个自定义的RedisTemplate需要优先被取出,例如:

@Bean
@Primary
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(factory);

    // 使用GenericToStringSerializer来序列化和反序列化redis的key
    GenericToStringSerializer<String> stringGenericToStringSerializer = new GenericToStringSerializer<>(String.class);
    redisTemplate.setKeySerializer(stringGenericToStringSerializer);
    redisTemplate.setHashKeySerializer(stringGenericToStringSerializer);
    redisTemplate.setStringSerializer(stringGenericToStringSerializer);

    // 使用FastJsonRedisSerializer来序列化和反序列化redis的值
    FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
    redisTemplate.setValueSerializer(fastJsonRedisSerializer);
    redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);

    return redisTemplate;
}

针对第二点原因,只要保证RedisTemplate和CacheManager序列化方式一样即可,最保险的写法如下:

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * redisTemplate相关
     */
    @Bean("customRedisTemplate")
    @Primary
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);

        // 使用GenericToStringSerializer来序列化和反序列化redis的key
        GenericToStringSerializer<String> stringGenericToStringSerializer = new GenericToStringSerializer<>(String.class);
        redisTemplate.setKeySerializer(stringGenericToStringSerializer);
        redisTemplate.setHashKeySerializer(stringGenericToStringSerializer);
        redisTemplate.setStringSerializer(stringGenericToStringSerializer);

        // 使用FastJsonRedisSerializer来序列化和反序列化redis的值
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);

        return redisTemplate;
    }

    /**
     * 选择redis作为默认缓存工具
     */
    @Bean("redisCacheManager")
    @Primary
    @DependsOn("customRedisTemplate")
    public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
        return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(redisTemplate.getConnectionFactory())
                // 设置缓存默认永不过期
                .cacheDefaults(
                        RedisCacheConfiguration.defaultCacheConfig()
                                // 不缓存null(需要与unless = "#result == null"共同使用)
                                .disableCachingNullValues()
                                .serializeKeysWith(
                                        RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getStringSerializer()))
                                .serializeValuesWith(
                                        RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer())))
                // 配置同步修改或删除 put/evict
                .transactionAware()
                .build();
    }
}
Spring Boot是一个开发框架,它简化了使用Spring框架进行Java应用程序开发的过程。Redis是一个内存数据结构存储系统,它可以用作缓存和数据库。@Cacheable是Spring框架的注解之一,它可以用于缓存方法的返回。 要在Spring Boot中使用Redis和@Cacheable来实现缓存,首先需要配置Redis连接。可以通过在`application.properties`或`application.yml`文件中添加以下配置来完成: ```yaml spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 接下来,在需要缓存的方法上使用`@Cacheable`注解。例如,假设我们有一个名为`getUserById`的方法,用于根据用户ID获取用户信息: ```java @Service public class UserService { @Cacheable(value = "users", key = "#id") public User getUserById(Long id) { // 从数据库或其他数据源获取用户信息 return userRepository.findById(id); } } ``` 在上述示例中,`@Cacheable`注解用于将方法的返回缓存起来。其中,`value`属性指定了缓存的名称,`key`属性指定了缓存的键。在这个例子中,缓存的名称为"users",缓存的键为方法的参数id。 最后,需要在Spring Boot应用程序的启动类上添加`@EnableCaching`注解来启用缓存功能: ```java @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 以上就是使用Spring Boot、Redis和@Cacheable实现缓存的基本步骤。通过配置Redis连接,使用`@Cacheable`注解来标记需要缓存的方法,并在启动类上添加`@EnableCaching`注解来启用缓存功能,可以轻松地实现缓存功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值