spring mvc源码分析

一、spring mvc 执行流程

这个图片来自这个博客

XmlWebApplicationContext先读配置文件;

1
 <mvc:annotation-driven></mvc:annotation-driven>

MvcNamespaceHandler处理mvc空间名,org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser解析"annotation-driven"配置;

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
   @Override
   public BeanDefinition parse(Element element, ParserContext context) {
       Object source = context.extractSource(element);
       XmlReaderContext readerContext = context.getReaderContext();

       CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
       context.pushContainingComponent(compDefinition);
       // ContentNegotiationManagerFactoryBean创建ContentNegotiationManager
       RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, context);
       //1.RequestMappingHandlerMapping
       RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
       handlerMappingDef.setSource(source);
       handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       handlerMappingDef.getPropertyValues().add("order", 0);
       handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);

       if (element.hasAttribute("enable-matrix-variables")) {
           Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
           handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
       }
       else if (element.hasAttribute("enableMatrixVariables")) {
           Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enableMatrixVariables"));
           handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
       }
       
       configurePathMatchingProperties(handlerMappingDef, element, context);
       readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
       //2.跨域CORS配置
       RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, context, source);
       handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
       //3.ConversionService,默认FormattingConversionServiceFactoryBean
       RuntimeBeanReference conversionService = getConversionService(element, source, context);
       //4.validator,默认javax.validation.Validator
       RuntimeBeanReference validator = getValidator(element, source, context);
       //5.messageCodesResolver,配置message-codes-resolver,无返回null
       RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
       //6.ConfigurableWebBindingInitializer
       RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
       bindingDef.setSource(source);
       bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       bindingDef.getPropertyValues().add("conversionService", conversionService);
       bindingDef.getPropertyValues().add("validator", validator);
       bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);
       //7.消息转换器
       //  默认ByteArrayHttpMessageConverter,StringHttpMessageConverter,
       // 加载Jackson的jar包;MappingJackson2XmlHttpMessageConverter,MappingJackson2HttpMessageConverter
       ManagedList<?> messageConverters = getMessageConverters(element, source, context);
       //8.参数解析器
       ManagedList<?> argumentResolvers = getArgumentResolvers(element, context);
       //9.返回值处理程序
       ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, context);
       //10.异步支持,
       String asyncTimeout = getAsyncTimeout(element);
       RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
       ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, context);
       ManagedList<?> deferredResultInterceptors = getDeferredResultInterceptors(element, source, context);
       //11.RequestMappingHandlerAdapter
       RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
       handlerAdapterDef.setSource(source);
       handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
       handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
       handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
       addRequestBodyAdvice(handlerAdapterDef);
       addResponseBodyAdvice(handlerAdapterDef);

       if (element.hasAttribute("ignore-default-model-on-redirect")) {
           Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));
           handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
       }
       else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
           // "ignoreDefaultModelOnRedirect" spelling is deprecated
           Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));
           handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
       }

       if (argumentResolvers != null) {
           handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
       }
       if (returnValueHandlers != null) {
           handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
       }
       if (asyncTimeout != null) {
           handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
       }
       if (asyncExecutor != null) {
           handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
       }

       handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
       handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
       readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME , handlerAdapterDef);
       //12.CompositeUriComponentsContributorFactoryBean创建CompositeUriComponentsContributor
       RootBeanDefinition uriContributorDef =
               new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
       uriContributorDef.setSource(source);
       uriContributorDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
       uriContributorDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
       String uriContributorName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
       readerContext.getRegistry().registerBeanDefinition(uriContributorName, uriContributorDef);
       //13.ConversionServiceExposingInterceptor接口,实现ConversionService设置
       RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
       csInterceptorDef.setSource(source);
       csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);
       //13.MappedInterceptor接口,添加ConversionServiceExposingInterceptor接口
       RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
       mappedInterceptorDef.setSource(source);
       mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
       mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
       String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedInterceptorDef);
       //14.ExceptionHandlerExceptionResolver
       RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
       methodExceptionResolver.setSource(source);
       methodExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       methodExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
       methodExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
       methodExceptionResolver.getPropertyValues().add("order", 0);
       addResponseBodyAdvice(methodExceptionResolver);
       if (argumentResolvers != null) {
           methodExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
       }
       if (returnValueHandlers != null) {
           methodExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
       }
       String methodExResolverName = readerContext.registerWithGeneratedName(methodExceptionResolver);
       //15.ResponseStatusExceptionResolver
       RootBeanDefinition statusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
       statusExceptionResolver.setSource(source);
       statusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       statusExceptionResolver.getPropertyValues().add("order", 1);
       String statusExResolverName = readerContext.registerWithGeneratedName(statusExceptionResolver);
       //16.DefaultHandlerExceptionResolver
       RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
       defaultExceptionResolver.setSource(source);
       defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       defaultExceptionResolver.getPropertyValues().add("order", 2);
       String defaultExResolverName = readerContext.registerWithGeneratedName(defaultExceptionResolver);

       context.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
       context.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
       context.registerComponent(new BeanComponentDefinition(uriContributorDef, uriContributorName));
       context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, mappedInterceptorName));
       context.registerComponent(new BeanComponentDefinition(methodExceptionResolver, methodExResolverName));
       context.registerComponent(new BeanComponentDefinition(statusExceptionResolver, statusExResolverName));
       context.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExResolverName));

       // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
       MvcNamespaceUtils.registerDefaultComponents(context, source);

       context.popAndRegisterContainingComponent();

       return null;
   }

二、DispatcherServlet 核心类

  1. HttpServletBean

  主要做一些初始化的工作,将web.xml中配置的参数设置到Servlet中。比如servlet标签的子标签init-param标签中配置的参数。

  1. FrameworkServlet

  将Servlet与Spring容器上下文关联。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文,它有个父类上下文,既web.xml中配置的ContextLoaderListener监听器初始化的容器上下文

