SpringMVC源码分析(二)

前言

     上一节,已经分析了获取执行链HandlerExecutionChain的过程,接下来继续分析DispatcherServlet的doDispatch方法下面要执行的内容。

 

源码分析

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

从获取处理器的适配器接着分析,为什么还需要这个适配器呢?到底需要适配什么内容?这个问题分析完成后再回答,现在进入这个方法中,很显然是从所有的适配器中找到通过支持此handler处理的。

/**
 * Return the HandlerAdapter for this handler object.
 * @param handler the handler object to find an adapter for
 * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
 */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   for (HandlerAdapter ha : this.handlerAdapters) {
      if (logger.isTraceEnabled()) {
         logger.trace("Testing handler adapter [" + ha + "]");
      }
      if (ha.supports(handler)) {
         return ha;
      }
   }
   throw new ServletException("No adapter for handler [" + handler +
         "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

在上面的代码中注意的地方是this.handlerAdapters的内容是怎么来的?ha.supports(handler)这个方法判断了什么?先来看看this.handlerAdapters的初始化(在DispatcherServlet类中)

/**
 * Initialize the HandlerAdapters used by this class.
 * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,
 * we default to SimpleControllerHandlerAdapter.
 */
private void initHandlerAdapters(ApplicationContext context) {
   this.handlerAdapters = null;
   //首先是一个变量(默认为true,但在web.xml中通过init-param可以设置成false)
   //意思是检测所有的handlerAdapters
   if (this.detectAllHandlerAdapters) {
      // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
      Map<String, HandlerAdapter> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
      if (!matchingBeans.isEmpty()) {
         this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
         // We keep HandlerAdapters in sorted order.
         AnnotationAwareOrderComparator.sort(this.handlerAdapters);
      }
   }
   //如果设置成了false,那么尝试获取名称为“handlerAdapter”的bean实例
   else {
      try {
         HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
         this.handlerAdapters = Collections.singletonList(ha);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default HandlerAdapter later.
      }
   }
   //如果都没有,那么就加载默认配置的适配器(在DispatcherServlet.properties文件中)
   
   // Ensure we have at least some HandlerAdapters, by registering
   // default HandlerAdapters if no other adapters are found.
   if (this.handlerAdapters == null) {
      this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
      if (logger.isDebugEnabled()) {
         logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
      }
   }
}

总之,上面的初始化过程是,先判断是否需要检测加载上下文中所有的适配器(默认),如果不是则尝试加载名称 是“handlerAdapter”的适配器。如果都没有,则加载默认配置的适配器。

org.springframework.web.servlet.HandlerAdapter=\
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
   org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
   org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

可以看到它配置了三种适配器,分别为:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter和AnnotationMethodHandlerAdapter,各自的作用是:

  • HttpRequestHandlerAdapter,http请求处理器适配器,仅仅支持http请求的适配,它不需要返回值,只是简单的将http请求的request和response对象传递给http请求处理器去实现。主要应用于http的远程调用的实现上。这种类型的适配器,所有的handler处理器需要实现HttpRequestHandler接口,并实现void handlerRequest(HttpRequest,HttpResponse)方法。
  • SimpleControllerHandlerAdapter,简单控制处理器适配器,它是将HTTP请求适配到一个控制器来实现处理。所有的业务都是在这个控制器的实现类中处理的。所有的handler处理器都需要实现Controller接口或者是继承AbstractController抽象类,并且需要实现ModelAndView handler(HttpRequest,HttpResponse,handler)方法,这个方法返回了ModelAndView对象,用于后续的模板渲染操作。
  • AnnotationMethodHandlerAdapter,注解方法处理器适配器,它的实现是基于注解的,需要结合注解的方法映射和方法处理器协同工作。通过解析声明在注解控制器的请求映射信息来解析响应的处理器来处理当前的http请求,在处理的过程中,通过反射发现处理器方法的参数,调用处理器方法,同时映射返回值到模型和控制器对象,最终返回模型和控制器对象给主控制器DispatcherServlet。

       所以,在这里我们就可以理解为什么需要适配器,主要是spring中使用的handler之间可以没有特殊的关系,但为了达到统一处理的目的,spring提供了不同handler的适配器去适配不同类型的handler处理器,其实除了上述的三种适配器还有SimpleServletHandlerAdapter、RequestMappingHandlerAdapter与上面的SimpleControllerHandlerAdapter原理大同小异。这样使得handler的实现更加多样化,与只能实现handler接口的方法相比也更加灵活。

分析完了Adapter适配器,接下来看看ha.supports(handler)是如何判断的,它是在handlerAdapter子类中实现的,不同的子类实现不太一样,又大致相同

HttpRequestHandlerAdapter中的实现

@Override
public boolean supports(Object handler) {
   return (handler instanceof HttpRequestHandler);
}

SimpleControllerHandlerAdapter

@Override
public boolean supports(Object handler) {
   return (handler instanceof Controller);
}

AnnotationMethodHandlerAdapter

@Override
public boolean supports(Object handler) {
   return getMethodResolver(handler).hasHandlerMethods();
}

RequestMappingHandlerAdapter这个与之前的有所区别,上面的都是直接实现了HandlerAdapter接口,而此类是继承了AbstractHandlerMethodAdapter。它主要是判断当前handler对象是否是HandlerMethod类的实例和是否支持当前handlerMethod

/**
 * This implementation expects the handler to be an {@link HandlerMethod}.
 * @param handler the handler instance to check
 * @return whether or not this adapter can adapt the given handler
 */
@Override
public final boolean supports(Object handler) {
    //supportsInternal总是返回true
   return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

       到此我们已经获取到了处理器的适配器,接着回到DispatcherServlet的doDispatch方法,看下面一段代码。先判断是GET请求,再判断重新getLastModified的时间戳是否新于上一次请求的时间,如果是最新的则说明请求的内容已经修改,继续往下执行,如果没有修改,则直接返回一个304的状态码,不再往下执行,浏览器拿304码后,直接拿缓存的数据展示。

// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
   long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
   if (logger.isDebugEnabled()) {
      logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
   }
   if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
      return;
   }
}

