关于Springboot日期时间格式化处理方式总结

2020-03-04 12:03:52于丽

扩充源码:深入研究SpringMVC数据绑定过程

接下来进入debug模式,看看mvc是如何将我们request中的参数绑定到我们controller层方法入参的;

写一个简单controller,打个断点看看方法调用栈:

  @GetMapping("/getDate")
  public LocalDateTime getDate(@RequestParam LocalDate date,
                 @RequestParam LocalDateTime dateTime,
                 @RequestParam Date originalDate) {
    System.out.println(date);
    System.out.println(dateTime);
    System.out.println(originalDate);
    return LocalDateTime.now();
  }

调用接口以后,我们看下方法调用栈中一些关键方法:

//进入DispatcherServlet
doService:942, DispatcherServlet
//处理请求
doDispatch:1038, DispatcherServlet
//生成调用链(前处理、实际调用方法、后处理)
handle:87, AbstractHandlerMethodAdapter
//反射获取到实际调用方法,准备开始调用
invokeHandlerMethod:895, RequestMappingHandlerAdapter
invokeAndHandle:102, ServletInvocableHandlerMethod
//这里是关键,参数从这里开始获取到
invokeForRequest:142, InvocableHandlerMethod
doInvoke:215, InvocableHandlerMethod
//这个是Java reflect调用,因此一定是在这之前获取到的参数
invoke:566, Method

根据上述分析,发现invokeForRequest:142, InvocableHandlerMethod这里的代码是用来拿到实际参数的:

  @Nullable
  public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {
    //这个方法是获取参数的,在这里下个断
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
      logger.trace("Arguments: " + Arrays.toString(args));
    }
    //这里开始调用方法
    return doInvoke(args);
  }

进入这个方法看看是什么操作:

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
  //获取方法参数数组,包含了入参信息,比如类型、泛型等等
  MethodParameter[] parameters = getMethodParameters();
  //这个用来存放一会从request parameter转换的参数
  Object[] args = new Object[parameters.length];
  for (int i = 0; i < parameters.length; i++) {
   MethodParameter parameter = parameters[i];
   parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
   //这里看起来没啥卵用(providedArgs为空)
   args[i] = resolveProvidedArgument(parameter, providedArgs);
   //这里开始获取到方法实际调用的参数,步进
   if (this.argumentResolvers.supportsParameter(parameter)) {
    //从名字就看出来:参数解析器解析参数
    args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
    continue;
   }
  }
  return args;
}