当前位置 主页 > 服务器问题 > Linux/apache问题 >

    详解SpringBoot时间参数处理完整解决方案

    栏目:Linux/apache问题 时间:2019-12-03 10:46

    在JavaWeb程序的开发过程中,接口是前后端对接的主要窗口,而接口参数的接收有时候是一个令人头疼的事情,这其中最困扰程序猿的,应该是时间参数的接收。

    比如:设置一个用户的过期时间,前端到底以什么格式传递参数呢?时间戳?还是2019-12-01 22:13:00这种格式?还是其他格式?

    今天我就来总结一下SpringBoot Web应用接口接收时间类型参数的问题解决方案。

    注:目前我对Spring源码的掌握还不是很好,所以这一篇仅仅总结一下解决方法,后面感悟多了会重写一下!

    示例代码请前往:https://github.com/laolunsi/spring-boot-examples

    经过简单的测试,我们知道:

    不使用@RequestBody注解的情况下,所有时间类型参数都会引起报错; 使用@RequestBody,前端传递时间戳或2019-11-22形式正常,传递2019-11-22 11:22:22报错,其他格式同样报错。

    之前有接触过类似的解决办法,在类的属性上加上@DateFormat注解,解决单个时间参数问题。

    但是局限较多。

    理想的解决方案是:一次配置,全局通用,多种格式,自动转换(朗朗上口嗷)

    一、源码简要分析

    首先我们来简单分析一下源码:

    深入的就不解释了(我现在也不懂🤦‍♂️)

    简单来说,接口接收的参数,首先被HandlerMethodArgumentResolver的实现类处理了一遍,将其转换为我们需要的格式。

    这里主要分为两种情况:

    使用了@RequestBody的参数,一般是对象接收,前端传递的通常是JSON形式 其他接收参数的方式,比如@RequestAttribute,@RequestParam,或者默认形式,前端传递的通常是表单参数、请求URL后缀参数等

    二、解决方法

    默认形式,或使用@RequestAttribute,或使用@RequestParam,这样的参数,通过配置converter来解决问题 使用@RequestBody解析的参数,通过在ObjectMapper中配置序列化和反序列化规则来处理

    2.1 自定义converter

    针对第一种情况,我们需要配置converter,这里介绍两种方法:

    @ControllerAdvice + @InitBinder 直接使用@Bean定义converter类

    首先我们这里需要一个DateConverter类,这个类实现了Converter接口,重写了其中的convert方法,将String转成Date类型:

    我们这里定义了三种处理格式:

    /**
     * 日期转换类
     * 将标准日期、标准日期时间、时间戳转换成Date类型
     */
    /*@Deprecated*/
    public class DateConverter implements Converter<String, Date> {
    
     private Logger logger = LoggerFactory.getLogger(DateConverter.class);
    
     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) {
      logger.info("转换日期:" + value);
    
      if(value == null || value.trim().equals("") || value.equalsIgnoreCase("null")) {
       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));
     }
    }