前面已经研究过spring mvc的简单流程:

  1. 根据request,从RequestMapping中获取handler
  2. 使用HandlerAdapter执行handler
  3. 使用执行结果,渲染视图

我们要研究的RequestMappingRequestMappingHandlerMapping,HandlerAdapterRequestMappingHandlerAdapter.

RequestMappingHandlerMapping获取handler

###初始化RequestMappingHandlerMapping

RequestMappingHandlerMapping实现了InitializingBean接口,当其被实例化完成,参数注入完成之后会调用afterPropertiesSet方法.
这个方法会遍历ApplicationContext中的所有BeanDefinition,找到所有的handler.那么什么样的类才算是handler呢?看下面代码:

protected boolean isHandler(Class<?> beanType) {
	return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
			(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
}

类头上顶着@Controller或者@RequestMapping的才算handler.
找到handler以后,会遍历寻找其下属的HandlerMethod.问题又来了,怎样的方法才算是HandlerMethod呢?看下面代码:

protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
	RequestMappingInfo info = null;
	RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
	if (methodAnnotation != null) {
		RequestCondition<?> methodCondition = getCustomMethodCondition(method);
		info = createRequestMappingInfo(methodAnnotation, methodCondition);
		RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
		if (typeAnnotation != null) {
			RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
			info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
		}
	}
	return info;
}

如果方法签名上有@RequestMapping,则根据注解信息创建RequestMappingInfo,接着判断所属类的类签名是否有@RequestMapping,有的话,将类签名中包含的mapping信息合并到刚才的RequestMappingInfo中,然后返回.

通过该方法后返回结果RequestMappingInfo不为null的,就是可用的HandlerMethod.然后就是把Method转成HandlerMethod,此处只需要简单封装一下就OK了.接着通过RequestMappingInfo分析出对应的URL模式(该模式使用的是类Ant的匹配语法).最后将URLRequestMappingInfo的对应关系,RequestMappingInfoHandlerMethod的对应关系放入两个Map中(其中URL的Map是一个MultiValueMap),留待后面使用.

###请求(Request)到来

Request到来的时候,先从Request中解析出请求的地址URL.然后根据地址去urlMap中查找,如果没找到的话,就遍历handlerMethods中所有的RequestMappingInfo,进行匹配.如果找到则返回对应的RequestMethod.如果找不到则执行handleNoMatch方法,这个方法会针对找不到的原因进行分析,必要的话抛出一大堆的异常来提醒开发者.

找到HandlerMethod之后,将其封装为HandlerExecutionChain,封装过程就是new HandlerExecutionChain(handler),然后把符合本次请求Url模式的HandlerInterceptor添加到HandlerExecutionChain里面,最后返回.
对于HandlerExecutionChain,这是DispatcherServlet要用到的,我们真正需要的还是HandlerMethod. 对于HandlerMethod的具体执行请看下面,因为spring mvc中对HandlerMethod的调用不是在HandlerMapping中进行的,而是通过HandlerAdapter进行的.

RequestMappingHandlerAdapter执行handler

###初始化RequestMappingHandlerAdapter

首先在构造其中对messageConverters做了初始化:

this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
this.messageConverters.add(new ByteArrayHttpMessageConverter());

StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316

this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());

这个类也实现了InitializingBean,同样有afterPropertiesSet方法,该方法做的工作如下:

  • 初始化argumentResolvers 默认加载的HandlerMethodArgumentResolver如下:
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));

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

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

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

其中包括了自定义的ArgumentResolver.

  • 初始化initBinderArgumentResolvers 默认加载的HandlerMethodArgumentResolver如下:
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));

// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());

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

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

其中包含了自定义的内容.注意这里的自定义跟argumentResolvers的是同一个方法.

  • 初始化returnValueHandlers 默认加载HandlerMethodReturnValueHandler如下:
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
handlers.add(new HttpHeadersReturnValueHandler());
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));

// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());

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

// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
	handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
	handlers.add(new ModelAttributeMethodProcessor(true));
}

其中包含了自定义的内容.

###执行handler

RequestMappingHandlerAdapterHandlerAdapter的子类.HandlerAdapter接口的内容如下:

public interface HandlerAdapter {

	boolean supports(Object handler);

	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

	long getLastModified(HttpServletRequest request, Object handler);
}

本文我们要关注的主要是supportshandle两个方法.support是用来判断一个handler是否能被该adapter处理的.handle方法是用来实际处理handler的.

RequestMappingHandlerAdaptersupport方法代码如下:

public final boolean supports(Object handler) {
	return handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler);
}
protected boolean supportsInternal(HandlerMethod handlerMethod) {
	return true;
}

这个没什么好解释的,只要handlerHandlerMethod的实例,RequestMappingHandlerAdapter都会接受.

RequestMappingHandlerAdapterhandle方法就没这么简单了.梳理后的执行逻辑如下:

  1. 构建WebDataBinderFactory对象binderFactory.根据HandlerMethod, binderFactory, argumentResolvers, returnValueHandlers构建 ServletInvocableHandlerMethod的对象requestMappingMethod
  2. 构建ModelAndViewContainer的对象mavContainer,并进行一些特殊的设置.
  3. 调用方法requestMappingMethod.invokeAndHandle(webRequest, mavContainer).
    这个方法调,我们所关心的主要有三块:
  1. InvocableHandlerMethod#getMethodArgumentValues,该方法作用是:为被调用的方法准备参数,比如Model,各种Request以及@RequestParam,@RequestEntity等各种注解. 这些参数是使用从RequestMappingHandlerMapping中传过来的argumentResolvers进行处理的(原理就是遍历其中所有的HandlerMethodArgumentResolver,谁支持谁上).
  2. InvocableHandlerMethod#invoke,该方法就是通过反射进行方法调用,并返回结果. (此处涉及到了Java中的Bridge Method的概念java bridge method)
  3. 最后调用this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest).
    其中的this.returnValueHandlers是从RequestMappingHandlerMapping传递过来的.
    这个方法的作用是对HandlerMethod的执行结果进行深加工.比如说把返回值放到Session或者Request中,再比如说处理@ResponseBodyjson写入Response等等.
  1. 根据上述过程参数及执行结果构建ModelAndView,并将其作为RequestMappingHandlerAdapter#invokeHandleMethod的结果返回.

后续:DispatcherServletprocessDispatchResult方法,进行视图的渲染及一些异常处理.接着是清理使用痕迹,还原现场之类的操作.