springboot接收Date類型數據異常與解決辦法


默認狀況下

在默認狀況下,不加任何有關接收Date類型數據的配置時,前端傳遞Date類型數據至後端接口,控制檯出現如下異常:前端

Failed to convert from type [java.lang.String] to type [java.util.Date] for value
 '2333333333'; nested exception is java.lang.IllegalArgumentException]]
複製代碼

也就是說,在SpringBoot中,必須添加某種配置才能讓前端正確傳遞時間類型數據到後端。下面針對不一樣的狀況來介紹一下解決辦法。java


局部配置——使用@DateTimeFormat

第一種狀況,僅須要對某個Bean類的Date類型字段進行轉換,那麼只須要在Bean類屬性上增長@DateTimeFormat()註解,括號內 pattern爲前端傳遞的日期格式。好比:web

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
Date createTime;
複製代碼

特色--缺陷:spring

按照如上配置,只能處理形如:2018-11-2 2:22:2這樣固定格式的數據,沒法處理時間戳和2018-11-2格式的數據。若是想要處理2018-11-2這樣的時間,就必須把pattern改爲yyyy-MM-dd後端

能夠對不一樣的屬性賦予不一樣的pattern,可是對每一個Date類型都要加上註解顯得比較繁瑣,也沒法處理單個屬性可能對應不一樣格式的值的狀況。mvc

更通用、有效的方式是定義一個時間轉換類,並將其應用到全部的接口上。app


全局配置——自定義時間轉換器

分爲兩個步驟:ide

  • 編寫一個時間轉換類,把可能的格式轉換爲Date類型
  • 經過某種方式,將時間轉換應用到Spring的全部接口上

時間轉換類

import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;

/** * 日期轉換類 * 將標準日期、標準日期時間、時間戳轉換成Date類型 */
public class DateConverter implements Converter<String, Date> {
    private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
    private static final String shortDateFormat = "yyyy-MM-dd";
    private static final String timeStampFormat = "^\\d+$";

    @Override
    public Date convert(String value) {

        if(StringUtils.isEmpty(value)) {
            return null;
        }

        value = value.trim();

        try {
            if (value.contains("-")) {
                SimpleDateFormat formatter;
                if (value.contains(":")) {
                    formatter = new SimpleDateFormat(dateFormat);
                } else {
                    formatter = new SimpleDateFormat(shortDateFormat);
                }
                return formatter.parse(value);
            } else if (value.matches(timeStampFormat)) {
                Long lDate = new Long(value);
                return new Date(lDate);
            }
        } catch (Exception e) {
            throw new RuntimeException(String.format("parser %s to Date fail", value));
        }
        throw new RuntimeException(String.format("parser %s to Date fail", value));
    }
}
複製代碼

將時間轉換類應用到接口上

介紹兩種方式:使用@Component + @PostConstruct@ControllerAdvice + @InitBinderspa


第一種方式:.net

@Component + @PostConstruct

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import javax.annotation.PostConstruct;

/** * @author zfh * @version 1.0 * @date 2018/12/30 10:16 */
@Component
public class WebConfigBeans {

  @Autowired
  private RequestMappingHandlerAdapter handlerAdapter;

  @PostConstruct
  public void initEditableAvlidation() {

    ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer)handlerAdapter.getWebBindingInitializer();
    if(initializer.getConversionService()!=null) {
      GenericConversionService genericConversionService = (GenericConversionService)initializer.getConversionService();

      genericConversionService.addConverter(new DateConverterConfig());

    }
  }
}
複製代碼

第二種方式:

@ControllerAdvice + @InitBinder

有關這兩個註解的含義請參考個人博客:Spring進階之@ControllerAdvice與統一異常處理

import com.aegis.config.converter.DateConverter;
import com.aegis.model.bean.common.JsonResult;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

/** * @author zfh * @version 1.0 * @since 2019/1/4 15:23 */
@ControllerAdvice
public class ControllerHandler {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        GenericConversionService genericConversionService = (GenericConversionService) binder.getConversionService();
        if (genericConversionService != null) {
            genericConversionService.addConverter(new DateConverter());
        }
    }
}
複製代碼

OK,關於SpringBoot處理前端日期傳值的問題的相關解決辦法就介紹到這裏了。

相關文章
相關標籤/搜索