日常开发中,时间格式的参数出现频率非常高,很多朋友对时间格式转换也很头疼,或者只知道如何配置,而不知道这些配置如何生效的。

今天我们来梳理一下Springboot项目中配置日期转换的三种方式,以及其大致原理。

Springboot版本:2.7.6

1,全局配置(推荐)

Spring提供了默认的jackson配置,我们只需修改Spring的默认配置,自定义对于日期参数的格式化方式即可。

新建一个配置类,构建一个自定义的ObjectMapper即可全局生效。

@Configuration
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper()
                .setLocale(Locale.CHINA)
                .setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()))
                //注册一个序列化和反序列化的module
                .registerModule(javaTimeModule())
                //配置date格式参数的解析
                .setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN))
                .setLocale(Locale.CHINA)
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .findAndRegisterModules();
    }

    @Bean
    public Module javaTimeModule() {
        JavaTimeModule module = new JavaTimeModule();
        module.addSerializer(new LocalDateTimeSerializer(
                DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)
        ));
        module.addSerializer(new LocalTimeSerializer(
                DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN))
        );
        module.addSerializer(new LocalDateSerializer(
                DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN))
        );
        module.addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(
                        DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)
                ));
        module.addDeserializer(LocalDate.class,
                new LocalDateDeserializer(
                        DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)
                ));
        module.addDeserializer(LocalTime.class,
                new LocalTimeDeserializer(
                        DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)
                ));
        return module;
    }

}

上述中的几项配置也比较简单,大家基本可以直接看出其作用,就不再一项项细说了。

另外大家可以注意到,自定义的类上使用了@AutoConfigureBefore(JacksonAutoConfiguration.class),他的目的在于提前构建ObjectMapper,这样当JacksonAutoConfiguration初始化时,使用的就是我们自定义的ObjectMapper,我们配置的格式化参数就可以生效了。

在JacksonAutoConfiguration中静态类JacksonObjectMapperConfiguration中,

spring boot时间差8小时 springboot日期_自定义

大家可以看到,当ObjectMapper已经存在时,就不会再使用Spring默认的了。

@ConditionalOnMissingBean是一个很好用的注解,大家在开发自己的组件时也可以尝试通过他实现动态的组件注册。

关于如何找到Jackson配置的启动类,有的同学可能一开始不知道如何下手。

其实很简单,我们只要知道一个类是由Spring自动配置的,那么就去Spring的autoconfigure.jar包下找就行,在org.springframework.boot.autoconfigure下面,我们可以找到Jackson的包,JacksonAutoConfiguration就在其中。

除了Jackson的配置,其他自动配置的组件也可以在autoconfigure中找到。

spring boot时间差8小时 springboot日期_自定义_02

2,通过@JsonFormat注解转换

我们也可以在一个类的属性上使用@JsonFormat达到格式化参数的目的。

@Data
public class OutputDTO {

    private String desc;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime time;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date date;
}

spring boot时间差8小时 springboot日期_spring boot时间差8小时_03

这种方式可以在需要的地方自由配置格式化方式,但是相对来说会增加许多工作,建议还是使用全局配置的方式。

3,yml配置文件自定义(不推荐)

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

需要注意的是,这种方式默认只对date生效,对于java8的LocalDate,LocalDateTime是不生效的。

对于为什么不生效感兴趣的朋友可以在JacksonAutoConfiguration的内部类Jackson2ObjectMapperBuilderCustomizerConfiguration中的customize.configureDateFormat方法中找到答案。

感谢您的点赞和关注。