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,我目前也就理解到這裏了。

相關文章
相關標籤/搜索