SpringBoot中使用@RequestBody時如何自定義須要轉換的日期格式

SpringBoot(SpringMVC)序列化和反序列化Json時默認使用的是Jackson(例如使用@RequestBody反序列化前端傳遞過來的Json字符串時),前端

當咱們前端使用Json字符串傳遞到後臺時日期格式多是時間戳(即long類型的數字),也有多是日期字符串(如:"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss")等等。java

若是是時間戳或者是yyyy-MM-dd格式的日期,Jackson會自動識別而且轉換成功,如果yyyy-MM-dd HH:mm:ss這種格式的日期字符串的話,Jackson沒法自動轉換成Date類型。web

這裏有幾種解決方案,以下:spring

一.

咱們能夠在須要被反序列化的日期屬性上添加com.fasterxml.jackson.annotation.JsonFormat註解,以下:apache

這個註解對於Jackson序列化以及反序列化均起做用(即將日期對象序列化成Json時格式爲以上指定的格式,將Json反序列化成日期時會按照以上指定的日期格式進行解析,若日期字符串的格式不知足以上指定的格式將會直接報錯)json

二.

方法一咱們只能指定一種日期的格式,可是咱們前端可能傳遞各類類型的日期格式,這個時候咱們須要自定義Json日期轉換器,以下在日期類型的屬性上添加com.fasterxml.jackson.databind.annotation.JsonDeserialize註解,以下:mvc

其中DateJacksonConverter類是咱們自定義的日期轉換類,這時在反序列化時咱們能夠轉換多種格式的日期,DateJacksonConverter類定義以下:app

package com.flying.eurekaclient;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;

/**
 * 自定義Jackson反序列化日期類型時應用的類型轉換器,通常用於@RequestBody接受參數時使用
 */
public class DateJacksonConverter extends JsonDeserializer<Date> {
    private static String[] pattern =
            new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S",
                    "yyyy.MM.dd", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss.S",
                    "yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.S"};

    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {

        Date targetDate = null;
        String originDate = p.getText();
        if (StringUtils.isNotEmpty(originDate)) {
            try {
                long longDate = Long.valueOf(originDate.trim());
                targetDate = new Date(longDate);
            } catch (NumberFormatException e) {
                try {
                    targetDate = DateUtils.parseDate(originDate, DateJacksonConverter.pattern);
                } catch (ParseException pe) {
                    throw new IOException(String.format(
                            "'%s' can not convert to type 'java.util.Date',just support timestamp(type of long) and following date format(%s)",
                            originDate,
                            StringUtils.join(pattern, ",")));
                }
            }
        }


        return targetDate;
    }

    @Override
    public Class<?> handledType() {
        return Date.class;
    }
}

在該方法中handledType()方法能夠不用重寫。ide

三.

以上兩種方法都須要在實體類上添加註解,這種方式污染了實體類,而且要是類太多的話,添加註解是一個麻煩事,這時咱們能夠配置全局的日期類型轉換器,以下:spa

package com.flying.eurekaclient;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

@Configuration
public class ConverterConfig {
    @Bean
    public DateJacksonConverter dateJacksonConverter() {
        return new DateJacksonConverter();
    }

    @Bean
    public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean(
            @Autowired
                    DateJacksonConverter dateJacksonConverter) {
        Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();

        jackson2ObjectMapperFactoryBean.setDeserializers(dateJacksonConverter);
        return jackson2ObjectMapperFactoryBean;
    }

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
            @Autowired
                    ObjectMapper objectMapper) {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
                new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        return mappingJackson2HttpMessageConverter;
    }
}

採用這種方式咱們自定義的DateJacksonConverter必須重寫handledType()方法。

本人推薦採用方式三,這樣不用污染實體類。

如下附上方式三的xml文件配置(若沒有使用SpringBoot的話):

Tips:

1.關於使用SpringMVC接受前端傳遞過來的QueryParameter數據(即後臺使用@RequestParam接收)或者formdata數據(後臺採用@RequestParam或者直接用對象接收),

若其中存在日期數據,則能夠採用如下博客提到的方式進行日期類型的正確轉換:

http://www.javashuo.com/article/p-nipzrhvq-x.html

2.關於Jackson的基本用法參考:http://www.javashuo.com/article/p-rsmavewr-v.html

相關文章
相關標籤/搜索