需求
使用接口时,入参和返参的时间格式都是时间戳。接口内部用Date,LocalDateTime,LocalDate接收。本文不做原理解析。
例如
@PostMapping("/test/{pathDate}")
public Result<LocalDate> dateTest(@RequestParam LocalDate date,
@RequestParam LocalDateTime dateTime,
@RequestParam Date originalDate,
@PathVariable("pathDate") LocalDateTime datePath,
LocalDate localDate,
@RequestBody Person person,
Person person2) {
System.out.println(date);
System.out.println(dateTime);
System.out.println(originalDate);
System.out.println(localDate);
System.out.println(datePath);
System.out.println(person);
System.out.println(person2);
//返回结果
return Result.ok(LocalDate.now());
}
@Data
public class Person {
String name;
Date birth1;
LocalDateTime birth2;
LocalDate birth3;
}
@Data
public class Result<T>
{
public static final int SUCCESS = 200;
public static final int ERROR = 500;
private long timestamp;
private String message;
private int code;
private T data;
public Result(final int code, final String message, final T data) {
this.timestamp = System.currentTimeMillis();
this.code = code;
this.message = message;
this.data = data;
}
public Result() {
}
public Result(T data) {
this.timestamp = System.currentTimeMillis();
this.data = data;
}
public static Result ok() {
Result result = new Result<>();
result.setTimestamp(System.currentTimeMillis());
result.setCode(200);
result.setMessage("success");
return result;
}
public static <T> Result<T> ok(T data) {
Result<T> result = new Result<>(data);
result.setTimestamp(System.currentTimeMillis());
result.setCode(200);
result.setMessage("success");
result.setData(data);
return result;
}
public static <T> Result<T> error(int code, String message) {
Result result = new Result();
result.setTimestamp(System.currentTimeMillis());
result.setCode(code);
result.setMessage(message);
return result;
}
public static <T> Result<T> error(String message) {
Result result = new Result();
result.setTimestamp(System.currentTimeMillis());
result.setCode(500);
result.setMessage(message);
return result;
}
}
解决方案
按照如下的方式设置:
1. 对jackson的Date的序列化和反序列化处理
spring:
jackson:
serialization:
WRITE_DATES_AS_TIMESTAMPS: true
time-zone: GMT+8 # 时区修改为东8区
2. 对spring参数Date的序列化处理和非Date的处理
@Configuration
public class CustomDateConverterConfig {
/**
* 入参-形参、@RequestParam和@PathVariable时候-字符串转Date相关类
*/
@Component
public static class LocalDateConvert implements Converter<String, LocalDate> {
@Override
public LocalDate convert(String timestamp) {
return DateUtil.date(Long.parseLong(timestamp)).toLocalDateTime().toLocalDate();
}
}
/**
* 入参-形参、@RequestParam和@PathVariable时候-字符串转Date相关类
*/
@Component
public static class LocalDateTimeConvert implements Converter<String, LocalDateTime> {
@Override
public LocalDateTime convert(String timestamp) {
return DateUtil.date(Long.parseLong(timestamp)).toLocalDateTime();
}
}
/**
* 入参-形参、@RequestParam和@PathVariable时候-字符串转Date相关类
*/
@Component
public static class DateConvert implements Converter<String, Date> {
@Override
public Date convert(String timestamp) {
return DateUtil.date(Long.parseLong(timestamp)).toJdkDate();
}
}
/**
* 反序列化LocalDateTime
*/
@Component
public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
Long timestamp = p.getLongValue();
Instant instant = Instant.ofEpochMilli(timestamp);
return LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
}
}
/**
* 序列化LocalDateTime为时间戳
*/
@Component
public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(value.toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
}
}
/**
* 反序列化LocalDate
*/
@Component
public static class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
Long timestamp = p.getLongValue();
Instant instant = Instant.ofEpochMilli(timestamp);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
LocalDate localDate = localDateTime.toLocalDate();
return localDate;
}
}
/**
* 序列化LocalDate为时间戳
*/
@Component
public static class LocalDateSerializer extends JsonSerializer<LocalDate> {
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(value.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
}
}
/**
* Json序列化和反序列化转换器,用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json
*/
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
//不显示为null的字段
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 忽略不能转移的字符
objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
// 过滤对象的null属性.
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//忽略transient
objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
//LocalDateTime系列序列化和反序列化模块,继承自jsr310,我们在这里修改了日期格式
JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDateTime
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
// LocalDate
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
}
测试结果
请求数据
POST http://localhost:8080/test/1651929101123?date=1651929101123&localDate=1651929101123&dateTime=1651929101123&originalDate=1651929101123&name=test&birth1=1651929101123&birth2=1651929101123
Content-Type: application/json
{
"name": "test",
"birth1": 1651929101123,
"birth2": 1651929101123,
"birth3": 1651929101123
}
返回结果
{
"timestamp": 1651929035396,
"message": "success",
"code": 200,
"data": 1651852800000
}