【问题标题】:storing raw json in redis by using spring-data-redis使用 spring-data-redis 将原始 json 存储在 redis 中
【发布时间】:2017-06-12 01:15:46
【问题描述】:

我正在使用 RedisCacheManager 将我的缓存数据存储在我的 spring-boot 应用程序中。默认序列化程序似乎将所有内容序列化为字节并从字节反序列化为适当的 java 类型。

但是,我想将缓存数据存储为 json,以便我可以从非 Java 客户端读取它。

我发现从默认序列化程序切换到其他序列化程序(例如 Jackson2JsonRedisSerializer)应该可以工作。执行此操作后,反序列化阶段失败。

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;
    }
}

有没有办法将它们存储为纯 JSON 格式并成功反序列化?

【问题讨论】:

    标签: java json spring serialization spring-data


    【解决方案1】:

    将此添加到您的配置中以在 redis 模板中显式设置杰克逊序列化程序。

    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;
    }
    

    【讨论】:

    • 我已经尝试过了,但是redis中的缓存数据仍然以字节为单位。喜欢"\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x01"
    • 您检查过我更新的答案吗?告诉我。
    • 如果我们使用 CrudRepository 模式来持久化数据,这不起作用吗?
    • 这可能适用于旧版本的 spring-data-redis 但它不适用于最新版本的 ATM
    【解决方案2】:

    至少从 spring-data-jpa:2.0.2.RELEASE 开始,配置默认的 redis 模板不会影响 @Cacheable 注解族如何访问 redis。 无论如何,由于我使用 redis 模板不止于此,这不是我想做的事情。

    然而,这会隔离缓存管理器的配置并按预期工作:

    @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();
        }
    
    }
    

    它使用 Redis 的通用 Json 序列化器 (GenericJackson2JsonRedisSerializer)。

    您还可以配置缓存管理器的其他方面,例如 redis 中 key 的生存时间。

    【讨论】:

      【解决方案3】:

      我通过定义 RedisConnectionFactory 设法做到了这一点

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

      然后使用 StringRedisTemplate

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

      我希望这可能会有所帮助!

      【讨论】:

      • 你是对的,如果你直接使用redisTemplate,你可以完全控制数据的进出。但是,在我的例子中,我使用了缓存注释,例如 @Cacheable@Cacheput,其中 cacheManager 使用 redisTemplate 进行缓存操作。
      猜你喜欢
      • 2018-12-16
      • 2022-08-03
      • 2021-09-13
      • 1970-01-01
      • 2019-07-07
      • 2020-09-29
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      相关资源
      最近更新 更多