问题描述
Springboot项目A服务使用restTemplate.postForObject()调用B服务的rest接口,返回的对象内有一个date类型字段,发现date类型比实际时间小了8个小时。
定位问题过程
查看B服务的日志信息,实际数据:
2018-11-05 10:56:09
返回的没有任何问题,查询A服务的日志,收到的结果是:2018-11-05 02:56:09
,比预期小了8个小时。于是在A服务中
restTemplate.postForObject()
方法debug代码,发现使用的是jackson序列化方式,继续debug定位发现jackson的配置信息类JacksonAutoConfiguration。
JacksonAutoConfiguration设置时区的代码如下:
private void configureDateFormat(Jackson2ObjectMapperBuilder builder) {
// We support a fully qualified class name extending DateFormat or a date
// pattern string value
String dateFormat = this.jacksonProperties.getDateFormat();
if (dateFormat != null) {
try {
Class<?> dateFormatClass = ClassUtils.forName(dateFormat, null);
builder.dateFormat(
(DateFormat) BeanUtils.instantiateClass(dateFormatClass));
}
catch (ClassNotFoundException ex) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
dateFormat);
// Since Jackson 2.6.3 we always need to set a TimeZone (see
// gh-4170). If none in our properties fallback to the Jackson's
// ***先读取配置文件的时区
TimeZone timeZone = this.jacksonProperties.getTimeZone();
//***如果配置文件没指定时区,则取下面值
if (timeZone == null) {
timeZone = new ObjectMapper().getSerializationConfig()
.getTimeZone();
}
simpleDateFormat.setTimeZone(timeZone);
builder.dateFormat(simpleDateFormat);
}
}
}
- 跟踪
timeZone = new ObjectMapper().getSerializationConfig() .getTimeZone();
继续找,在BaseSettings.java发现:
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
- 原来jackson在处理date类型时,如果不指定时区,则会取UTC。
解决办法
在A服务的配置文件application.properties增加配置,指定jackson使用的时区:
#指定时区为东八区
spring.jackson.time-zone=GMT+8
重新打包部署后OK。