DispatcherServlet覆写了FrameworkServlet中的onRefresh方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    protected void onRefresh(ApplicationContext context) {
        this.initStrategies(context);
    }

    protected void initStrategies(ApplicationContext context) {
        //上传文件
        this.initMultipartResolver(context);
        //LocaleResolver
        this.initLocaleResolver(context);
        //ThemeResolver
        this.initThemeResolver(context);
        //RequestMappingHandlerMapping
        this.initHandlerMappings(context);
        //RequestMappingHandlerAdapter
        this.initHandlerAdapters(context);
        //HandlerExceptionResolver
        this.initHandlerExceptionResolvers(context);
        //RequestToViewNameTranslator
        this.initRequestToViewNameTranslator(context);
        //ViewResolvers
        this.initViewResolvers(context);
        //FlashMapManager,flashmap的作用是在redirect中传递参数。大家都知道转发 request是不变的,重定向会生成新的request,那传递参数就不能直接用request进行传递
        this.initFlashMapManager(context);
    }

三、RequestMappingHandlerMapping 核心类

RequestMappingHandlerMapping继承InitializingBean,创建对象之后触发InitializingBean.afterPropertiesSet方法

AbstractHandlerMethodMapping.afterPropertiesSet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
  * Detects handler methods at initialization.
  */
 public void afterPropertiesSet() {
     initHandlerMethods();
 }

 /**
  * Scan beans in the ApplicationContext, detect and register handler methods.
  * @see #isHandler(Class)
  * @see #getMappingForMethod(Method, Class)
  * @see #handlerMethodsInitialized(Map)
  */
 protected void initHandlerMethods() {
     if (logger.isDebugEnabled()) {
         logger.debug("Looking for request mappings in application context: " + getApplicationContext());
     }
     //查询所有bean 
     String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
             BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
             getApplicationContext().getBeanNamesForType(Object.class));

     for (String beanName : beanNames) {
         //isHandler抽象方法,RequestMappingHandlerMapping实现,主要判断Controller和RequestMapping注解
         if (isHandler(getApplicationContext().getType(beanName))){
             detectHandlerMethods(beanName);
         }
     }
     //处理钩子
     handlerMethodsInitialized(getHandlerMethods());
 }

1.detectHandlerMethods 创建HandlerMethod,注册Map

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

  protected void detectHandlerMethods(final Object handler) {
      Class<?> handlerType = (handler instanceof String ?
              getApplicationContext().getType((String) handler) : handler.getClass());
      final Class<?> userType = ClassUtils.getUserClass(handlerType);

      Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
              new MethodIntrospector.MetadataLookup<T>() {
                  @Override
                  public T inspect(Method method) {
                      try {
                           //getMappingForMethod抽象方法,RequestMappingHandlerMapping实现,
                           // 作用查找RequestMapping注解,创建RequestMappingInfo,
                          return getMappingForMethod(method, userType);
                      }
                      catch (Throwable ex) {
                          throw new IllegalStateException("Invalid mapping on handler class [" +
                                  userType.getName() + "]: " + method, ex);
                      }
                  }
              });

      if (logger.isDebugEnabled()) {
          logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
      }
      for (Map.Entry<Method, T> entry : methods.entrySet()) {
          Method invocableMethod = AopUtils.selectInvocableMethod(entry.getKey(), userType);
          T mapping = entry.getValue();
          //注册mappingRegistry中
          registerHandlerMethod(handler, invocableMethod, mapping);
      }
  }
  /**
   * Register a handler method and its unique mapping. Invoked at startup for
   * each detected handler method.
   * @param handler the bean name of the handler or the handler instance
   * @param method the method to register
   * @param mapping the mapping conditions associated with the handler method
   * @throws IllegalStateException if another method was already registered
   * under the same mapping
   */
  protected void registerHandlerMethod(Object handler, Method method, T mapping) {
      this.mappingRegistry.register(mapping, handler, method);
  }

(1). RequestMappingHandlerMapping.getMappingForMethod

把RequestMapping注解信息,创建RequestMappingInfo对接包装起来;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
   @Override
   protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
       RequestMappingInfo info = null;
       //查找方法RequestMapping注解
       RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
       if (methodAnnotation != null) {
           RequestCondition<?> methodCondition = getCustomMethodCondition(method);
           info = createRequestMappingInfo(methodAnnotation, methodCondition);
           //查找类RequestMapping注解
           RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
           if (typeAnnotation != null) {
               RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
               //合并RequestMappingInfo
               info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
           }
       }
       return info;
   }
   /**
    * Created a RequestMappingInfo from a RequestMapping annotation.
    */
   protected RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) {
       String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value());
       //getPathMatche()=AntPathMatcher
       return new RequestMappingInfo(
               new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
                       this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions),
               new RequestMethodsRequestCondition(annotation.method()),
               new ParamsRequestCondition(annotation.params()),
               new HeadersRequestCondition(annotation.headers()),
               new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
               new ProducesRequestCondition(annotation.produces(), annotation.headers(), getContentNegotiationManager()),
               customCondition);
   } 	

(2). RequestMappingInfo

