1.统一处理前端传入时间戳
1.使用 LocalDateDeserializer 对前端传入的时间戳格式进行统一反序列成 LocalDate
/**
* 扩展jackson反序列, 使其支持时间戳转LocalDate
*
* @author: mxj
*/
public class LocalDateExtDeserializer extends LocalDateDeserializer {
public LocalDateExtDeserializer() {
super(DateTimeFormatter.ISO_LOCAL_DATE);
}
public LocalDateExtDeserializer(DateTimeFormatter dtf) {
super(dtf);
}
@Override
protected JsonDeserializer<LocalDate> withDateFormat(DateTimeFormatter formatter) {
return new LocalDateExtDeserializer(formatter);
}
@Override
public LocalDate deserialize(JsonParser parse, DeserializationContext context) throws IOException {
if (parse.hasToken(JsonToken.VALUE_NUMBER_INT)) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(parse.getLongValue()), ZoneId.systemDefault()).toLocalDate();
}
return super.deserialize(parse, context);
}
}
2.使用 LocalDateTimeDeserializer 对前端传输的时间戳格式进行统一反序列成 LocalDateTime 类型
/**
* 扩展jackson反序列, 使其支持时间戳转LocalDateTime
*
* @author: mxj
*/
public class LocalDateTimeExtDeserializer extends LocalDateTimeDeserializer {
public LocalDateTimeExtDeserializer() {
super(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
public LocalDateTimeExtDeserializer(DateTimeFormatter formatter) {
super(formatter);
}
@Override
protected JsonDeserializer<LocalDateTime> withDateFormat(DateTimeFormatter formatter) {
return new LocalDateTimeExtDeserializer(formatter);
}
@Override
public LocalDateTime deserialize(JsonParser parse, DeserializationContext context) throws IOException {
if (parse.hasToken(JsonToken.VALUE_NUMBER_INT)) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(parse.getLongValue()), ZoneId.systemDefault());
}
return super.deserialize(parse, context);
}
}
2.统一处理后台返回给前端时间格式问题(时间戳)
1.使用 LocalDateSerializerh 对后端接口中 LocalDate 类型返回给前端时间进行统一序列化成时间戳
package com.cell.jackson.serializer;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class LocalDateExtSerializer extends LocalDateSerializer {
private final Boolean writeDatesAsTimestamps;
public LocalDateExtSerializer(Boolean writeDatesAsTimestamps) {
super(DateTimeFormatter.ISO_LOCAL_DATE);
this.writeDatesAsTimestamps = writeDatesAsTimestamps;
}
protected LocalDateExtSerializer(LocalDateSerializer base,
Boolean useTimestamp, DateTimeFormatter dtf, JsonFormat.Shape shape, Boolean writeDatesAsTimestamps) {
super(base, useTimestamp, dtf, shape);
this.writeDatesAsTimestamps = writeDatesAsTimestamps;
}
@Override
protected LocalDateSerializer withFormat(Boolean useTimestamp, DateTimeFormatter dtf, JsonFormat.Shape shape) {
return new LocalDateExtSerializer(this, useTimestamp, dtf, shape, writeDatesAsTimestamps);
}
@Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (writeDatesAsTimestamps) {
jsonGenerator.writeNumber(localDate.atStartOfDay(ZoneOffset.systemDefault()).toInstant().toEpochMilli());
} else {
super.serialize(localDate, jsonGenerator, serializerProvider);
}
}
}
2.使用 LocalDateTimeSerializer 对后端接口中 LocalDateTime 类型返回给前端时间进行统一序列化成时间戳
package com.cell.jackson.serializer;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeExtSerializer extends LocalDateTimeSerializer {
private final Boolean writeDatesAsTimestamps;
public LocalDateTimeExtSerializer(Boolean writeDatesAsTimestamps) {
super(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
this.writeDatesAsTimestamps = writeDatesAsTimestamps;
}
protected LocalDateTimeExtSerializer(DateTimeFormatter f, Boolean writeDatesAsTimestamps) {
super(f);
this.writeDatesAsTimestamps = writeDatesAsTimestamps;
}
@Override
protected LocalDateTimeSerializer withFormat(Boolean useTimestamp, DateTimeFormatter f, JsonFormat.Shape shape) {
return new LocalDateTimeExtSerializer(f, writeDatesAsTimestamps);
}
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (writeDatesAsTimestamps) {
jsonGenerator.writeNumber(localDateTime.toInstant(OffsetDateTime.now().getOffset()).toEpochMilli());
} else {
super.serialize(localDateTime, jsonGenerator, serializerProvider);
}
}
}
3.WebMvcConfigurer 配置 RequestBody 内容转换器
1.配置好以上两步后,要在 WebMvcConfigurer 配置类中进行增加 RequestBody 内容转换器(缺点就是只针对于 Controller 层中的接中 @RequestBody 注解中的参数生效,解决方案在后头)
/**
* WebMvcConfig
*
* @author: mxj
* @Date 2023/1/28 11:29
*/
@ConditionalOnClass(WebMvcConfigurer.class)
public class WebMvcConfiguration implements WebMvcConfigurer {
/**
* 增加了Jackson对Jdk8Time的支持
*
* @param converters RequestBody内容转换器列表, 这里只需要对jackson提供的转换器进行拦截
*/
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (MappingJackson2HttpMessageConverter.class.isAssignableFrom(converter.getClass())) {
ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
SimpleModule dateModule = new SimpleModule();
//jackson序列化
dateModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
dateModule.addSerializer(LocalDate.class, new LocalDateExtSerializer(true));
dateModule.addSerializer(LocalDateTime.class, new LocalDateTimeExtSerializer(true));
//jackson反序列化, 默认的格式为 yyyy-MM-ddTHH:mm:ss, 故需要配置
dateModule.addDeserializer(LocalDate.class, new LocalDateExtDeserializer());
dateModule.addDeserializer(LocalDateTime.class, new LocalDateTimeExtDeserializer());
objectMapper.registerModule(dateModule);
}
}
}
}
4.解决掉 @PathVariable 与 @RequestParam 等注解的接收参数时间转换问题
1.以 LongLocalDateTime 为例子,利用 Converter 将前端传的时间戳格式转换为 java 对应的 LocalDateTime 对象
package com.cell.converter;
import com.cell.converter.handler.localDateTime.LocalDateTimeConverterHandler;
import com.cell.converter.handler.localDateTime.LongLocalDateTimeConverter;
import com.cell.converter.handler.localDateTime.StringLocalDateTimeConverter;
import com.cell.webExport.config.response.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
private static List<LocalDateTimeConverterHandler> localDateTimeConverterHandlerList = new ArrayList<>();
static {
localDateTimeConverterHandlerList.add(new StringLocalDateTimeConverter());
localDateTimeConverterHandlerList.add(new LongLocalDateTimeConverter());
}
@Override
public LocalDateTime convert(String source) {
for (LocalDateTimeConverterHandler item : localDateTimeConverterHandlerList) {
try {
return item.getLocalDateTime(source);
} catch (Exception e) {
log.info("LocalDateTime时间格式解释失败");
}
}
throw new BusinessException("LocalDateTime时间格式解释失败");
}
}
package com.cell.converter.handler.localDateTime;
import java.time.LocalDateTime;
public interface LocalDateTimeConverterHandler {
LocalDateTime getLocalDateTime(String source);
}
package com.cell.converter.handler.localDateTime;
import lombok.extern.slf4j.Slf4j;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@Slf4j
public class LongLocalDateTimeConverter implements LocalDateTimeConverterHandler {
@Override
public LocalDateTime getLocalDateTime(String source) {
Instant instant = Instant.ofEpochMilli(Long.parseLong(source));
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
}
package com.cell.converter.handler.localDateTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class StringLocalDateTimeConverter implements LocalDateTimeConverterHandler{
@Override
public LocalDateTime getLocalDateTime(String source) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yy-M-d ah:mm");
return LocalDateTime.parse(source, formatter);
}catch (Exception e){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return LocalDateTime.parse(source, formatter);
}
}
}
5.以上就是统一实现前后端时间格式问题(请大家多多指教)
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于