storing raw json in redis by using spring-data-red

2020-06-03 05:20发布

问题:

I am using RedisCacheManager to store my cache data in my spring-boot application. Default serializer seems to serialize everything into byte and deserialize from byte to appropriate java type.

However, I want to make the cache data be stored as json so that I can read it from none-java clients.

I found that switching from default one to other serializers such as Jackson2JsonRedisSerializer supposed to work. After doing this, deserialization phase fails.

pom.xml

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

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>

CacheConfig.java

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public RedisConnectionFactory createRedisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName("localhost");
        return factory;
    }

//    SPRING-DATA-REDIS ALREADY PROVIDES A STRING REDIS TEMPLATE, SO THE FOLLOWING IS NOT NECESSARY
//    @Bean
//    public RedisTemplate<String, String> createRedisTemplate(RedisConnectionFactory factory) {
//        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
//        redisTemplate.setConnectionFactory(factory);
//        return redisTemplate;
//    }

    @Bean
    public CacheManager redisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        return cacheManager;
    }
}

Is there a way to store them in a pure JSON format and successfully deserialize from it?

回答1:

add this in your configuration to explicitly set the jackson serializer in redis template.

public @Bean RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {

    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}


回答2:

As of spring-data-jpa:2.0.2.RELEASE at least, configuring the default redis template does not affect how the @Cacheable annotation family accesses redis. Anyway, since I'm using a redis template for more than that, it's not something I want to do.

This, however, isolates the configuration for the cache manager and works as expected:

@Configuration
@EnableCaching
public class RedisCacheManagerConfiguration {

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Bean
    public CacheManager redisCacheManager() {
        RedisSerializationContext.SerializationPair<Object> jsonSerializer = 
         RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer());
         return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory)
                .cacheDefaults(
                    RedisCacheConfiguration.defaultCacheConfig()
                            .entryTtl(Duration.ofDays(1))
                            .serializeValuesWith(jsonSerializer)
                )
                .build();
    }

}

It makes use of the generic Json serializer for Redis (GenericJackson2JsonRedisSerializer).

You can also configure other aspects of the cache manager, such as the time-to-live of the key in redis.



回答3:

I managed to make this by defining RedisConnectionFactory

@Bean
public RedisConnectionFactory jedisPool()
{
    JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(new JedisPoolConfig());
    jedisConnectionFactory.setHostName("localhost");

    return jedisConnectionFactory;
}

and then using StringRedisTemplate

ValueOperations<String, String> ops = redisTemplate.opsForValue();
ops.set("key", "Json_string");

I hope this might help!