接下来,就是执行执行链中的拦截器的preHandler方法,如果任何一下拦截器的此方法返回了false,就会调用triggerAfterCompletion进行资源清理,此方法也是遍历所有拦截器调用拦截器的afterCompletion()方法,然后返回false,doDispatch方法不会再往下执行。

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
   return;
}

再往下,这才是重点,就是适配器执行handler方法,返回ModelAndView,上面也说了不同的handler处理器对应不同的适配器,所以此方法也肯定是由各子类去实现的

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

在这里我们主要是看AbstractHandlerMethodAdapter

@Override
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {

   return handleInternal(request, response, (HandlerMethod) handler);
}

protected abstract ModelAndView handleInternal(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;

再进入handleInternal,就来到了RequestMappingHandlerAdapter类的handleInternal方法中,我们来看看这个方法做了什么

@Override
protected ModelAndView handleInternal(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
/**
  检查请求,调用它父类WebContentGenerator中的checkRequest()方法,判断支持的请求方式
是否包含当前请求的方式,如果supportedMethods不为空且不支持当前请求方式,
会抛出著名的HttpRequestMetohdNotSupportedException。
如果需要session且从当前请求获得不到session,
同样抛出HttpSessionRequiredException异常
*/
   checkRequest(request);

/**
判断headlerMethod上是否有@SessionAttributes的注解,如果有
则在response上设置Cache-Control
*/
   if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
      applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
   }
   else {
       //如果没有,则预处理response,判断cacheControl是否为空
       //如果不空则设置,如果为空则清空response的cacheControl
      prepareResponse(response);
   }

   // Execute invokeHandlerMethod in synchronized block if required.
   //判断是否需要同步机制来执行invokeHandlerMethod
   if (this.synchronizeOnSession) {
      HttpSession session = request.getSession(false);
      if (session != null) {
         Object mutex = WebUtils.getSessionMutex(session);
         synchronized (mutex) {
            return invokeHandlerMethod(request, response, handlerMethod);
         }
      }
   }
   //如果不需要则直接执行method
   return invokeHandlerMethod(request, response, handlerMethod);
}

