spring boot 项目用jackson反序列化日期类型LocalDateTime

https://www.cnblogs.com/carrychan/p/9883172.html

问题

公司的项目是刚刚搭的,前端传“2018-09-12 08:12:12”后端反序列化就报错,因为默认Jackson反序列化是通过LocalDateTimeDeserializer的deserialize方法,但是默认的DateTimeFormatter是“yyyy-MM-ddTHH:mm:ss”,但是我传的值没有T,也就是说“2018-09-12T08:12:12”可以反序列化成功,后来通过在实体类的时间字段上加@JsonFormat来规定时间类型,这样做可以实现但是每新增一个就要做同样的操作,增加了操作冗余,再后来写了一个自定义jacksonObjectMapperBuilder规定LocalDateTime类型的序列化与反序列化器并都指定了Format,但是在我自己的项目中成功了,在公司的项目中失败了,故研究了spring boot中反序列化的底层实现。

import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Configuration
@ConditionalOnClass(JavaTimeModule.class)
public class JavaTimeAutoConfiguration {

    @Bean
    @ConditionalOnProperty("spring.jackson.date-format")
    Jackson2ObjectMapperBuilderCustomizer customizeLocalDateTimeFormat(@Value("${spring.jackson.date-format}") String dateFormat){
        return jacksonObjectMapperBuilder -> {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);

            jacksonObjectMapperBuilder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
            jacksonObjectMapperBuilder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
        };
    }
}

思路

分析springmvc解析入参,每接收到一个请求,先到达dispatcherServlet,handlerMapping把请求封装为HandlerExecutionChain对象(包括handler+handlerInterceptor),再获取HandlerAdapter适配器模式,再执行DispatcherServlet的doDispatch(),这里最核心是调adapter的handle方法,执行对应的controller的对应方法并返回一个ModelAndView对象,这里涉及入参的反序列化。

  • 执行InvocableHandlerMethod的getMethodArgumentValues获取入参的值,也就是解析入参的实参。
    HandlerMethodArgumentResolver.resolveArgument()解析参数,然后就是
    RequestResponseBodyMethodProcessor的readWithMessageConverters,
    然后就是AbstractMessageConverterMethodArgumentResolver的readWithMessageConverters泛型方法,然后是AbstractJackson2HttpMessageConverter的readJavaType(JavaType javaType, HttpInputMessage inputMessage),javaType是controller的参数类型,inputMessage就是你前端传过来的body里的参数。
    到此为止是mvc里做的事情,接下去是针对不同类型的参数,做反序列化操作了
    关键的jackson反序列化步骤如下:
    • BeanDeserializer的deserializeFromObject方法,这个方法里最关键就是获取一个SettableBeanProperty prop,这个prop根据当前这个参数的字段名称获取,具体看源码为BeanPropertyMap的find(String key)方法,prop 包含了反序列化器,也就是这个反序列化器获取不正确才导致了日期类型解析一直失败。我目前还没有找到反序列化器为什么没有获取到我自定义的那个。

下午重新创建了一个spring boot项目,配置上面贴出的代码,生效了,所以问题还是定位中。

如果也遇到过类似问题的朋友,或者有思路的朋友,请留言,或者微信联系我(15026969417),谢谢。
https://www.cnblogs.com/carrychan/p/9883172.html 开始时候的链接。

你可能感兴趣的:(spring,framework,java基础)