在 JDK 8 中 Date、Calendar 等类型已经不推荐使用,取而代之是全新的java.time
包,但是在实际的使用中遇到一些问题,比如 SpringCloud 在使用 java.time
包时不太方便,主要在接收前端参数、返回数据以及 feign 调用传参时
时间传递
传递时间类型数据一般就两种方式
- 时间格式的字符串
- 时间戳 (13 位数值类型)
建议在任何场景下优先考虑时间戳 (13 位数值类型),具体分析参考 微服务中时间传递的最佳实践
接收前端时间类型参数
在 Spring 中接收前端时间类型参数有以下注意点
- spring 默认使用 Jackson 作为 json 的序列化反序列化工具
- 只有前端传参使用 json 格式(Content-Type : application/json),并放在 body 体中时,sping 才会使用 Jackson 将传参反序列化成对象
- 当参数作为 url 的一部分,或者拼接在 url 后面,或者通过表单提交时,并不属于 json 格式(Content-Type : application/json),spring 不会使用 Jackson 将参数反序列化成对象,而是使用自己的解析方法转换参数
所以处理前端传递的时间类型数据时,也要两种情况
- 通过 json (Content-Type : application/json) 传递时间类型数据
- 通过其他方式传递时间类型数据
通过 json (Content-Type : application/json) 传递时间类型数据
使用这种方式传递时间类型数据时,可以通过自定义 Jackson 反序列化器,把传入的时间类型数据转换成任意类型。
以时间戳为例,把时间戳转换成 LocalDateTime ,只需要自定义一个反序列化器,比如叫 TimestampDeserializerLocalDateTime
,然后再需要转换的字段上添加 @JsonDeserialize(using = TimestampDeserializerLocalDateTime.class)
详情请参考 自定义 Jackson 序列化反序列化器
通过其他方式传递时间类型数据
主要包括
- 参数作为 url 的一部分,在 spring 中使用 @PathVariable() 来接收
- 参数以?拼接在 url 后面,一般是 get 请求
- 参数通过表单提交,多见于 post 请求
这种需要走 Spring 自己的解析方法,我们可以通过 @bean 的方式,覆盖默认的方法
例如将时间戳转换成 LocalDateTime
package com.cusc.its.bussinessservicezx.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
@Configuration
public class LocalDateTimeConfig {
@Bean
public Formatter<LocalDateTime> localDateTimeFormatter() {
return new Formatter<LocalDateTime>() {
@Override
public LocalDateTime parse(String text, Locale locale) {
return Instant
.ofEpochMilli(Long.parseLong(text))
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}
@Override
public String print(LocalDateTime object, Locale locale) {
return DateTimeFormatter.ISO_DATE.format(object);
}
};
}
}
返回时间类型的数据给前端
怎么接收前端传递的时间类型数据说完了,现在说下怎么返回时间类型的数据。
没有特殊说明的情况下,后端普遍都是返回 json 格式的数据给前端,java的对象类型会被 Jackson 序列化成 json。
虽然常用的类 Jackson 都提供了对应的序列化器,但有时候序列化的结果并不是我们需要的。这时候我们就需要根据返回的数据格式,自定义自己的序列化器。
返回的数据格式
返回时间类型的数据,一般也是两种格式
- 时间格式的字符串
- 时间戳 (13 位数值类型)
同样,建议优先选择时间戳 (13 位数值类型)
自定义序列化器
假设字段类型为 LocalDateTime 要返回的时间类型为时间戳,则我们需要定义一个 LocalDateTime转时间戳的序列化器,具体操作和使用参考 自定义 Jackson 序列化反序列化器