进入到RequestMappingHandlerAdapter类的invokeHandlerMethod

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   //封装一个RequestAttribute,方便取各参数
   ServletWebRequest webRequest = new ServletWebRequest(request, response);
   //获取一个绑定工厂类,主要用于创建WebDataBinder对象
   WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
   //获取一个模型工厂类
   ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

   ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
   invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
   invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
   invocableMethod.setDataBinderFactory(binderFactory);
   invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

   ModelAndViewContainer mavContainer = new ModelAndViewContainer();
   mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
   modelFactory.initModel(webRequest, mavContainer, invocableMethod);
   mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

   AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
   asyncWebRequest.setTimeout(this.asyncRequestTimeout);

   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
   asyncManager.setTaskExecutor(this.taskExecutor);
   asyncManager.setAsyncWebRequest(asyncWebRequest);
   asyncManager.registerCallableInterceptors(this.callableInterceptors);
   asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

   if (asyncManager.hasConcurrentResult()) {
      Object result = asyncManager.getConcurrentResult();
      mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
      asyncManager.clearConcurrentResult();
      if (logger.isDebugEnabled()) {
         logger.debug("Found concurrent result value [" + result + "]");
      }
      invocableMethod = invocableMethod.wrapConcurrentResult(result);
   }

   invocableMethod.invokeAndHandle(webRequest, mavContainer);
   if (asyncManager.isConcurrentHandlingStarted()) {
      return null;
   }

   return getModelAndView(mavContainer, modelFactory, webRequest);
}

      上面第二步获取WebDataBinderFactory,它的作用是创建WebDataBinder对象。我们都知道客户端无论什么类型的参数,最终都是以字节的形式传给服务端,然后由request.getParameter方法以字符串的形式取出来。这样就需要有一个转换类把这个字符串类型转给我们需要的类型,比如:2019-02-28转换成Date类型等等。WebDataBinder对象就是我们需要的转换工具,它不需要我们去创建,我们只需要使用类似 binder.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, true))的操作向它注册相应的PropertyEditor(最常见的做法实现WebBindingInitializer接口)。PropertyEditor调用它的void setAsText(String text)方法实现数据转换的过程可以将字符串转换成真正的数据类型,这个是sun包中的类,比如:BooleanPropertyEditor,LongPropertyEditor等等。除了使用PropertyEditor转换外,我们还可以使用org.springframework.core.convert.converter.Converter<S, T>,并且把它注册到org.springframework.context.support.ConversionServiceFactoryBean中来实现类型的转换。

扯远了,我们再回到ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);方法

private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
   Class<?> handlerType = handlerMethod.getBeanType();
   Set<Method> methods = this.initBinderCache.get(handlerType);
   if (methods == null) {
      methods = HandlerMethodSelector.selectMethods(handlerType, INIT_BINDER_METHODS);
      this.initBinderCache.put(handlerType, methods);
   }
   List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
   // Global methods first
   //首先遍历所有@ControllerAdvice注解的类,从这些类中找到@InitBinder的方法
   //封装成InitBinderMethod对象加入到list中
   for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache .entrySet()) {
      if (entry.getKey().isApplicableToBeanType(handlerType)) {
         Object bean = entry.getKey().resolveBean();
         for (Method method : entry.getValue()) {
            initBinderMethods.add(createInitBinderMethod(bean, method));
         }
      }
   }
   //说明可以有多个@InitBinder
   for (Method method : methods) {
      Object bean = handlerMethod.getBean();
      initBinderMethods.add(createInitBinderMethod(bean, method));
   }
   return createDataBinderFactory(initBinderMethods);
}

先是从initBinderCache中获取,如果没有取到,就重新使用查找器找,INIT_BINDER_METHODS这是一个Filter,可以看到在当前类中找@InitBinder注解的方法,再放到缓存中

public static final MethodFilter INIT_BINDER_METHODS = new MethodFilter() {
   @Override
   public boolean matches(Method method) {
      return AnnotationUtils.findAnnotation(method, InitBinder.class) != null;
   }
};

从这里可以看出所创建的WebDataBinderFactory,其实是ServletRequestDataBinderFactory

protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)
      throws Exception {

   return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
}

到这里我们已经知道,创建了一个WebDataBinderFactory,它包含了很多类型转换器,接下来就是创建ModelFactory

