springboot 全局配置时间格式化

springboot 全局配置时间格式化

web项目中,后台服务返回给前端的时间格式若未配置,则返回的数据可能是时间戳或者数组,例子如下:

entity 类型LocalDateTime

{
    "id": 5,
    "name": null,
    "age": null,
    "jsonStr": null,
    "ct": "2020-08-04T14:56:54.971"
}

entity 类型为Date,时间为时间戳

{
    "id": 5,
    "ct": 1596524214971
}

若需要显示yyyy-MM-dd HH:mm:ss时间格式时,可以在对应的属性上配置@JsonFormat注解:例如:

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

还可以支持

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

若系统内时间属性字段相对多了之后,会多次配置,也会比较麻烦,所以需要进行全局配置

若时间属性字段为Date类型时,可直接在配置文件中配置如下配置:

spring.jackson.date-formate=yyyy-MM-dd HH:mm:ss

若时间属性为JDK1.8以后的接口时,此配置就不生效了。为解决这个查看了spring-boot的实现方式。

spring-boot提供了JacksonAutoConfiguration自动配置相关类,观察源码:

private void configureDateFormat(Jackson2ObjectMapperBuilder builder) {
                String dateFormat = this.jacksonProperties.getDateFormat();
                if(dateFormat != null) {
                    try {
                        Class ex = ClassUtils.forName(dateFormat, (ClassLoader)null);
                        builder.dateFormat((DateFormat)BeanUtils.instantiateClass(ex));
                    } catch (ClassNotFoundException var6) {
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
                        TimeZone timeZone = this.jacksonProperties.getTimeZone();
                        if(timeZone == null) {
                            timeZone = (new ObjectMapper()).getSerializationConfig().getTimeZone();
                        }

                        simpleDateFormat.setTimeZone(timeZone);
                        builder.dateFormat(simpleDateFormat);
                    }
                }

            }
@ConfigurationProperties(
    prefix = "spring.jackson"
)
public class JacksonProperties {
    private String dateFormat;
}

查看源码可知,当配置spring.jackson.date-formate属性时,若配置为类路径,则初始化格式化类,进行处理。若配置的不为类路径时,采用SimpleDateFormat类进行格式化时间,而SimpleDateFormat这个类只能对Date类型的时间格式化,所以当采用JDK1.8版本以后的时间接口时,会出现配置失效的问题。

当查看JacksonAutoConfiguration源码时:

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {
	...
}

JacksonAutoConfiguration类配置了条件注解 @ConditionalOnClass依赖ObjectMapper

查看ObjectMapper源码:

public ObjectMapper registerModule(Module module) {
        this._assertNotNull("module", module);
        String name = module.getModuleName();
        if(name == null) {
            throw new IllegalArgumentException("Module without defined name");
        } else {
            Version version = module.version();
            if(version == null) {
                throw new IllegalArgumentException("Module without defined version");
            } else {
                ...

                module.setupModule(new SetupContext() {
                    ...

                    //反序列化
                    public void addDeserializers(Deserializers d) {
                        DeserializerFactory df = ObjectMapper.this._deserializationContext._factory.withAdditionalDeserializers(d);
                        ObjectMapper.this._deserializationContext = ObjectMapper.this._deserializationContext.with(df);
                    }

					...

                    //序列化
                    public void addSerializers(Serializers s) {
                        ObjectMapper.this._serializerFactory = ObjectMapper.this._serializerFactory.withAdditionalSerializers(s);
                    }
                    ...
                });
                return this;
            }
        }
    }

由源码可知,ObjectMapper类在此处定义了时间序列化相关配置,查看Module实现类JavaTimeModule

public JavaTimeModule() {
        super(PackageVersion.VERSION);
        ...
        this.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
        this.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE);
        this.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE);
        ...
        this.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
        this.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE);
        this.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE);
        ...
        this.addKeyDeserializer(LocalDateTime.class, LocalDateTimeKeyDeserializer.INSTANCE);
        this.addKeyDeserializer(LocalDate.class, LocalDateKeyDeserializer.INSTANCE);
        this.addKeyDeserializer(LocalTime.class, LocalTimeKeyDeserializer.INSTANCE);
       	...
    }

JavaTimeModule设置了LocalDateTime,LocalDate,LocalTime的默认的序列化和反序列的实现。

springboot提供了自定义ObjectMapper

/**
     * 更改jackson默认配置
     * 支持 Date和jdk8的时间操作类
     * 配置时间格式化的全局操作,允许配置优先级更高的注解@JsonFormat 当配置@JsonFormat注解时以@JsonFormat配置为主
     */
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 对于空的对象转json的时候不抛出错误
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁用遇到未知属性抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 序列化BigDecimal时不使用科学计数法输出
        objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
        //null的属性不序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 日期和时间格式化
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

备注:虽说配置了自定义的ObjectMapper,但依旧只是支持LocalDateTime,LocalDate,LocalTime类相关的配置,若系统内部还是采用Date类型,只需在配置文件中添加

spring.jackson.date-formate=yyyy-MM-dd HH:mm:ss

若需要支持LocalDateTime,LocalDate,LocalTime自定义配置,一定不能使用@EnableWebMvc注解。否则自定义配置ObjectMapper会失效。

{
 "id": 5,
 "name": null,
 "age": null,
 "jsonStr": null,
 "ct": [
     2020,
     8,
     4,
     14,
     56,
     54,
     971000000
 ]
}

自此常用类型的时间在web项目中有服务器返回给前端的的时间格式化可按照自定义格式化处理.

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值