RequestCondition接口说明

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface RequestCondition<T> {

 /**
 * 定义将此条件(即当前实例)与另一个条件组合的规则。例如,类和方法的注解RequestMapping组合条件。
 */
 T combine(T other);

 /**
  * 检查此条件是否与给定请求匹配,并返回可能具有针对当前请求定制的内容的新请求条件。
   * 例如,具有URL模式的条件可能会返回一个新条件,该条件包含在顶部以最佳匹配模式排序的匹配模式。
  * @return a condition instance in case of a match;
  * or {@code null} if there is no match
  */
 T getMatchingCondition(HttpServletRequest request);

 /**
  * 将此条件与特定请求的上下文中的另一个条件进行比较。
  * 此方法假设已通过{@link #getMatchingCondition(HttpServletRequest)}获取这两个实例,以确保它们仅具有与当前请求相关的内容。
  */
 int compareTo(T other, HttpServletRequest request);

}
(a). RequestMethodsRequestCondition

保存对象Set;RequestMethod是GET,POST等http方法;

(b). ParamsRequestCondition

Set保存请求参数验证

(c). HeadersRequestCondition

Set保存头请求验证

(d). ConsumesRequestCondition

List保存Content-Type格式

(e). ConsumesRequestCondition

List保存Accept头

(f).PatternsRequestCondition 路径条件匹配,这个相对复杂点

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
 @Override
 public PatternsRequestCondition getMatchingCondition(HttpServletRequest request) {
     if (this.patterns.isEmpty()) {
         return this;
     }
     //获取路径
     String lookupPath = this.pathHelper.getLookupPathForRequest(request);
     List<String> matches = new ArrayList<String>();
     for (String pattern : this.patterns) {
         //AntPathMatcher匹配路径
         String match = getMatchingPattern(pattern, lookupPath);
         if (match != null) {
             matches.add(match);
         }
     }
     //运用AntPathMatcher排序
     Collections.sort(matches, this.pathMatcher.getPatternComparator(lookupPath));
     return matches.isEmpty() ? null :
         new PatternsRequestCondition(matches, this.pathHelper, this.pathMatcher, this.useSuffixPatternMatch,
                 this.useTrailingSlashMatch, this.fileExtensions);
 }

后面具体分析AntPathMatcher

2.MappingRegistry 注册RequestMappingInfo对应HandlerMethod操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
       private final Map<T, MappingRegistration<T>> registry = new HashMap<T, MappingRegistration<T>>();

       private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();

       private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();

       private final Map<String, List<HandlerMethod>> nameLookup =
               new ConcurrentHashMap<String, List<HandlerMethod>>();

       private final Map<HandlerMethod, CorsConfiguration> corsLookup =
               new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();

       private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

(1).register 注册

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public void register(T mapping, Object handler, Method method) {
          this.readWriteLock.writeLock().lock();
          try {
              //1.创建HandlerMethod
              HandlerMethod handlerMethod = createHandlerMethod(handler, method);
              assertUniqueMethodMapping(handlerMethod, mapping);

              if (logger.isInfoEnabled()) {
                  logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
              }
              //2.注册RequestMappingInfo->HandlerMethod
              this.mappingLookup.put(mapping, handlerMethod);
              //3.RequestMappingInfo中Patterns连接不包含*或者?,就注册url->RequestMappingInfo
              List<String> directUrls = getDirectUrls(mapping);
              for (String url : directUrls) {
                  this.urlLookup.add(url, mapping);
              }
              //
              String name = null;
              if (getNamingStrategy() != null) {
                  name = getNamingStrategy().getName(handlerMethod, mapping);
                  addMappingName(name, handlerMethod);
              }
              //4.Cors配置
              CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
              if (corsConfig != null) {
                  this.corsLookup.put(handlerMethod, corsConfig);
              }
              //4.RequestMappingInfo-->MappingRegistration
              this.registry.put(mapping, new MappingRegistration<T>(mapping, handlerMethod, directUrls, name));
          }
          finally {
              this.readWriteLock.writeLock().unlock();
          }
      }

3.AbstractHandlerMapping.getHandler获取HandlerExecutionChain对象

HandlerExecutionChain包含处理HandlerInterceptor集合和RequestMappingInfo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   @Override
   public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
       Object handler = getHandlerInternal(request);
       if (handler == null) {
           handler = getDefaultHandler();
       }
       if (handler == null) {
           return null;
       }
       // Bean name or resolved handler?
       if (handler instanceof String) {
           String handlerName = (String) handler;
           handler = getApplicationContext().getBean(handlerName);
       }
       //添加HandlerInterceptor,MappedInterceptor按路径匹配,
       HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
       //处理Cors跨越;
       if (CorsUtils.isCorsRequest(request)) {
           CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
           CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
           CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
           executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
       }
       return executionChain;
   }

(1).lookupHandlerMethod 查找HandlerMethod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
   protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
       List<Match> matches = new ArrayList<Match>();
       //按Url查询RequestMappingInfo集合
       List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
       if (directPathMatches != null) {
           //验证RequestCondition,获取HandlerMethod
           addMatchingMappings(directPathMatches, matches, request);
       }
       if (matches.isEmpty()) {
           // No choice but to go through all mappings...
           //别无选择,只能通过所有映射......
           addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
       }

       if (!matches.isEmpty()) {
           //按RequestMappingInfo排序
           Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
           Collections.sort(matches, comparator);
           if (logger.isTraceEnabled()) {
               logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
                       lookupPath + "] : " + matches);
           }
           //获取第一个RequestMappingInfo
           Match bestMatch = matches.get(0);
           if (matches.size() > 1) {
               //valid CORS pre-flight
               if (CorsUtils.isPreFlightRequest(request)) {
                   return PREFLIGHT_AMBIGUOUS_MATCH;
               }
               Match secondBestMatch = matches.get(1);
               //比较
               if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                   Method m1 = bestMatch.handlerMethod.getMethod();
                   Method m2 = secondBestMatch.handlerMethod.getMethod();
                   throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                           request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
               }
           }
           //找到匹配的URL
           handleMatch(bestMatch.mapping, lookupPath, request);
           return bestMatch.handlerMethod;
       }
       else {
           return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
       }
   }

