Springboot получает исключение данных типа Date и решение

Spring Boot

по умолчанию

По умолчанию, если конфигурация для получения данных типа 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, необходимо добавить некоторую конфигурацию, чтобы внешний интерфейс мог правильно передавать данные типа времени на серверную часть. Ниже приведены решения для различных ситуаций.


Локальная конфигурация - использовать@DateTimeFormat

В первом случае необходимо преобразовать только поле типа даты класса Bean, затем необходимо добавить только атрибут класса Bean.@DateTimeFormat()Примечания в скобкахpatternФормат даты, переданный для внешнего интерфейса. Например:

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

Особенности - Дефекты:

В соответствии с приведенной выше конфигурацией может быть обработана только форма:2018-11-2 2:22:2Такие данные фиксированного формата не могут обрабатывать метки времени и2018-11-2форматировать данные. Если вы хотите иметь дело с2018-11-2В такое время необходимоpatternизменить наyyyy-MM-dd.

Разным атрибутам можно присвоить разныеpattern, но добавлять аннотации к каждому типу 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 + @InitBinder


Первый способ:

@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());
        }
    }
}

Хорошо, здесь представлены соответствующие решения проблемы обработки SpringBoot передачи даты во внешнем интерфейсе.