Springboot整合Redis其实很简单,只要在项目中添加redis的starter依赖就可以了。

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

但在整合过程中,出现了一些莫名其妙的问题。

可能是由于springboot版本太高的原因,版本号2.7.0。

1 redisTemplate自动装配失败

首先是Spring自动注入的redisTemplate找不到。

 检查springboot中的关于redis的autoconfiguration。

public class RedisAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		return new StringRedisTemplate(redisConnectionFactory);
	}

}

其中已经配置了RedisTemplate<Object,Object>类型的bean是已经存在的。即使没有经过序列化,但不应该装配失败。

强行运行,尽然没有报错,顺利执行。

可以判断出,注入应该是成功的,报错原因应该是idea的原因。idea寻找不到bean的创建声明,因为该bean是springboot运行阶段创建的。

这个报错可以不用理会,或者是使用@Resource注解进行注入。

开启springboot的debug日志输出。

logging:
  level:
    root: debug

在项目启动时,查看redisTemplate的创建情况。

RedisAutoConfiguration#redisTemplate matched:
      - @ConditionalOnSingleCandidate (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found a single bean 'redisConnectionFactory'; @ConditionalOnMissingBean (names: redisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)

RedisAutoConfiguration#stringRedisTemplate matched:
      - @ConditionalOnSingleCandidate (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found a single bean 'redisConnectionFactory'; @ConditionalOnMissingBean (types: org.springframework.data.redis.core.StringRedisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)

可以看出,RedisAutoConfiguration 的两个bean实例是创建成功的。因此,进一步可以确认上面的报错是idea产生的。

2 自定义redisConfig不生效。

springboot自动注入的redisTemplate是没有经过序列化处理的,它使用的是默认的JDK序列化处理。在存储任意值时,会出现乱码情况。

例如,使用默认的redisTemplate存储键值对{'xcc','123'}。

redisTemplate.opsForValue().set("xcc","123");

而在redis中最终呈现的效果如下。

在键与值之前都出现了\xAC\xED\x00\x05t\x00\x03前缀,这并不符合使用redis时的期望。这是因为使用的默认的JDK序列化器造成的。

同时,我们在使用redis时,通常使用的是RedisTemplate<String,Object>类型,这需要我们手动创建。同时,我们也需要在存储时,对数据进行序列化处理,这些可以一起进行。

Redis的手动配置如下。

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> myRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        //jackson序列化器
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //该方法已弃用
        //om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //字符串序列化器
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //key与hashkey的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        //value与hashvalue的序列化方式
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        return template;
    }
}

 其中又有报错。

 与之前的报错类似,初步怀疑还是idea造成的。

直接执行测试方法,报错,提示找不到RedisTemplate<String, Object>类型的bean。

在自定义的RedisConfig 代码中打断点,发现并没有执行,说明自定义的redisConfig并没有生效。

最后的解决方案:继承RedisAutoConfiguration类。

继承之后,所有问题迎刃而解,redisConnectionFactory 也能访问到不报错了。

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