四、RequestMappingHandlerAdapter 核心类

实现InitializingBean接口,触发afterPropertiesSet()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
  public void afterPropertiesSet() {
      if (this.argumentResolvers == null) {
          List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
          this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
      }
      if (this.initBinderArgumentResolvers == null) {
          List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
          this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
      }
      if (this.returnValueHandlers == null) {
          List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
          this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
      }
      //@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中
      //扫描所有ControllerAdvice注解,缓存@InitBinder、@ModelAttribute
      initControllerAdviceCache();
  }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   protected List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
       List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

       // Annotation-based argument resolution
       //解析方法参数SessionAttribute注解
       resolvers.add(new SessionAttributeMethodArgumentResolver());
       //解析方法参数RequestAttribute注解
       resolvers.add(new RequestAttributeMethodArgumentResolver());

       // Type-based argument resolution
       //基于类型的参数解析
       //ServletRequest,WebRequest等
       resolvers.add(new ServletRequestMethodArgumentResolver());
       //ServletResponse,OutputStream等
       resolvers.add(new ServletResponseMethodArgumentResolver());
       //RedirectAttributes参数
       resolvers.add(new RedirectAttributesMethodArgumentResolver());
       //Model参数
       resolvers.add(new ModelMethodProcessor());

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

       return resolvers;
   }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
       List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

       // Annotation-based argument resolution
       //基于注释的参数解析
       //@RequestParam
       resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
       //@RequestParam,参数是MAP
       resolvers.add(new RequestParamMapMethodArgumentResolver());
       //PathVariable
       resolvers.add(new PathVariableMethodArgumentResolver());
       //PathVariable,参数Map
       resolvers.add(new PathVariableMapMethodArgumentResolver());
       //MatrixVariable;/path;name=value;name=value以;解析值
       resolvers.add(new MatrixVariableMethodArgumentResolver());
       //MatrixVariable Map
       resolvers.add(new MatrixVariableMapMethodArgumentResolver());
       //Value注解,EL表达式
       resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
       //SessionAttribute
       resolvers.add(new SessionAttributeMethodArgumentResolver());
       //RequestAttribute
       resolvers.add(new RequestAttributeMethodArgumentResolver());

       // Type-based argument resolution
       //ServletRequest,WebRequest等
       resolvers.add(new ServletRequestMethodArgumentResolver());
       //ServletResponse,OutputStream等
       resolvers.add(new ServletResponseMethodArgumentResolver());

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

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

       return resolvers;
   }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   protected List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
       List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();

       // Single-purpose return value types
       //ModelAndView返回类型
       handlers.add(new ModelAndViewMethodReturnValueHandler());
       //Model
       handlers.add(new ModelMethodProcessor());
       //View
       handlers.add(new ViewMethodReturnValueHandler());
       //解析{@link HttpEntity}和{@link RequestEntity}方法参数值,并处理{@link HttpEntity}和{@link ResponseEntity}返回值。
       handlers.add(new HttpEntityMethodProcessor(
               getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));

       // Annotation-based return value types
       //ModelAttribute注解
       handlers.add(new ModelAttributeMethodProcessor(false));
       //解析用{@code @RequestBody}注释的方法参数,并通过使用{@link HttpMessageConverter}读取和
       // 写入请求或响应的主体来处理来自使用{@code @ResponseBody}注释的方法的返回值
       handlers.add(new RequestResponseBodyMethodProcessor(
               getMessageConverters(), this.contentNegotiationManager, this.responseBodyAdvice));

       // Multi-purpose return value types
       //处理类型{@code void}和{@code String}的返回值,将它们解释为视图名称引用。
       // 从4.2开始,它还处理一般的{@code CharSequence} 类型,例如, {@code StringBuilder}或Groovy的{@code GString},作为视图名称。
       handlers.add(new ViewNameMethodReturnValueHandler());
       //解析{@link Map}方法参数并处理{@link Map}返回值。
       handlers.add(new MapMethodProcessor());

       // Custom return value types
       if (getCustomReturnValueHandlers() != null) {
           handlers.addAll(getCustomReturnValueHandlers());
       }

       // Catch-all
       handlers.add(new ModelAttributeMethodProcessor(true));

       return handlers;
   }

