2

我有一个 Redisson 客户端来存储一对字符串 LocalDateTime。它被配置为通过 JCache API (JSR-107) 使用。

存储完成,使用 Jackson 转换为类似但检索的值不使用任何转换器并返回字符串,在调用2018-01-23T11:59:34.997834中给出 ClassCastException 。cache#get

我在这里想念什么?

@Test
public void getCacheInline() {
    Config redissonCfg = new Config();
    redissonCfg
        .setCodec(new JsonJacksonCodec(buildObjectMapper()))
        .useSingleServer()
        .setAddress("redis://redis:6379");

    MutableConfiguration<String, LocalDateTime> jcacheConfig = new MutableConfiguration<String, LocalDateTime>()
        .setTypes(String.class, LocalDateTime.class)
        .setExpiryPolicyFactory((Factory<ExpiryPolicy>) () -> new CreatedExpiryPolicy(new Duration(SECONDS, 100)));

    Configuration<String, LocalDateTime> configuration = RedissonConfiguration.fromConfig(redissonCfg, jcacheConfig);


    Cache<String, LocalDateTime> cache = cacheManager.createCache(CACHE_NAME, configuration);
    LocalDateTime expectedDateTime = LocalDateTime.now();
    cache.put("testKey", expectedDateTime);

    // In this line: java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.time.LocalDateTime
    LocalDateTime actualDateTime = cache.get("testKey");
    assertThat(actualDateTime, is(equalTo(expectedDateTime)));
}

private ObjectMapper buildObjectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    objectMapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.configure(WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
    objectMapper.setSerializationInclusion(NON_NULL);
    return objectMapper;
}
4

1 回答 1

2

最初的解决方法不是存储 pair String, LocalDateTime,而是将 LocalDateTime 包装在包装类中:

public class LocalDateTimeWrapper {
    private LocalDateTime value;
    ...
}

这将使 Jackson 序列化一个带有@class指示 LocalDateTimeWrapper 类的属性的 json 字符串,并且可以从那里检索 LocalDateTime 作为反序列化字符串的类型2018-01-23T11:59:34.997834

我尝试过并为我工作的更好的解决方案是 GitHub 问题https://github.com/redisson/redisson/issues/1260#issuecomment-367272400中建议的一个,它像这样扩展 JsonJacksonMapCodec:

public static class ExtendedJsonJacksonMapCodec extends JsonJacksonMapCodec {

    public ExtendedJsonJacksonMapCodec() {
        super(String.class, LocalDateTime.class);
    }

    @Override
    protected void init(ObjectMapper objectMapper) {
        objectMapper.registerModule(new JavaTimeModule());
        super.init(objectMapper);
    }

}

然后像这样从配置链接它(YAML 格式):

singleServerConfig:
    address: "redis://localhost:6379"
codec: !<com.example.ExtendedJsonJacksonMapCodec> {}
于 2018-02-28T15:00:41.263 回答