RestTemplate使用jackson序列化的时区问题

问题描述

Springboot项目A服务使用restTemplate.postForObject()调用B服务的rest接口,返回的对象内有一个date类型字段,发现date类型比实际时间小了8个小时。


jackson.jpeg

定位问题过程

  • 查看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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容