1、HandlerMethodArgumentResolver 用于将方法参数解析为给定请求的上下文中的参数值的策略接口。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public interface HandlerMethodArgumentResolver {

   /**
    * Whether the given {@linkplain MethodParameter method parameter} is
    * supported by this resolver.
    * 此解析程序是否支持给定的{@linkplain MethodParameter方法参数}。
    * @param parameter the method parameter to check
    * @return {@code true} if this resolver supports the supplied parameter;
    * {@code false} otherwise
    */
   boolean supportsParameter(MethodParameter parameter);

   /**
    * Resolves a method parameter into an argument value from a given request.
    * A {@link ModelAndViewContainer} provides access to the model for the
    * request. A {@link WebDataBinderFactory} provides a way to create
    * a {@link WebDataBinder} instance when needed for data binding and
    * type conversion purposes.
    * 将方法参数解析为来自给定请求的参数值。  {@link ModelAndViewContainer}提供对请求模型的访问。
    * {@link WebDataBinderFactory}提供了一种在需要进行数据绑定和类型转换时创建{@link WebDataBinder}实例的方法。
    * @param parameter the method parameter to resolve. This parameter must
    * have previously been passed to {@link #supportsParameter} which must
    * have returned {@code true}.
    * @param mavContainer the ModelAndViewContainer for the current request
    * @param webRequest the current request
    * @param binderFactory a factory for creating {@link WebDataBinder} instances
    * @return the resolved argument value, or {@code null}
    * @throws Exception in case of errors with the preparation of argument values
    */
   Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
           NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;

AbstractNamedValueMethodArgumentResolver抽象类实现HandlerMethodArgumentResolver接口,主要处理resolveArgument方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
private final Map<MethodParameter, NamedValueInfo> namedValueInfoCache =
           new ConcurrentHashMap<MethodParameter, NamedValueInfo>(256);
   @Override
   public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
           NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
       //1.创建NamedValueInfo,缓存到namedValueInfoCache中
       NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
       //2.嵌套MethodParameter
       MethodParameter nestedParameter = parameter.nestedIfOptional();
      // 解析给定的注释指定值,可能包含占位符和表达式。
       Object resolvedName = resolveStringValue(namedValueInfo.name);
       if (resolvedName == null) {
           throw new IllegalArgumentException(
                   "Specified name must not resolve to null: [" + namedValueInfo.name + "]");
       }
       //3.将给定的参数类型和值名称解析为参数值。抽象方法
       Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
       if (arg == null) {
           //参数值为空,默认不为空,设置默认值;
           if (namedValueInfo.defaultValue != null) {
               arg = resolveStringValue(namedValueInfo.defaultValue);
           }
           else if (namedValueInfo.required && !nestedParameter.isOptional()) {
               handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
           }
           //判断参数类型是否bool,参数值为空,默认设置为false
           arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
       }
       else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
           arg = resolveStringValue(namedValueInfo.defaultValue);
       }

       if (binderFactory != null) {
           //4.创建绑定类型
           WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
           try {
               //解析类型值
               arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
           }
           catch (ConversionNotSupportedException ex) {
               throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
                       namedValueInfo.name, parameter, ex.getCause());
           }
           catch (TypeMismatchException ex) {
               throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
                       namedValueInfo.name, parameter, ex.getCause());

           }
       }
       //5.钩子方法
       handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);

       return arg;
   }

2.HandlerMethodReturnValueHandler 用于处理从处理程序方法调用返回的值的策略接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public interface HandlerMethodReturnValueHandler {

   /**
    * Whether the given {@linkplain MethodParameter method return type} is
    * supported by this handler.
    * 此处理程序是否支持给定的{@linkplain MethodParameter方法返回类型}。
    * @param returnType the method return type to check
    * @return {@code true} if this handler supports the supplied return type;
    * {@code false} otherwise
    */
   boolean supportsReturnType(MethodParameter returnType);

   /**
    * Handle the given return value by adding attributes to the model and
    * setting a view or setting the
    * {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
    * to indicate the response has been handled directly.
    * 通过向模型添加属性并设置视图或将{@link ModelAndViewContainer #setRequestHandled}标志设置为{@code true}来处理给定的返回值,
    * 以指示响应已被直接处理。
    * @param returnValue the value returned from the handler method
    * @param returnType the type of the return value. This type must have
    * previously been passed to
    * {@link #supportsReturnType(org.springframework.core.MethodParameter)}
    * and it must have returned {@code true}
    * @param mavContainer the ModelAndViewContainer for the current request
    * @param webRequest the current request
    * @throws Exception if the return value handling results in an error
    */
   void handleReturnValue(Object returnValue, MethodParameter returnType,
           ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}

3.HandlerAdapter 核心接口,处理执行方法返回ModelAndView

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

public interface HandlerAdapter {

   /**
    * Given a handler instance, return whether or not this {@code HandlerAdapter}
    * can support it. Typical HandlerAdapters will base the decision on the handler
    * type. HandlerAdapters will usually only support one handler type each.
    * 给定一个处理程序实例,返回此{@code HandlerAdapter}是否可以支持它。
    * 典型的HandlerAdapters将根据处理程序类型做出决定。HandlerAdapters通常每个只支持一种处理程序类型。
    * <p>A typical implementation:
    * <p>{@code
    * return (handler instanceof MyHandler);
    * }
    * @param handler handler object to check
    * @return whether or not this object can use the given handler
    */
   boolean supports(Object handler);

   /**
    * Use the given handler to handle this request.
    * 使用给定的处理程序来处理此请求
    * The workflow that is required may vary widely.
    * @param request current HTTP request
    * @param response current HTTP response
    * @param handler handler to use. This object must have previously been passed
    * to the {@code supports} method of this interface, which must have
    * returned {@code true}.
    * @throws Exception in case of errors
    * @return ModelAndView object with the name of the view and the required
    * model data, or {@code null} if the request has been handled directly
    */
   ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

   /**
    * Same contract as for HttpServlet's {@code getLastModified} method.
    * Can simply return -1 if there's no support in the handler class.
    * 与HttpServlet的{@code getLastModified}方法相同的。 如果处理程序类中没有支持,可以简单地返回-1。
    * @param request current HTTP request
    * @param handler handler to use
    * @return the lastModified value for the given handler
    * @see javax.servlet.http.HttpServlet#getLastModified
    * @see org.springframework.web.servlet.mvc.LastModified#getLastModified
    */
   long getLastModified(HttpServletRequest request, Object handler);

}

(1).supports

AbstractHandlerMethodAdapter

1
2
3
4
5
6
   @Override
   public final boolean supports(Object handler) {
       //supportsInternal子类实现
       return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
   }

(2).handle

AbstractHandlerMethodAdapter

1
2
3
4
5
6
  @Override
  public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
          throws Exception {
      //子类执行,RequestMappingHandlerAdapter
      return handleInternal(request, response, (HandlerMethod) handler);
  }

RequestMappingHandlerAdapter

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   @Override
   protected ModelAndView handleInternal(HttpServletRequest request,
           HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

       ModelAndView mav;
       //验证requset方法和session
       checkRequest(request);

       // Execute invokeHandlerMethod in synchronized block if required.
       //如果需要,在synchronized块中执行invokeHandlerMethod。
       if (this.synchronizeOnSession) {
           HttpSession session = request.getSession(false);
           if (session != null) {
               Object mutex = WebUtils.getSessionMutex(session);
               synchronized (mutex) {
                   mav = invokeHandlerMethod(request, response, handlerMethod);
               }
           }
           else {
               // No HttpSession available -> no mutex necessary
               mav = invokeHandlerMethod(request, response, handlerMethod);
           }
       }
       else {
           // No synchronization on session demanded at all...
           mav = invokeHandlerMethod(request, response, handlerMethod);
       }

       if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
           if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
               applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
           }
           else {
               prepareResponse(response);
           }
       }

       return mav;
   }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
           HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        
       ServletWebRequest webRequest = new ServletWebRequest(request, response);
       try {
           //1.创建ServletRequestDataBinderFactory,这里处理绑定,先从类查找@InitBinder,在从ControllerAdvice注解中InitBinder
           WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
           //2.创建ModelFactory,这里对象模型,先从类查找@ModelAttribute,在从ControllerAdvice注解中ModelAttribute
           ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
           //3.创建ServletInvocableHandlerMethod
           ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
           invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
           invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
           invocableMethod.setDataBinderFactory(binderFactory);
           invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
           //4.创建ModelAndViewContainer
           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;
           }
            //获取ModelAndView
           return getModelAndView(mavContainer, modelFactory, webRequest);
       }
       finally {
           webRequest.requestCompleted();
       }
   }