private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
   SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
   Class<?> handlerType = handlerMethod.getBeanType();
   Set<Method> methods = this.modelAttributeCache.get(handlerType);
   if (methods == null) {
      methods = HandlerMethodSelector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
      this.modelAttributeCache.put(handlerType, methods);
   }
   List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
   // Global methods first
   for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
      if (entry.getKey().isApplicableToBeanType(handlerType)) {
         Object bean = entry.getKey().resolveBean();
         for (Method method : entry.getValue()) {
            attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
         }
      }
   }
   for (Method method : methods) {
      Object bean = handlerMethod.getBean();
      attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
   }
   return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
}

过程和创建WebDataBinderFactory类型,ModelFactory的作用是在控制器方法调用前初始化Model模型,调用后对Model模型进行更新操作。既然binderFactory和modelFactory都已经被创建出来了,接下来就是对handlerMethod进行再次封装了,接着invokeHandlerMethod方法往下走

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
...
//ServletInvocableHandlerMethod的作用就是对处理器方法的返回
//值进行相关的处理,同时还有ResponseStatus
   ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
   invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
   invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
   invocableMethod.setDataBinderFactory(binderFactory);
   invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
//实例化容器
   ModelAndViewContainer mavContainer = new ModelAndViewContainer();
   //把request中的DispatcherServlet.INPUT_FLASH_MAP,重定向
   //参数注入到容器的model模型中,FlashMap的作用是在redirect中传递参数。
   //重定向是会生成新的request,传递参数就不能直接用request进行传递
   mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
   modelFactory.initModel(webRequest, mavContainer, invocableMethod);
   mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
...
   return getModelAndView(mavContainer, modelFactory, webRequest);
}

实例化ModelAndViewContainer容器,它主要是用来返回Model对象的,在容器中有两种Model一个是defaultModel,另一个是redirectModel,redirectModel用于传递redirect时的参数。

接下来看看modelFactory.initModel(webRequest, mavContainer, invocableMethod);做了什么事情

public void initModel(NativeWebRequest request, ModelAndViewContainer mavContainer, HandlerMethod handlerMethod)
      throws Exception {

   Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
   mavContainer.mergeAttributes(sessionAttributes);

   invokeModelAttributeMethods(request, mavContainer);

   for (String name : findSessionAttributeArguments(handlerMethod)) {
      if (!mavContainer.containsAttribute(name)) {
         Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
         if (value == null) {
            throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
         }
         mavContainer.addAttribute(name, value);
      }
   }
}

从request中获取@SessionAttribute的属性,先存在map结构中,然后执行了invokeModelAttributeMethods(request, mavContainer);方法

/**
 * Invoke model attribute methods to populate the model.
 * Attributes are added only if not already present in the model.
 */
private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer mavContainer)
      throws Exception {

   while (!this.modelMethods.isEmpty()) {
      InvocableHandlerMethod attrMethod = getNextModelMethod(mavContainer).getHandlerMethod();
      //把@ModelAttribute注解的handlerMethod中的模型添加到容器中的model中
      String modelName = attrMethod.getMethodAnnotation(ModelAttribute.class).value();
      if (mavContainer.containsAttribute(modelName)) {
         continue;//只有当容器中不存在@ModelAtrribute中的属性时才加入
         
      }
    //取出所有的参数并且利用容器中包含的参数解析器进行解析,完成后
    //取得HandlerMethod属性方法和对应的bean对象,利用反射机制执行此方法
    //获取返回值
      Object returnValue = attrMethod.invokeForRequest(request, mavContainer);
    //如果HandlerMethod方法不是void的
      if (!attrMethod.isVoid()){
          //如果@ModelAtrribute注解设置了value值,则此值
          //作为返回值的名称,如果没有设置,则选择被@ModelAtrribute注解
          //注解的handlerMethod的返回类型名称(首字母小写)作为model中的key
          //如果这个返回类型是数组或集合,那么这个名称是返回类型名称再拼接上"List"
          //如果返回类型是String或者是map,那么key就是map或string
         String returnValueName = getNameForReturnValue(returnValue, attrMethod.getReturnType());
         if (!mavContainer.containsAttribute(returnValueName)) {
            mavContainer.addAttribute(returnValueName, returnValue);
         }
      }
   }
}

