• Redis 在Springboot 中反序列化 LocalDateTime 时报错


    最近使用了 JDK8 中新的时间 API LocalDateTime,中间使用了Redis作为缓存,发现 Springboot 默认使用的 Jackson 无法正确序列化 LocalDateTime,究其原因是 Jackson 在序列化 LocalDateTime 时输出的不是普通的字符串时间格式,而是如下所示的格式

    "createTime":{
        "date":			{"year":2020,"month":"FEBRUARY","day":4,"dayOfWeek":"TUESDAY","era":"CE","dayOfYear":35,"leapYear":true,"monthValue":2,"dayOfMonth":4,
                         "chronology":{"id":"ISO","calendarType":"iso8601"},"prolepticMonth":24241
               }
    

    而普通时间格式是:2019-02-27 12:10:17。

    以下是抛出的异常:

    2020-11-02 22:08:15.606 ERROR 2992 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with 
    path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot
     construct instance of `java.time.LocalDateTime` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based
     Creator)
     at [Source: (byte[])"["java.util.ArrayList",[["cn.duniqb.mall.tiny.modules.ums.model.UmsResource",{"id":1,"createTime":{"date":
    {"year":2020,"month":"FEBRUARY","day":4,"dayOfWeek":"TUESDAY","era":"CE","dayOfYear":35,"leapYear":true,"monthValue":2,"dayOfMonth":4,"chronology":
    {"id":"ISO","calendarType":"iso8601"},"prolepticMonth":24241},"time":
    {"hour":17,"minute":4,"second":55,"nano":0},"month":"FEBRUARY","dayOfWeek":"TUESDAY","dayOfYear":35,"nano":0,"year":2020,"monthValue":2,"dayOfMonth":4,"hour":17,"minu
    te":4,"secon"[truncated 17976 bytes]; line: 1, column: 100] (through reference chain: java.util.ArrayList[0]-
    >cn.duniqb.mall.tiny.modules.ums.model.UmsResource["createTime"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct
     instance of `java.time.LocalDateTime` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
    

    所以是原因是 Jackson 序列化 LocalDateTime 跟我们所预想的不一致,将注册给 Redis 的序列化模板修改成以下就行。

        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisSerializer<Object> serializer = redisSerializer();
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(factory);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(serializer);
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashValueSerializer(serializer);
            redisTemplate.afterPropertiesSet();
    
            // 下面代码解决LocalDateTime序列化与反序列化不一致问题
            Jackson2JsonRedisSerializer<Object> j2jrs = new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            // 解决jackson2无法反序列化LocalDateTime的问题
            objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
            j2jrs.setObjectMapper(objectMapper);
            // 序列化 value 时使用此序列化方法
            redisTemplate.setValueSerializer(j2jrs);
            redisTemplate.setHashValueSerializer(j2jrs);
    
            return redisTemplate;
        }
    

    这样使用就不会出错了。

    没有修不好的电脑
  • 相关阅读:
    求两条链表有无交点和第一个交点
    重载自增运算符(前置自增++p和后置自增p++)
    二叉排序树和平衡二叉树
    红黑树
    java学习攻略
    Intellij IDEA / IntelliJ
    ngrinder test
    eclipsejeekeplerSR2win32x86_64 jsonedit plugin
    向叶子文文的.net之路学习(大量的转载)
    微软发布机制(转)从浅入深
  • 原文地址:https://www.cnblogs.com/duniqb/p/13917062.html
Copyright © 2020-2023  润新知