ServletInvocableHandlerMethod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //1.处理方法的参数,执行方法
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		//根据{@link ResponseStatus}注释设置响应状态
		setResponseStatus(webRequest);
        //执行方法返回结果为空或者响应状态不为空,不做解析返回结果
		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		try {
		    //处理执行方法返回结果
			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;
		}
	}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
	public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //执行HandlerMethodArgumentResolver处理解析方法参数
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
					"' with arguments " + Arrays.toString(args));
		}
		//执行方法返回结果
		Object returnValue = doInvoke(args);
		if (logger.isTraceEnabled()) {
			logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
					"] returned [" + returnValue + "]");
		}
		return returnValue;
	}

4.ViewResolver 按名称解析视图的对象实现的接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
   /**
    * Resolve the given view by name.
    * <p>Note: To allow for ViewResolver chaining, a ViewResolver should
    * return {@code null} if a view with the given name is not defined in it.
    * However, this is not required: Some ViewResolvers will always attempt
    * to build View objects with the given name, unable to return {@code null}
    * (rather throwing an exception when View creation failed).
    * 按名称解析视图
    * @param viewName name of the view to resolve
    * @param locale Locale in which to resolve the view.
    * ViewResolvers that support internationalization should respect this.
    * @return the View object, or {@code null} if not found
    * (optional, to allow for ViewResolver chaining)
    * @throws Exception if the view cannot be resolved
    * (typically in case of problems creating an actual View object)
    */
   View resolveViewName(String viewName, Locale locale) throws Exception;

View接口是MVC查看Web交互;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public interface View {

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains the response status code.
	 * <p>Note: This attribute is not required to be supported by all View implementations.
	 * @since 3.0
	 */
	String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";

	/**
	 * Name of the {@link HttpServletRequest} attribute that contains a Map with path variables.
	 * The map consists of String-based URI template variable names as keys and their corresponding
	 * Object-based values -- extracted from segments of the URL and type converted.
	 * <p>Note: This attribute is not required to be supported by all View implementations.
	 * @since 3.1
	 */
	String PATH_VARIABLES = View.class.getName() + ".pathVariables";

	/**
	 * The {@link org.springframework.http.MediaType} selected during content negotiation,
	 * which may be more specific than the one the View is configured with. For example:
	 * "application/vnd.example-v1+xml" vs "application/*+xml".
	 * @since 3.2
	 */
	String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";


	/**
	 * Return the content type of the view, if predetermined.
	 * <p>Can be used to check the view's content type upfront,
	 * i.e. before an actual rendering attempt.
	 * @return the content type String (optionally including a character set),
	 * or {@code null} if not predetermined
	 */
	String getContentType();

	/**
	 * Render the view given the specified model.
	 * <p>The first step will be preparing the request: In the JSP case, this would mean
	 * setting model objects as request attributes. The second step will be the actual
	 * rendering of the view, for example including the JSP via a RequestDispatcher.
	 * 给定指定模型的视图。 , <p>第一步是准备请求:在JSP情况下,这意味着将模型对象设置为请求属性。
	  * 第二步是视图的实际呈现,例如通过RequestDispatcher包含JSP。
	 * @param model Map with name Strings as keys and corresponding model
	 * objects as values (Map can also be {@code null} in case of empty model)
	 * @param request current HTTP request
	 * @param response HTTP response we are building
	 * @throws Exception if rendering failed
	 */
	void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

}

例如:

1
2
3
4
5
6
7
8
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix">
           <value>/WEB-INF/view/</value>
       </property>
       <property name="suffix">
           <value>.jsp</value>
       </property>
   </bean>

1.InternalResourceViewResolver 构造

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
   public InternalResourceViewResolver() {
       // InternalResourceView
       Class<?> viewClass = requiredViewClass();
       //jstl配置
       if (InternalResourceView.class == viewClass && jstlPresent) {
           viewClass = JstlView.class;
       }
       //设置viewClass
       setViewClass(viewClass);
   }

2.resolveViewName 方法