public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {
    //解析获取参数
   Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
   if (logger.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder("Invoking [");
      sb.append(getBeanType().getSimpleName()).append(".");
      sb.append(getMethod().getName()).append("] method with arguments ");
      sb.append(Arrays.asList(args));
      logger.trace(sb.toString());
   }
   //执行
   Object returnValue = doInvoke(args);
   if (logger.isTraceEnabled()) {
      logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
   }
   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);
      GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
      args[i] = resolveProvidedArgument(parameter, providedArgs);
      if (args[i] != null) {
         continue;
      }
      //使用对应的解析器去解析参数
      if (this.argumentResolvers.supportsParameter(parameter)) {
         try {
            args[i] = this.argumentResolvers.resolveArgument(
                  parameter, mavContainer, request, this.dataBinderFactory);
            continue;
         }
         catch (Exception ex) {
            if (logger.isDebugEnabled()) {
               logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
            }
            throw ex;
         }
      }
      if (args[i] == null) {
         String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
         throw new IllegalStateException(msg);
      }
   }
   return args;
}

protected Object doInvoke(Object... args) throws Exception {
   ReflectionUtils.makeAccessible(getBridgedMethod());
   try {
       //反射机制执行方法
      return getBridgedMethod().invoke(getBean(), args);
   }
   catch (IllegalArgumentException ex) {
      assertTargetBean(getBridgedMethod(), getBean(), args);
      throw new IllegalStateException(getInvocationErrorMessage(ex.getMessage(), args), ex);
   }
   catch (InvocationTargetException ex) {
      // Unwrap for HandlerExceptionResolvers ...
      Throwable targetException = ex.getTargetException();
      if (targetException instanceof RuntimeException) {
         throw (RuntimeException) targetException;
      }
      else if (targetException instanceof Error) {
         throw (Error) targetException;
      }
      else if (targetException instanceof Exception) {
         throw (Exception) targetException;
      }
      else {
         String msg = getInvocationErrorMessage("Failed to invoke controller method", args);
         throw new IllegalStateException(msg, targetException);
      }
   }
}
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {

   Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
   if (logger.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder("Invoking [");
      sb.append(getBeanType().getSimpleName()).append(".");
      sb.append(getMethod().getName()).append("] method with arguments ");
      sb.append(Arrays.asList(args));
      logger.trace(sb.toString());
   }
   Object returnValue = doInvoke(args);
   if (logger.isTraceEnabled()) {
      logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
   }
   return returnValue;
}

public static String getNameForReturnValue(Object returnValue, MethodParameter returnType) {
   ModelAttribute annotation = returnType.getMethodAnnotation(ModelAttribute.class);
   if (annotation != null && StringUtils.hasText(annotation.value())) {
      return annotation.value();
   }
   else {
      Method method = returnType.getMethod();
      Class<?> resolvedType = GenericTypeResolver.resolveReturnType(method, returnType.getContainingClass());
     //这个方法是判断如果返回的是object类型,那么就会通过实现的返回类型推测出
     //类的简称
       return Conventions.getVariableNameForReturnType(method, resolvedType, returnValue);
   }
}

 

再回到initModel()方法上,分析接下来的代码

//遍历handlerMethod的参数,判断是否有被@ModelAttribute注解的
//如果有,则继续判断这个参数和类型是否和当前handlerMethod所在类
//中的@SessionAttribute注解中的参数和类型一致
for (String name : findSessionAttributeArguments(handlerMethod)) {
   if (!mavContainer.containsAttribute(name)) {
      Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
      if (value == null) {
         throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
      }
      //把名称和值添加到model中,这里的model是defaultModel
      
      mavContainer.addAttribute(name, value);
   }
}

private List<String> findSessionAttributeArguments(HandlerMethod handlerMethod) {
   List<String> result = new ArrayList<String>();
   for (MethodParameter parameter : handlerMethod.getMethodParameters()) {
      if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
         String name = getNameForParameter(parameter);
         if (this.sessionAttributesHandler.isHandlerSessionAttribute(name, parameter.getParameterType())) {
            result.add(name);
         }
      }
   }
   return result;
}

