Spring Boot LocalDateTime序列化反序列

在项目中,实际的例子是:用户触发password changed event,listener 执行update password事件,创建producer。随后通过RabbitMQ Direct Exchange的方式发送数据给queue队列,consumer端接收数据,操作数据库表。
其中环节:在Channel中发送/接收数据时,存在Java Bean 与 Message(一般为Json数据类型)的序列化与反序列化。
附加情况:Java Bean中属性声明modifyDateTime,数据类型为LocalDateTime
最终问题在于:对LocalDateTime属性的序列化与反序列化。
复现问题所在:
定义Java Bean Demo.java:
Spring Boot LocalDateTime序列化反序列_第1张图片
通过Junit Test执行程序:
Spring Boot LocalDateTime序列化反序列_第2张图片
其中,serializer打印为:

{
	"localDateTime": {
		"dayOfWeek": "MONDAY",
		"dayOfYear": 301,
		"month": "OCTOBER",
		"year": 2019,
		"monthValue": 10,
		"minute": 51,
		"second": 49,
		"nano": 848000000,
		"dayOfMonth": 28,
		"hour": 13,
		"chronology": {
			"id": "ISO",
			"calendarType": "iso8601"
		}
	}
}

这就是问题所在,在LocalDateTime属性被序列化成Json Object,这使得没法进行反序列化处理。(我这里用的Spring Boot 2.1.6.RELEASE),在正常项目中,这种问题是不存在的,因为默认,spring boot在转换过程中给我们提供了DeserializerSerializer
题外,简单地查看@ResponseBody注解的实现:
Spring RequestResponseBodyMethodProcessor handles return values from methods annotated with @ResponseBody by writing to the body of the response with an HttpMessageConverter.
通过Http Request Header Accept指定类型,查找当前response converter,在这里就不多解释这个问题了,抛一篇好文,觉得解释得挺到位(https://www.cnblogs.com/java-chen-hao/p/11187914.html )
对于Json类型,采用了HttpMessageConverter实现类MappingJackson2HttpMessageConverter,通过MappingJackson2HttpMessageConverter给我们提供了ObjectMapper,查看其中的build()# configue(mapper)#registerWellKnownModulesIfAvailable(modulesToRegister) 从中可以看到,

com.fasterxml.jackson.datatype.jsr310.JavaTimeModule

将该模块添加至ObjectMapper中,查看JavaTimeModule源码发现:

addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);

这正是我们所需要的。所以,基于Spring Boot的默认机制,已经实现了对LocalDateTime属性的JSON序列化和反序列化实现。
紧接着上个话题,我通过Junit Test复现问题,在代码中,我们创建了一个新的ObjectMapper实例,在这种情况下,没有对mapper进行注册JavaTimeModule模块。

接下来,尝试声明JavaTimeModule unit test:
Spring Boot LocalDateTime序列化反序列_第3张图片
序列化结果为:

{"localDateTime":[2019,10,29,1,8,26,191000000]}

也可以通过addSerializer方法加入你想要的或者自定义的序列化实现方式:
Spring Boot LocalDateTime序列化反序列_第4张图片
结果为:

{"localDateTime":"2019-10-29T12:43:49.272"}

另外,还可以定义输出的日期格式:
Spring Boot LocalDateTime序列化反序列_第5张图片
输出结果为:

{"localDateTime":"2019-10-29 12:54:25"}

在项目中,通过xml配置或注解方式进行声明:
对于注解方式:
在Java Bean的该属性声明时,加注@JsonSerialize(指定序列化方式), @JsonDeserialize(指定反序列化方式),@JsonFormat(指定格式):
Spring Boot LocalDateTime序列化反序列_第6张图片
对于xml配置方式,主要是对MappingJackson2HttpMessageConverter创建ObjectMapper实例,通过继承ObjectMapper自定义CustomObjectMapper,通过构造器方法将需要注册的module添加到mapper中:
Spring Boot LocalDateTime序列化反序列_第7张图片
Spring Boot LocalDateTime序列化反序列_第8张图片
其实本质上是对mapper进行添加注册所需的module模块类,通过这种方式,引入我们所需的(反)序列化的方式。当然,对于通过xml配置这种方式对于spring boot本身是没有将注解的方式发挥完整,这个就属于另外一个知识点的学习总结了。

你可能感兴趣的:(Spring Boot LocalDateTime序列化反序列)