AbstractCachingViewResolver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  @Override
  public View resolveViewName(String viewName, Locale locale) throws Exception {
     //是否缓存,默认是缓存
      if (!isCache()) {
          return createView(viewName, locale);
      }
      else {
          //key: viewName+"_"+locale
          Object cacheKey = getCacheKey(viewName, locale);
          View view = this.viewAccessCache.get(cacheKey);
          if (view == null) {
              synchronized (this.viewCreationCache) {
                  view = this.viewCreationCache.get(cacheKey);
                  if (view == null) {
                      // Ask the subclass to create the View object.
                      //createView抽象方法,子类实现
                      view = createView(viewName, locale);
                      if (view == null && this.cacheUnresolved) {
                          view = UNRESOLVED_VIEW;
                      }
                      if (view != null) {
                          this.viewAccessCache.put(cacheKey, view);
                          this.viewCreationCache.put(cacheKey, view);
                          if (logger.isTraceEnabled()) {
                              logger.trace("Cached view [" + cacheKey + "]");
                          }
                      }
                  }
              }
          }
          return (view != UNRESOLVED_VIEW ? view : null);
      }
  }

UrlBasedViewResolver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
	@Override
	protected View createView(String viewName, Locale locale) throws Exception {
		// If this resolver is not supposed to handle the given view,
		// return null to pass on to the next resolver in the chain.
		//如果此解析程序不应处理给定视图,则返回null以传递给链中的下一个解析程序。
		if (!canHandle(viewName, locale)) {
			return null;
		}

		// Check for special "redirect:" prefix.
		//检查特殊的“redirect:”前缀。
		if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
			String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
			RedirectView view = new RedirectView(redirectUrl,
					isRedirectContextRelative(), isRedirectHttp10Compatible());
			view.setHosts(getRedirectHosts());
			//初始化initializeBean
			return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
		}

		// Check for special "forward:" prefix.
		//检查特殊的“forward:”前缀。
		if (viewName.startsWith(FORWARD_URL_PREFIX)) {
			String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
			return new InternalResourceView(forwardUrl);
		}

		// Else fall back to superclass implementation: calling loadView.
		//否则回退到超类实现:调用loadView。
		return super.createView(viewName, locale);
	}

UrlBasedViewResolver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   @Override
   protected View loadView(String viewName, Locale locale) throws Exception 
       //创建InternalResourceView
       AbstractUrlBasedView view = buildView(viewName);
       View result = applyLifecycleMethods(viewName, view);
       return (view.checkResource(locale) ? result : null);
   }
   
   protected AbstractUrlBasedView buildView(String viewName) throws Exception {
       //创建InternalResourceView
       AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
       //添加前缀,添加后缀
       view.setUrl(getPrefix() + viewName + getSuffix());
       //添加内容类型
       String contentType = getContentType();
       if (contentType != null) {
           view.setContentType(contentType);
       }

       view.setRequestContextAttribute(getRequestContextAttribute());
       view.setAttributesMap(getAttributesMap());
       //解析程序解析的视图是否应将路径变量添加到模型中。
       Boolean exposePathVariables = getExposePathVariables();
       if (exposePathVariables != null) {
           view.setExposePathVariables(exposePathVariables);
       }
       //设置是否允许应用程序上下文中的所有Spring bean作为请求属性访问*,一旦访问了属性,通过延迟检查。
       // <p>这将使所有这些bean在JSP 2.0页面中的普通{@code $ {...}} 表达式以及JSTL的{@code c:out} 值表达式中可访问。 <p>默认为“false”。
       Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
       if (exposeContextBeansAsAttributes != null) {
           view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes);
       }
       //在上下文中指定应该公开的bean的名称。如果这是非null,则只有指定的bean才有资格作为属性公开。		
       String[] exposedContextBeanNames = getExposedContextBeanNames();
       if (exposedContextBeanNames != null) {
           view.setExposedContextBeanNames(exposedContextBeanNames);
       }		
       

3.InternalResourceView的render

AbstractView

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
   @Override
   public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
       if (logger.isTraceEnabled()) {
           logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
               " and static attributes " + this.staticAttributes);
       }

       Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
       prepareResponse(request, response);
       renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
   }

InternalResourceView

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

/**
	 * Render the internal resource given the specified model.
	 * This includes setting the model as request attributes.
	 */
	@Override
	protected void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Expose the model object as request attributes.
		//将模型对象公开为请求属性。
		exposeModelAsRequestAttributes(model, request);

		// Expose helpers as request attributes, if any.
		//这里只是钩子方法
		exposeHelpers(request);

		// Determine the path for the request dispatcher.
		//确定请求调度程序的路径。
		String dispatcherPath = prepareForRendering(request, response);

		// Obtain a RequestDispatcher for the target resource (typically a JSP).
		//获取目标资源(通常是JSP)的RequestDispatcher。
		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
		if (rd == null) {
			throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
					"]: Check that the corresponding file exists within your web application archive!");
		}

		// If already included or response already committed, perform include, else forward.
		//如果已经包含或响应已经提交,请执行include,否 forward。
		if (useInclude(request, response)) {// 判断javax.servlet.include.request_uri
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
			rd.include(request, response);
		}

		else {
			// Note: The forwarded resource is supposed to determine the content type itself.
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
			rd.forward(request, response);
		}
	}

