springboot中的resttemplate使用了jackson序列化遇到的坑
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
springboot之restTemplate学习
SpringBoot系列: RestTemplate 快速入门 - harrychinese - 博客园 (cnblogs.com)
由于springboot默认使用jackson做序列化,但是jackson序列化按照的是GMT时区的时间。中国是GTM+8小时,所以原本在中国是2020-11-28 19:00:00,序列化到前端就是2020-11-28 12:00:00
就是说北京时间晚上19点的时候,伦敦才中午12点。
解决返回前端的日期字段少了8小时,可以通过入下三种方式,
一:所有日期字段加上时区
@JsonFormat( pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8" ) private Date date;
二:springboot配置文件中统一配置
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
三:通过配置类的方式:
@Configuration public class TimeZoneConfiguration { @Bean public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8")); } }
前端的展示时间的问题解决了,但是后端的问题并没有解决,一次偶然中发现,微服务consumer调用微服务provider的时候,传过去的时间也少了8个小时。
排查后发现使用springboot的RestTemplate请求去调用服务的时候,也会进行jackson序列化,此时上面三种方式,二和三都失效了,序列化的时候都不会帮我们+8小时,
只有在每个字段上面加上时区标识才有效
timezone = "GMT+8"
调式看为什么RestTemplate的时候序列化少8小时
代码调式到这里的时候,值变了
com.fasterxml.jackson.databind.ObjectWriter#writeValue(com.fasterxml.jackson.core.JsonGenerator, java.lang.Object)
最后跟到这里来了。java.text.SimpleDateFormat#format(java.util.Date, java.lang.StringBuffer, java.text.Format.FieldDelegate)
最关键的日期字段格式化在这里
g.writeString(f.format(value));
DateFormat里面的属性如下:
calendar里面的时区,使用的是UTC(相当于GMT+0)