我有一个Redisson客户端来存储一对String,LocalDateTime。它被配置为通过JCache API(JSR-107)使用。
存储已经完成,使用Jackson转换为2018-01-23T11:59:34.997834
之类的值,但是检索不使用任何转换器并返回String,在cache#get
调用中给出ClassCastException。
我在这里缺少什么?
@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;
}
答案 0 :(得分:1)
初始解决方法不是存储一对String, LocalDateTime
,而是将LocalDateTime包装在包装类中:
public class LocalDateTimeWrapper {
private LocalDateTime value;
...
}
这将使Jackson序列化一个json字符串,其中@class
属性用信号表示LocalDateTimeWrapper类,从那里可以检索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> {}