4.HandlerExceptionResolver 异常解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface HandlerExceptionResolver {

   /**
    * Try to resolve the given exception that got thrown during handler execution,
    * returning a {@link ModelAndView} that represents a specific error page if appropriate.
    * <p>The returned {@code ModelAndView} may be {@linkplain ModelAndView#isEmpty() empty}
    * to indicate that the exception has been resolved successfully but that no view
    * should be rendered, for instance by setting a status code.
    * 尝试解决在处理程序执行期间抛出的给定异常,返回表示特定错误页面的{@link ModelAndView}(如果适用)。
     * <p>返回的{@code ModelAndView}可能是{@linkplain ModelAndView#isEmpty()empty},表示异常已成功解析,
     * 但不应呈现任何视图,例如通过设置状态代码。
    * @param request current HTTP request
    * @param response current HTTP response
    * @param handler the executed handler, or {@code null} if none chosen at the
    * time of the exception (for example, if multipart resolution failed)
    * @param ex the exception that got thrown during handler execution
    * @return a corresponding {@code ModelAndView} to forward to,
    * or {@code null} for default processing in the resolution chain
    */
   ModelAndView resolveException(
           HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

}

AbstractHandlerExceptionResolver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
   @Override
   public ModelAndView resolveException(
           HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

       if (shouldApplyTo(request, handler)) {
           prepareResponse(ex, response);
           ModelAndView result = doResolveException(request, response, handler, ex);
           if (result != null) {
               // Print warn message when warn logger is not enabled...
               if (logger.isWarnEnabled() && (this.warnLogger == null || !this.warnLogger.isWarnEnabled())) {
                   logger.warn("Resolved [" + ex + "]" + (result.isEmpty() ? "" : " to " + result));
               }
               // warnLogger with full stack trace (requires explicit config)
               logException(ex, request);
           }
           return result;
       }
       else {
           return null;
       }
   }

ExceptionHandlerExceptionResolver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

	/**
	 * Find an {@code @ExceptionHandler} method and invoke it to handle the raised exception.
	 */
	@Override
	protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
        //创建ServletInvocableHandlerMethod
        // 1.先从类中@ExceptionHandler注解方法
        // 2.在从@ControllerAdvice查找
		ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
		if (exceptionHandlerMethod == null) {
			return null;
		}

		exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();

		try {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking @ExceptionHandler method: " + exceptionHandlerMethod);
			}
			Throwable cause = exception.getCause();
			if (cause != null) {
				// Expose cause as provided argument as well
				//执行异常方法
				exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);
			}
			else {
				// Otherwise, just the given exception as-is
				exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);
			}
		}
		catch (Throwable invocationEx) {
			// Any other than the original exception is unintended here,
			// probably an accident (e.g. failed assertion or the like).
			if (invocationEx != exception && logger.isWarnEnabled()) {
				logger.warn("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
			}
			// Continue with default processing of the original exception...
			return null;
		}
        //创建ModelAndView
		if (mavContainer.isRequestHandled()) {
			return new ModelAndView();
		}
		else {
			ModelMap model = mavContainer.getModel();
			HttpStatus status = mavContainer.getStatus();
			ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
			mav.setViewName(mavContainer.getViewName());
			if (!mavContainer.isViewReference()) {
				mav.setView((View) mavContainer.getView());
			}
			if (model instanceof RedirectAttributes) {
				Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
			return mav;
		}
	}

ResponseStatusExceptionResolver

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
   @Override
   protected ModelAndView doResolveException(
           HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
       //处理异常类ResponseStatus注解信息
       ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);
       if (status != null) {
           try {
               return resolveResponseStatus(status, request, response, handler, ex);
           }
           catch (Exception resolveEx) {
               logger.warn("ResponseStatus handling resulted in exception", resolveEx);
           }
       }
       else if (ex.getCause() instanceof Exception) {
           ex = (Exception) ex.getCause();
           return doResolveException(request, response, handler, ex);
       }
       return null;
   }

5.DispatcherServlet doDispatch方法,处理http请求

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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;
          Exception dispatchException = null;

          try {
              //验证文件上传
              processedRequest = checkMultipart(request);
              multipartRequestParsed = (processedRequest != request);

              // Determine handler for the current request.
              //1.通过http的url查找MapperHander,找到HandlerExecutionChain对象,对象中包含拦截器集合和HandlerMethod
              mappedHandler = getHandler(processedRequest);
              if (mappedHandler == null || mappedHandler.getHandler() == null) {
                  noHandlerFound(processedRequest, response);
                  return;
              }

              // Determine handler adapter for the current request.
              //2.通过HandlerMethod找到相应HandlerAdapter
              HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

              // 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;
                  }
              }
              //3.处理拦截applyPreHandle
              if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                  return;
              }

              // Actually invoke the handler.
              //4.通过HandlerAdapter执行方法,返回ModelView
              mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

              if (asyncManager.isConcurrentHandlingStarted()) {
                  return;
              }

              applyDefaultViewName(processedRequest, mv);
              //4.处理拦截applyPostHandle
              mappedHandler.applyPostHandle(processedRequest, response, mv);
          }
          catch (Exception ex) {
              dispatchException = ex;
          }
          catch (Throwable err) {
              // As of 4.3, we're processing Errors thrown from handler methods as well,
              // making them available for @ExceptionHandler methods and other scenarios.
              dispatchException = new NestedServletException("Handler dispatch failed", err);
          }
          //下面说明方法中说明
          processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
      }
      catch (Exception ex) {
          //出现异常,也要处理拦截afterCompletion
          triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
      }
      catch (Throwable err) {
          //出现异常,也要处理拦截afterCompletion
          triggerAfterCompletion(processedRequest, response, mappedHandler,
                  new NestedServletException("Handler processing failed", 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);
              }
          }
      }
  }

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
   /**
    * Handle the result of handler selection and handler invocation, which is
    * either a ModelAndView or an Exception to be resolved to a ModelAndView.
    */
   private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
           HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

       boolean errorView = false;
       //5.处理异常 
       if (exception != null) {
           if (exception instanceof ModelAndViewDefiningException) {
               logger.debug("ModelAndViewDefiningException encountered", exception);
               mv = ((ModelAndViewDefiningException) exception).getModelAndView();
           }
           else {
               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()) {
           //6.通过ModelView查找相应ViewResolver,在通过ViewResolver解析获取View
           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) {
           //7.处理拦截afterCompletion
           mappedHandler.triggerAfterCompletion(request, response, null);
       }
   }