SpringBoot日期格式化處理(單獨與全局)

SpringBoot日期格式化處理(單獨與全局)

包括單獨,與全局

1. 單獨配置

1.1 使用Springboot提供註解方式

springboot默認提供,在需要的字段上使用@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")

這個方式每個字段都需要加有點過於麻煩。

1.2. 使用Spring自帶註解

@DateTimeFormat(pattern = "yyyy-MM-dd")

這個方式每個字段都需要加有點過於麻煩。

2. 全局配置

2.1 在配置文件上配置

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
  • 支持(content-type=application/json)請求中格式爲yyyy-MM-dd HH:mm:ss的字符串,後臺用@RequestBody接收,及返回值date轉爲yyyy-MM-dd HH:mm:ss格式string;

  • 不支持(content-type=application/json)請求中yyyy-MM-dd等類型的字符串轉爲date;

  • 不支持java8日期api

2.2 使用配置類方式

適合前後端都是json格式交互。

只需要用@Configuration定義一個配置類,注入兩個Bean即可完成全局日期響應格式化處理。

@Configuration
public class LocalDateTimeSerializerConfig {

    /** 注入配置文件格式化的格式 
    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;*/
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     *  註冊響應json格式的LocalDateTime日期格式序列化器,指定格式
     *
     * @return LocalDateTimeSerializer
     * @author: zhihao
     * @date: 2020/4/14
     */
    @Bean
    public LocalDateTimeSerializer localDateTimeSerializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

    /** 
     *  註冊json請求方式的LocalDateTime反序列化器,指定格式
     *
     * @return LocalDateTimeDeserializer 
     * @author: zhihao
     * @date: 2020/4/14 
     */
    @Bean
    public LocalDateTimeDeserializer localDateTimeDeserializer() {
        return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

    /**
     *  格式化日期類型,響應對應格式化日期字符串
     *
     * @return Jackson2ObjectMapperBuilderCustomizer
     * @author: zhihao
     * @date: 2020/4/14
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            //返回json格式,前端序列化爲字符串
            builder.serializerByType(LocalDateTime.class, localDateTimeSerializer());
            //從json對象日期字符串反序列化爲日期對象
            builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
        };
    }
}

上面方式如果需要其他格式,那就需要配合@JsonFormat註解使用,在特定的字段屬性添加@JsonFormat註解即可,因爲@JsonFormat註解優先級比較高,會以@JsonFormat註解標註的時間格式爲主。

2.3.使用Jackson解決

JSON請求的序列化和響應Json的反序列化, 適合前後端都是json格式交互。

根據官方文檔 Custom JSON Serializers and Deserializers ,想要接管Jackson的JSON的序列化和反序列化,只需通過註解@JsonComponent來聲明其靜態內部類即可。

首先根據項目要求提供自定義的日期序列化器和反序列化器,其中包括:

  • DateJsonSerializer extends JsonSerializer 表示將LocalDateTime格式化爲日期字符串。

  • DateJsonDeserializer extends JsonDeserializer 表示將日期字符串解析爲LocalDateTime日期。

    使用註解@JsonComponent是直接處理String和LocalDateTime的相互轉換的,所以要注意空串問題。

@JsonComponent
public class DateFormatConfig {

    /**
     * 響應json日期格式化
     */
    public static class DateJsonSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            jsonGenerator.writeString(localDateTime.format(formatter));
        }
    }

    /**
     * 解析json請求日期字符串
     */
    public static class DateJsonDeserializer extends JsonDeserializer<LocalDateTime> {

        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            return LocalDateTime.parse(jsonParser.getText());
        }
    }
}

2.4 GET請求及POST表單日期時間字符串格式轉換

這種情況要和時間作爲Json字符串時區別對待,因爲前端json轉後端entity底層使用的是Json序列化Jackson工具(HttpMessageConverter<T>);而時間字符串作爲普通請求參數傳入時,轉換用的是Converter<S, T>,兩者在處理方式上是有區別。

非json請求的轉換

使用自定義參數轉換器(Converter)

實現 org.springframework.core.convert.converter.Converter,自定義參數轉換器,如下:

@Configuration
public class DateConverterConfig {
    
    private static final String YYYY_MM_DD = "yyyy-MM-dd";
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    
   /** 
     * 自定義類型轉換,HTTP請求日期字符串轉換日期類型,
     * 相當於以前設置進 ConversionServiceFactoryBean
     *
     * @return Converter<java.lang.String,java.util.Date>
     * @author: zhihao
     * @date: 2020/4/14 
     */
    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                try {
                    return parse(source);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                throw new RuntimeException("日期解析錯誤");
            }
        };
    }

    /**
     * 根據字符串進行解析,將Date轉LocalDateTime
     *
     * @param source 日期字符串
     * @return java.time.LocalDateTime
     * @author: zhihao
     * @date: 2020/4/14
     */
    public LocalDateTime parse(String source) throws ParseException {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        DateFormat format;
        source = source.trim();
        //判斷是否yyyy-MM-dd格式
        if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
            format = new SimpleDateFormat(YYYY_MM_DD);
            Date date = format.parse(source);
            return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
            //判斷是否yyyy-MM-dd HH:mm:ss格式
        }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
            format = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
            Date date = format.parse(source);
            return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        }else {
            throw new IllegalArgumentException("Invalid false value " + source);
        }
    }
}

點評:以上兩個bean會注入到spring mvc的參數解析器(好像叫做ParameterConversionService),當傳入的字符串要轉爲LocalDateTime類時,spring會調用該Converter對這個入參進行轉換。

參考了:

https://www.jianshu.com/p/f4654d251104

https://segmentfault.com/a/1190000022355979

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章