Spring Boot Redis 将 POJO 列表存储为值

Posted

技术标签:

【中文标题】Spring Boot Redis 将 POJO 列表存储为值【英文标题】:Spring Boot Redis store a list of POJOs as values 【发布时间】:2020-09-08 14:17:47 【问题描述】:

我正在使用带有 Spring 引导的 Redis。我将字符串用作键,并将其值用作复杂 POJO 的列表。以下是我的配置:

@Configuration
@EnableCaching
@Slf4j
public class RedisCacheConfig extends CachingConfigurerSupport 

private static final long DEFAULT_CACHE_EXPIRES = 60;

@Bean
public RedisTemplate<String, Object> redisTemplate(final RedisConnectionFactory redisConnectionFactory) 
    final RedisTemplate<String, Object> template = new RedisTemplate<>();
    setRedisTemplateConfigValues(redisConnectionFactory, template);
    return template;


@Bean
public CacheManager cacheManager(final RedisConnectionFactory redisConnectionFactory) 
    Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();

    return RedisCacheManager
            .builder(redisConnectionFactory)
            .cacheDefaults(createCacheConfiguration())
            .withInitialCacheConfigurations(cacheConfigurations).build();


private static RedisCacheConfiguration createCacheConfiguration() 
    return RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofSeconds(DEFAULT_CACHE_EXPIRES));


private <T> void setRedisTemplateConfigValues(final RedisConnectionFactory redisConnectionFactory,
                                              final RedisTemplate<String, T> template) 

    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());


cahcing 工作正常,通过我的应用程序进行序列化/反序列化似乎也可以工作。但是当我使用redis-cli时,当我使用命令时我会看到以下内容 按键 *

1) "schools::ABC"

现在 ABC 键的值应该是复杂对象的列表。但是当我这样做时 获取“学校::ABC”

我得到如下奇怪字符的值:

\xac\xed\x00\x05sr\x00\x13java.util.ArrayListx\x81\xd2\x1d\x99\xc7a\x9d\x03\x00\x01I\x00\x04sizexp\x00\x00\x00\x01w\ x04\x00\x00\x00\x01sr\x00(com.example.等等....

为什么会这样?

另外,我尝试将 valueSerializer 配置中的 GenericJackson2JsonRedisSerializer 更新为 Jackson2JsonRedisSerializer。结果也不例外。

另外,我尝试获取键的类型,我得到的结果是“字符串”,所以列表被存储为字符串。

【问题讨论】:

能否指定 Spring Boot 和 Redis 版本? @RobertoManfreda Spring boot 2.1.4.RELEASE 和 Redis 来自 spring-boot-starter-data-redis 您能否发布一个复杂对象的示例,或从应用程序代码推送的任何键值对。 您可以在向缓存中添加项目的位置添加代码吗? 【参考方案1】:

您看到这些奇怪字符的原因是因为它是二进制数据。

您将 GenericJackson2JsonRedisSerializer 配置为值的序列化程序。此类在内部调用 ObjectMapper#writeValueAsBytes(...) ,顾名思义,它将您输入的值转换为字节。

这是意料之中的。 Redis 不直接支持存储 Java 对象。但是,它确实支持存储二进制数据。通过使用 Jackson,我们可以将 Java 对象转换为字节并将其存储在 Redis 中。当然反过来也可以。

【讨论】:

那么,你是说通过redis cli,没有办法看到正确的值,它总是将它们显示为字节? 好吧,如果您想查看格式化为 json 的数据,您可以将序列化程序换成输出 json、xml 或其他格式的序列化程序。 Redis 只显示您插入的内容。插入二进制数据,显示二进制数据,插入json,显示json。【参考方案2】:

您的 Redis 配置看起来不错,但您没有提及存储过程的类型。也许您必须使用另一种存储数据的方式。比如你可以试试

redisTemplate.opsForHash().put('yourKey','yourHashKey', objectValue);

【讨论】:

【参考方案3】:

您可以尝试在 cachemanager bean 中设置序列化程序,如下所示

@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) 
    RedisSerializationContext.SerializationPair<Object> jsonSerializer = RedisSerializationContext.SerializationPair
            .fromSerializer(new GenericJackson2JsonRedisSerializer());

    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .serializeValuesWith(jsonSerializer);

    return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory)
            .cacheDefaults(config).build();

这对我有用。我还可以将 redis gui 中的值视为 json

【讨论】:

以上是关于Spring Boot Redis 将 POJO 列表存储为值的主要内容,如果未能解决你的问题,请参考以下文章

使用spring boot将JSON反序列化为带有通用对象列表的POJO

Kotlin > Spring Boot > 使用路由器 DSL,POST 方法主体,无法将 JSON 转换为 POJO

来自查询的响应无法映射到 pojo 类 spring boot

Spring Boot 嵌套动态 json 请求映射到 pojo

@RequestBody 没有将 JSON 映射到 Java 对象 - Spring Boot

将 spring boot 与 redis 混合使用