springmvc处理请求流程2

当请求来到,并找到正确的Controller以及HandlerAdapter以后。就该执行方法了。web

这里说的是 3.0版本以后的 RequestMappingAdapter 的解析执行过程。app

如下源码都是简化以后的。ide

首先,在DispatcherServlet部分源码以下ui

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
         // 找controller
         mappedHandler = getHandler(processedRequest);
         // 找HandlerAdaper
         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
         // HandlerAdaper执行handle方法
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
      }   
}

最后的handle方法,是调用到了RequestMappingAdapter的handleInternal()方法。this

RequestMappingAdapter源码以下spa

protected ModelAndView handleInternal(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   mav = invokeHandlerMethod(request, response, handlerMethod);
   return mav;
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
   try {
      // 每一个请求过来的时候,都会新建一个ServletInvocableHandlerMethod 对象
      ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
      // 给ServletInvocableHandlerMethod 对象设置方法参数解析器、方法返回值解析器 等
      invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
      invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
      // 交给 ServletInvocableHandlerMethod 来处理请求了
      invocableMethod.invokeAndHandle(webRequest, mavContainer);
}

在 ServletInvocableHandlerMethod 类中,源码以下debug

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {
   // 处理请求,invokeForRequest方法是父类InvocableHandlerMethod 的,父类主要处理请求
   Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
   
   try {
      // 处理返回值
      this.returnValueHandlers.handleReturnValue(
            returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
   }
}

InvocableHandlerMethod  类的源码 以下对象

public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {
   // 获取方法的参数 
   Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
   // 内部经过反射,调用controller 中的方法。
   Object returnValue = doInvoke(args);
   return returnValue;
}
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {

   MethodParameter[] parameters = getMethodParameters();
   Object[] args = new Object[parameters.length];
   for (int i = 0; i < parameters.length; i++) {
      MethodParameter parameter = parameters[i];
      parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
      args[i] = resolveProvidedArgument(parameter, providedArgs);
      if (args[i] != null) {
         continue;
      }
      // 这个参数解析器是刚刚RequestMappingHandlerAdapter给注入的,是 HandlerMethodArgumentResolverComposite
      // 类型,它实现了HandlerMethodArgumentResolver接口,是个HandlerMethodArgumentResolver组合(集合)
      if (this.argumentResolvers.supportsParameter(parameter)) {
         try {
            // 解析参数,获得参数。
            args[i] = this.argumentResolvers.resolveArgument(
                  parameter, mavContainer, request, this.dataBinderFactory);
            continue;
         }
   }
   return args;
}

HandlerMethodArgumentResolverComposite类的 supportsParameter具体实现以下,其实就是在它的属性里有个List<HandlerMethodArgumentResolver>,而后看这个list里面有没有supports的。接口

@Override
public boolean supportsParameter(MethodParameter parameter) {
   return (getArgumentResolver(parameter) != null);
}
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
   HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
   if (result == null) {
      for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
         if (logger.isTraceEnabled()) {
            logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
                  parameter.getGenericParameterType() + "]");
         }
         // 这个就是遍历 List<HandlerMethodArgumentResolver> 里面的参数解析器,看有没有suppotrs的。
         if (methodArgumentResolver.supportsParameter(parameter)) {
            result = methodArgumentResolver;
            this.argumentResolverCache.put(parameter, result);
            break;
         }
      }
   }
   return result;
}

 

参数的解析大致流程就是上面的代码了,补一下总体的结构。更加清晰一些get

RequestMappingHandlerAdapter的属性有以下(部分)

// 如下是 处理方法参数的解析器,第一个是须要咱们自定义,第二个是默认的

private List<HandlerMethodArgumentResolver> customArgumentResolvers;

private HandlerMethodArgumentResolverComposite argumentResolvers;

// 如下是 处理方法返回值的解析器,第一个是须要咱们自定义,第二个是默认的

private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;

private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

那么RequestMappingHandlerAdapter的 argumentResolvers 和 returnValueHandlers是哪里来的呢?

是Spring启动时注册RequestMappingHandlerAdapter的时候自动注入的。以下

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
   List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

   // Annotation-based argument resolution
   resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
   resolvers.add(new RequestParamMapMethodArgumentResolver());
   resolvers.add(new PathVariableMethodArgumentResolver());
   resolvers.add(new PathVariableMapMethodArgumentResolver());
   resolvers.add(new MatrixVariableMethodArgumentResolver());
   resolvers.add(new MatrixVariableMapMethodArgumentResolver());
   resolvers.add(new ServletModelAttributeMethodProcessor(false));
   resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
   resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
   resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
   resolvers.add(new RequestHeaderMapMethodArgumentResolver());
   resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
   resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
   resolvers.add(new SessionAttributeMethodArgumentResolver());
   resolvers.add(new RequestAttributeMethodArgumentResolver());

   // Type-based argument resolution
   resolvers.add(new ServletRequestMethodArgumentResolver());
   resolvers.add(new ServletResponseMethodArgumentResolver());
   resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
   resolvers.add(new RedirectAttributesMethodArgumentResolver());
   resolvers.add(new ModelMethodProcessor());
   resolvers.add(new MapMethodProcessor());
   resolvers.add(new ErrorsMethodArgumentResolver());
   resolvers.add(new SessionStatusMethodArgumentResolver());
   resolvers.add(new UriComponentsBuilderMethodArgumentResolver());

   // Custom arguments
   if (getCustomArgumentResolvers() != null) {
      resolvers.addAll(getCustomArgumentResolvers());
   }

   // Catch-all
   resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
   resolvers.add(new ServletModelAttributeMethodProcessor(true));

   return resolvers;
}

而后执行handle方法的时候,RequestMappingHandlerAdapter 又把这两个属性给了

ServletInvocableHandlerMethod。而后ServletInvocableHandlerMethod利用解析器作各类处理。

 

ServletInvocableHandlerMethod 是主要处理 方法返回值的,它的父类是

InvocableHandlerMethod 是主要处理 方法参数的。 它的父类就是 HandlerMethod 了。

 

因此以上主要涉及的几个类,名字都比较长。不能混淆,都要知道它们各自是干吗的,本文比较粗略,内部仍是没有debug,我目前也就理解到这里了。

相关文章
相关标签/搜索