接着再回到

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
...
//处理一些异步请求
   AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
   asyncWebRequest.setTimeout(this.asyncRequestTimeout);

   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
   asyncManager.setTaskExecutor(this.taskExecutor);
   asyncManager.setAsyncWebRequest(asyncWebRequest);
   asyncManager.registerCallableInterceptors(this.callableInterceptors);
   asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

   if (asyncManager.hasConcurrentResult()) {
      Object result = asyncManager.getConcurrentResult();
      mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
      asyncManager.clearConcurrentResult();
      if (logger.isDebugEnabled()) {
         logger.debug("Found concurrent result value [" + result + "]");
      }
      invocableMethod = invocableMethod.wrapConcurrentResult(result);
   }
//调用invokeAndHandle方法
   invocableMethod.invokeAndHandle(webRequest, mavContainer);
   if (asyncManager.isConcurrentHandlingStarted()) {
      return null;
   }

   return getModelAndView(mavContainer, modelFactory, webRequest);
}

我们来看看invokeAndHandle,从给定请求中解析handlerMethod的参数,调用此方法,并获取handlerMethod的返回值,具体的过程与上面的执行属性方法类似

public void invokeAndHandle(ServletWebRequest webRequest,
      ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {

   Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
   //如果有使用@ResponseStatus注解来设置响应状态时则设置responseStatus
   setResponseStatus(webRequest);
   //如果返回值为空,则状态是否是request请求或者返回状态有值时
   if (returnValue == null) {
      if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
         mavContainer.setRequestHandled(true);//直接使用response来处理返回
         return;
      }
   }
   else if (StringUtils.hasText(this.responseReason)) {
      mavContainer.setRequestHandled(true);
      return;
   }
  //如果不使用response来处理,则设置为false,使用view来处理返回
   mavContainer.setRequestHandled(false);
   try {
       //遍历所有的返回值处理器,通过supportsReturnType()
       //来找到支持此返回值类型的处理器
      this.returnValueHandlers.handleReturnValue(
            returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
   }
   catch (Exception ex) {
      if (logger.isTraceEnabled()) {
         logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
      }
      throw ex;
   }
}

@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
      ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

   HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
   Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
   handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {
   boolean isAsyncValue = isAsyncReturnValue(value, returnType);
   for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
      if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
         continue;
      }
      if (handler.supportsReturnType(returnType)) {
         return handler;
      }
   }
   return null;
}

我们再回到RequestMappingHandlerAdapter中的invokeHandlerMethod()方法,接下来,还剩下

return getModelAndView(mavContainer, modelFactory, webRequest);

 

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
      ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
  //查看下面updateModel中的解释
   modelFactory.updateModel(webRequest, mavContainer);
   //如果容器采用的是response直接处理的方式,说明不采用view
   //的方案,直接返回null即可
   if (mavContainer.isRequestHandled()) {
      return null;
   }
   //采用的是view方案,获取默认的model,将此model和视图名称
   //直接填充到ModelAndView中,创建一个ModelAndView出来
   ModelMap model = mavContainer.getModel();
   ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
   //return (this.view instanceof String);如果容器中的view不是string的话
   //就设置此视图对象,如果是string说明是逻辑视图名称,等待下一步处理
   if (!mavContainer.isViewReference()) {
      mav.setView((View) mavContainer.getView());
   }
   //如果model是RedirectAttributes的实例,
   //那么说明是model是重定向所需要的属性,我们把model填充到FlashMap即可
   if (model instanceof RedirectAttributes) {
      Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
      HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
      RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
   }
   return mav;
}

public void updateModel(NativeWebRequest request, ModelAndViewContainer mavContainer) throws Exception {
   ModelMap defaultModel = mavContainer.getDefaultModel();
   //获取默认的model对象,判断当前会话是否完成,如果完成
   //则清理相关的资源,如果没有完成,则把当前request中
   //的model对象保存在sessionAttributeStore方便下次请求
   //
   if (mavContainer.getSessionStatus().isComplete()){
      this.sessionAttributesHandler.cleanupAttributes(request);
   }
   else {
      this.sessionAttributesHandler.storeAttributes(request, defaultModel);
   }
   if (!mavContainer.isRequestHandled() && mavContainer.getModel() == defaultModel) {
      updateBindingResult(request, defaultModel);
   }
}

