Some problems encountered in integrating Redis with Springboot

The Springboot integration of redis is actually very simple. Just add the redis starter dependency to the project.

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

But in the process of integration, there are some inexplicable problems.

It may be because the springboot version is too high. The version number is 2.7.0.

1 automatic assembly of redisTemplate failed

First, the redisTemplate automatically injected by Spring cannot be found.

Check the autoconfiguration about redis in springboot.

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> type bean s already exist when redistemplate<object> is configured. Assembly should not fail even if it is not serialized.

Forced operation without error reporting and smooth implementation.

It can be judged that the injection should be successful, and the error reason should be the reason of idea. Idea cannot find the bean creation declaration because the bean was created by the springboot runtime.

This error can be ignored or injected with the @Resource annotation.

Enable the debug log output of springboot.

logging:
  level:
    root: debug

When the project is started, check the creation of 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)

It can be seen that the two bean instances of RedisAutoConfiguration are successfully created. Therefore, it can be further confirmed that the above error is caused by idea.

2 the customized redisConfig does not take effect.

The redisTemplate automatically injected by springboot is not serialized. It uses the default JDK serialization. When any value is stored, there will be garbled code.

For example, use the default redisTemplate to store key value pairs {'xcc','123'}.

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

The final effect in redis is as follows.

The prefix \xAC\xED\x00\x05t\x00\x03 appears before the key and value, which does not meet the expectation when using redis. This is because the default JDK serializer is used.

At the same time, when we use redis, we usually use redistemplate<string, object> type, which needs to be created manually. At the same time, we also need to serialize the data during storage, which can be done together.

The manual configuration of Redis is as follows.

@Configuration
public class RedisConfig {

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

        //jackson serializer
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //This method is deprecated
        //om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //String serializer
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //Serialization mode of key and hashkey
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        //Serialization of value and hashvalue
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        return template;
    }
}

There is also an error report.

Similar to the previous error reports, it is preliminarily suspected that idea was the cause.

Directly execute the test method, report an error, and prompt that the redistemplate<string, object> type bean cannot be found.

Break the point in the customized redisConfig code and find that it has not been implemented, indicating that the customized redisConfig has not taken effect.

The final solution: inherit the RedisAutoConfiguration class.

After inheritance, all problems will be solved, and redisConnectionFactory can also access it without reporting errors.

 

Tags: Java Redis Spring Boot

Posted by ashrust on Mon, 30 May 2022 06:56:42 +0530