背景说明

一个JAVA项目,从MYSQL数据库中查询数据时,发现数据库表中显示的Date类型字段的数据,与查询出来的数据相差8小时
2020241210103808

排查过程

  1. 查看执行的SQL日志:SQL日志中显示,查询出来的数据与数据库一致
  2. 查看接口返回的数据:发现返回的数据与数据库中相差8小时

修复过程

  1. 【无效】给数据库连接添加了:serverTimezone=Asia/Shanghai
  2. 【无效】在项目的启动类main方法,添加如下的代码:TimeZone.setDefault(TimeZone.getTimeZone(“GMT+8”));
  3. 【无效】将Date类型的引入的包从:import java.util.Date; 改成 import java.sql.Date;
  4. 【有效】在对应实体类的Date类型的字段添加注解:@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)
  5. 【有效】使用全局配置:
    1
    2
    spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
    spring.jackson.time-zone=GMT+8
  6. 【有效】配置全局的Jackson ObjectMapper
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    import com.fasterxml.jackson.databind.ObjectMapper;

    import com.fasterxml.jackson.databind.SerializationFeature;

    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;

    import java.text.SimpleDateFormat;

    import java.util.TimeZone;

    @Configuration

    public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper() {

    ObjectMapper objectMapper = new ObjectMapper();

    // 设置日期格式_

    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    // 设置时区_

    objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));

    // 注册JavaTimeModule以支持Java 8日期和时间API_

    objectMapper.registerModule(new JavaTimeModule());

    // 禁用时间戳_

    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

    return objectMapper;

    }

    }

分析原因

java默认使用UTC时间,而大多数数据库(如MySQL)在中国地区通常设置为东八区(GMT+8)。因此,当Java从数据库中读取时间时,如果没有正确设置时区,就会出现时间差异。

因此在spring项目中,Jackson在处理日期和时间时,需要指定对应的时区