再返回到上一步RequestMappingHandlerAdapter中的hanlderInternal()方法中,方法已经执行完成,接着返回到RequestMappingHandlerAdapter中方法也执行完成,接着再返回到AbstractHandlerMethodAdapter中的handler方法,即在doDispatch方法中执行的mv = ha.handle(processedRequest, response, mappedHandler.getHandler());此时我们得到了ModelAndView对象。接下来就是如何把Model绑定到相应的view的问题了。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   HttpServletRequest processedRequest = request;
   HandlerExecutionChain mappedHandler = null;
   boolean multipartRequestParsed = false;

   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

   try {
      ModelAndView mv = null;
     ...........

         // Actually invoke the handler.
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }
      //如果mv中没有视图名称,则设置默认的视图名称
         applyDefaultViewName(processedRequest, mv);
         //执行 在执行链中的所有拦截器的postHandle方法对返回的结果再次处理
         mappedHandler.applyPostHandle(processedRequest, response, mv);
      }
      catch (Exception ex) {
         dispatchException = ex;
      }
      //对返回结果进行处理,详见下面 processDispatchResult方法
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
   catch (Exception ex) {
      triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
   }
   catch (Error err) {
      triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
   }
   finally {
      if (asyncManager.isConcurrentHandlingStarted()) {
         // Instead of postHandle and afterCompletion
         if (mappedHandler != null) {
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
         }
      }
      else {
         // Clean up any resources used by a multipart request.
         if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
         }
      }
   }
}

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
      HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

   boolean errorView = false;
  //判断是否有异常存在,如果有则再判断是否是ModelAndViewDefiningException
  //如果是则把视图解析成ModelAndViewDefiningException需要的类型
   if (exception != null) {
      if (exception instanceof ModelAndViewDefiningException) {
         logger.debug("ModelAndViewDefiningException encountered", exception);
         mv = ((ModelAndViewDefiningException) exception).getModelAndView();
      }
      else {
          //如果是其它异常,
          //就让HandlerExceptionResovlers中的异常解析器来处理
         Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
         mv = processHandlerException(request, response, handler, exception);
         errorView = (mv != null);
      }
   }

   // Did the handler return a view to render?
   if (mv != null && !mv.wasCleared()) {
       //如果mv不为空且mv中的model和view没有被清理
       //则执行render
      render(mv, request, response);
      if (errorView) {
         WebUtils.clearErrorRequestAttributes(request);
      }
   }
   else {
      if (logger.isDebugEnabled()) {
         logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
               "': assuming HandlerAdapter completed request handling");
      }
   }

   if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
      // Concurrent handling started during a forward
      return;
   }

   if (mappedHandler != null) {
      mappedHandler.triggerAfterCompletion(request, response, null);
   }
}
//render的作用就是判断mv中的视图是否是逻辑视图名称,如果是,
//则去视图解析器中找到对应的物理视图对象,找到后直接执行视图的render方法
//完成渲染工作
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
   // Determine locale for request and apply it to the response.
   Locale locale = this.localeResolver.resolveLocale(request);
   response.setLocale(locale);

   View view;
   if (mv.isReference()) {
      // We need to resolve the view name.
      view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
      if (view == null) {
         throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
               "' in servlet with name '" + getServletName() + "'");
      }
   }
   else {
      // No need to lookup: the ModelAndView object contains the actual View object.
      view = mv.getView();
      if (view == null) {
         throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
               "View object in servlet with name '" + getServletName() + "'");
      }
   }

   // Delegate to the View object for rendering.
   if (logger.isDebugEnabled()) {
      logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
   }
   try {
       //调用它本身的render方法把model对象填充到view中,完成渲染工作
      view.render(mv.getModelInternal(), request, response);
   }
   catch (Exception ex) {
      if (logger.isDebugEnabled()) {
         logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
               getServletName() + "'", ex);
      }
      throw ex;
   }
}

 protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
            HttpServletRequest request) throws Exception {

        for (ViewResolver viewResolver : this.viewResolvers) {
            View view = viewResolver.resolveViewName(viewName, locale);
            if (view != null) {
                return view;
            }
        }
        return null;
    }

总结

       到现在为止,dispatch方法主体才执行完成,后续还有一些清理的方法不再描述。可以看到springmvc在处理请求的时候还是先复杂的,这个主要是由于springmvc具有很强的扩展性,在请求的名阶段都可以干预请求的处理和处理结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值