springboot中最优雅的时间处理方式

209 阅读1分钟

在开发中经常会遇到前端传时间字符串,后端又是时间对象。然后就转来转去非常麻烦。接的时候string到date.回去的时候date->string.

你也许会想到一个优雅的方式。

@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")

但是我们还可以更优雅点,和这个注解配合。就是使用一个转换器

package com.lar.config;  
  
import com.fasterxml.jackson.core.JacksonException;  
import com.fasterxml.jackson.core.JsonGenerator;  
import com.fasterxml.jackson.core.JsonParser;  
import com.fasterxml.jackson.databind.DeserializationContext;  
import com.fasterxml.jackson.databind.JsonDeserializer;  
import com.fasterxml.jackson.databind.JsonSerializer;  
import com.fasterxml.jackson.databind.ObjectMapper;  
import com.fasterxml.jackson.databind.SerializerProvider;  
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;  
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;  
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;  
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;  
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;  
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;  
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;  
import lombok.SneakyThrows;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.context.annotation.Primary;  
  
import java.io.IOException;  
import java.text.SimpleDateFormat;  
import java.time.LocalDate;  
import java.time.LocalDateTime;  
import java.time.LocalTime;  
import java.time.format.DateTimeFormatter;  
import java.util.Date;  
  
@Configuration  
public class TimeFormatConvert {  
    @Bean  
    @Primary  
    public ObjectMapper objectMapper() {  
        // 序列化为时间字符串给前端,和前端时间字符串反序列化为日期对象  
        ObjectMapper objectMapper = new ObjectMapper();  
        JavaTimeModule javaTimeModule = new JavaTimeModule();  

        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(TimeFormat.DateTime)));  
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(TimeFormat.Date)));  
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TimeFormat.Time)));  
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(TimeFormat.DateTime)));  
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(TimeFormat.Date)));  
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TimeFormat.Time)));  

        javaTimeModule.addSerializer(Date.class, new DateSerializer());  
        javaTimeModule.addDeserializer(Date.class, new DateDeserializer());  

        objectMapper.registerModule(javaTimeModule);  
        return objectMapper;  
    }  

    public interface TimeFormat {  
        String DateTime = "yyyy-MM-dd HH:mm:ss";  
        String Date = "yyyy-MM-dd";  
        String Time = "HH:mm:ss";  
    }  

    public static class DateSerializer extends JsonSerializer<Date> {  
        @Override  
        public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {  
            SimpleDateFormat formatter = new SimpleDateFormat(TimeFormat.DateTime);  
            formatter.setLenient(true);  
            formatter.setTimeZone(TimeZone.getDefault());
            String formattedDate = formatter.format(date);  
            jsonGenerator.writeString(formattedDate);  
        }  
    }  

    public static class DateDeserializer extends JsonDeserializer<Date> {  
        @SneakyThrows  
        @Override  
        public Date deserialize(JsonParser p, DeserializationContext deserializationContext) {  
            if (p.getText() == null || "".equals(p.getText().trim())) {  
                return null;  
            }  
            SimpleDateFormat formatter = new SimpleDateFormat(TimeFormat.DateTime);  
            formatter.setLenient(true);  
            formatter.setTimeZone(TimeZone.getDefault());  
            if(p.getText().length()<=10){  
                formatter = new SimpleDateFormat(TimeFormat.Date);  
                if (p.getText().charAt(4) != '-') {  
                    formatter = new SimpleDateFormat(TimeFormat.Time);  
                }  
            }  
            return formatter.parse(p.getText());
        }  
    }  
}

image.png

后端model还是时间对象接收

image.png

上面效果实现了传是字符串回来还是字符串。这样大部分场景你代码都不用手动改。最后建议用新的api.localdate,更加好用.这可是我研究了好久的。所有时间除了date这块比较麻烦。默认只处理全部格式的序列化,鬼知道前端要啥奇奇怪怪的格式。然后不会有人只传时分秒用date对象吧。不会吧。。