一、前沿
Spring MVC 是我们非常常用的框架,在使用的过程中,你了解它的工作原理吗?它的整个过程是怎样的?下面会从以下两个方面为大家一一介绍:
1)、SpringMVC 工作原理
2)、SpringMVC 核心类 DispatcherServlet 源码
二、SpringMVC 工作原理
先来看一张SpringMVC的工作原理图:
上述工作原理图清晰的展示了SpringMVC的工作原理,具体过程如下:
1)、客户端发送http请求给web服务器,web服务器对http请求进行解析,如果匹配到web.xml中dispatcherServlet对应的请求映射路径,则web服务器将请求转交给DispatcherServlet
如下图:
2)、DispatcherServlet接收到请求后根据请求的信息(包括请求URL、Http方法、请求报文头和请求参数Cookie等)和 HandlerMapping 中的映射配置找到处理请求的处理器 Handler
3)、DispatcherServlet将处理权交给 Handler, 然后根据 Handler 和 handlerAdapters 找到对应的 HandlerAdapter
4)、HandlerAdapter 对 Handler 进行具体的调用,处理http请求
5)、Handler 对请求处理完成以后将返回一个 ModelAndView 对象给 DispatcherServlet,这个 ModelAndView 只是一个逻辑视图而不是一个真正意义上的视图
6)、DispatcherServlet 通过 ViewResolver 将 ModelAndView 转化为真正的视图 view
7)、DispatcherServlet 调用 View 的 render 方法(传参是 ModelAndView 中 Model)渲染 View 并返回给客户端
从SpringMVC工作原理可知,主要的工作就是在 DispatcherServlet 完成的,下面学习一下 DispatcherServlet 源码
三、DispatcherServlet 源码
3.1 初始化工作
DispatcherServlet 在初始化屎主要完成了所有策略的初始化,比如 MultipartResolver、HandlerMapping、HandlerAdapter 等,所有默认的策略配置在 DispatcherServlet.properties 文件中,如下图:
初始化过程源码如下:
// 1、加载DispatcherServlet.properties 配置文件
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
// 加载 resources/org/springframework/web/servlet 目录下的 DispatcherServlet.properties 配置文件,加载默认策略
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
/**
* This implementation calls {@link #initStrategies}.
*/
// 2、onRefresh 方法初始化所有的策略
@Override
protected void onRefresh(ApplicationContext context) {
// 初始化策略
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
// 初始化上传文件解析器
initMultipartResolver(context);
// 初始化本地解析器,默认 AcceptHeaderLocaleResolver
initLocaleResolver(context);
// 初始化主题解析器,默认 FixedThemeResolver
initThemeResolver(context);
// 初始化HandlerMappings,默认 BeanNameUrlHandlerMapping
initHandlerMappings(context);
// 初始化HandlerAdapters,默认 SimpleControllerHandlerAdapter
initHandlerAdapters(context);
// 初始化异常处理器解析器,默认 DefaultHandlerExceptionResolver
initHandlerExceptionResolvers(context);
// 初始化RequestToViewNameTranslator,默认 DefaultRequestToViewNameTranslator
initRequestToViewNameTranslator(context);
// 初始化视图解析器,默认 InternalResourceViewResolver
initViewResolvers(context);
// 初始化FlashMapManager,默认 DefaultFlashMapManager
initFlashMapManager(context);
}
/**
* Initialize the MultipartResolver used by this class.
* <p>If no bean is defined with the given name in the BeanFactory for this namespace,
* no multipart handling is provided.
*/
private void initMultipartResolver(ApplicationContext context) {
try {
// 从Spring容器中获取名称为 multipartResolver && 类型是 MultipartResolver 的 MultipartResolver
this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("Detected " + this.multipartResolver);
}
else if (logger.isDebugEnabled()) {
logger.debug("Detected " + this.multipartResolver.getClass().getSimpleName());
}
}
catch (NoSuchBeanDefinitionException ex) {
// Default is no multipart resolver.
this.multipartResolver = null;
if (logger.isTraceEnabled()) {
logger.trace("No MultipartResolver '" + MULTIPART_RESOLVER_BEAN_NAME + "' declared");
}
}
}
/**
* Initialize the LocaleResolver used by this class.
* <p>If no bean is defined with the given name in the BeanFactory for this namespace,
* we default to AcceptHeaderLocaleResolver.
*/
private void initLocaleResolver(ApplicationContext context) {
try {
// 从Spring容器中获取名称为 localeResolver && 类型是 LocaleResolver 的 LocaleResolver
this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("Detected " + this.localeResolver);
}
else if (logger.isDebugEnabled()) {
logger.debug("Detected " + this.localeResolver.getClass().getSimpleName());
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
// 使用默认 AcceptHeaderLocaleResolver
this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("No LocaleResolver '" + LOCALE_RESOLVER_BEAN_NAME +
"': using default [" + this.localeResolver.getClass().getSimpleName() + "]");
}
}
}
/**
* Initialize the ThemeResolver used by this class.
* <p>If no bean is defined with the given name in the BeanFactory for this namespace,
* we default to a FixedThemeResolver.
*/
private void initThemeResolver(ApplicationContext context) {
try {
// 从Spring容器中获取名称为 themeResolver && 类型是 ThemeResolver 的 ThemeResolver
this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("Detected " + this.themeResolver);
}
else if (logger.isDebugEnabled()) {
logger.debug("Detected " + this.themeResolver.getClass().getSimpleName());
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
// 使用默认的 FixedThemeResolver
this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("No ThemeResolver '" + THEME_RESOLVER_BEAN_NAME +
"': using default [" + this.themeResolver.getClass().getSimpleName() + "]");
}
}
}
/**
* Initialize the HandlerMappings used by this class.
* <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
* we default to BeanNameUrlHandlerMapping.
*/
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// detectAllHandlerMappings 默认为true,检测所有的 HandlerMapping
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// 从 ApplicationContext 上下文 或者 祖先上下文中获取所有的 HandlerMapping
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
// 对 HandlerMapping 排序
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
// detectAllHandlerMappings 为false 时
try {
// 从Spring容器中获取名称为 handlerMapping && 类型是 HandlerMapping 的 HandlerMapping
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
// 使用默认的 BeanNameUrlHandlerMapping
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
/**
* 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;
// detectAllHandlerAdapters 默认为true,检测所有的 HandlerAdapter
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
// 从 ApplicationContext 上下文 或者 祖先上下文中获取所有的 HandlerAdapter
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
// 对 HandlerAdapter 排序
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
// detectAllHandlerAdapters 为false
try {
// 从Spring容器中获取名称为 handlerAdapter && 类型是 HandlerAdapter 的 HandlerAdapter
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.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
// 使用默认的 SimpleControllerHandlerAdapter
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
/**
* Initialize the HandlerExceptionResolver used by this class.
* <p>If no bean is defined with the given name in the BeanFactory for this namespace,
* we default to no exception resolver.
*/
private void initHandlerExceptionResolvers(ApplicationContext context) {
this.handlerExceptionResolvers = null;
// detectAllHandlerExceptionResolvers 默认为true,检测所有的 HandlerExceptionResolver
if (this.detectAllHandlerExceptionResolvers) {
// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
// 从 ApplicationContext 上下文 或者 祖先上下文中获取所有的 HandlerExceptionResolver
Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
// We keep HandlerExceptionResolvers in sorted order.
// 对 HandlerExceptionResolver 排序
AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
}
}
else {
try {
// 从Spring容器中获取名称为 handlerExceptionResolver && 类型是 HandlerExceptionResolver 的 HandlerExceptionResolver
HandlerExceptionResolver her =
context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
this.handlerExceptionResolvers = Collections.singletonList(her);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, no HandlerExceptionResolver is fine too.
}
}
// Ensure we have at least some HandlerExceptionResolvers, by registering
// default HandlerExceptionResolvers if no other resolvers are found.
if (this.handlerExceptionResolvers == null) {
// 使用默认的 DefaultHandlerExceptionResolver
this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerExceptionResolvers declared in servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
/**
* Initialize the RequestToViewNameTranslator used by this servlet instance.
* <p>If no implementation is configured then we default to DefaultRequestToViewNameTranslator.
*/
private void initRequestToViewNameTranslator(ApplicationContext context) {
try {
// 从Spring容器中获取名称为 viewNameTranslator && 类型是 RequestToViewNameTranslator 的 RequestToViewNameTranslator
this.viewNameTranslator =
context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);
if (logger.isTraceEnabled()) {
logger.trace("Detected " + this.viewNameTranslator.getClass().getSimpleName());
}
else if (logger.isDebugEnabled()) {
logger.debug("Detected " + this.viewNameTranslator);
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
// 使用默认的 DefaultRequestToViewNameTranslator
this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);
if (logger.isTraceEnabled()) {
logger.trace("No RequestToViewNameTranslator '" + REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME +
"': using default [" + this.viewNameTranslator.getClass().getSimpleName() + "]");
}
}
}
/**
* Initialize the ViewResolvers used by this class.
* <p>If no ViewResolver beans are defined in the BeanFactory for this
* namespace, we default to InternalResourceViewResolver.
*/
private void initViewResolvers(ApplicationContext context) {
this.viewResolvers = null;
// detectAllViewResolvers 默认为true,检测所有的 ViewResolver
if (this.detectAllViewResolvers) {
// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
// 从 ApplicationContext 上下文 或者 祖先上下文中获取所有的 ViewResolver
Map<String, ViewResolver> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.viewResolvers = new ArrayList<>(matchingBeans.values());
// We keep ViewResolvers in sorted order.
// 对 ViewResolver 排序
AnnotationAwareOrderComparator.sort(this.viewResolvers);
}
}
else {
// detectAllViewResolvers 为false
try {
// 从Spring容器中获取名称为 viewResolver && 类型是 ViewResolver 的 ViewResolver
ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
this.viewResolvers = Collections.singletonList(vr);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default ViewResolver later.
}
}
// Ensure we have at least one ViewResolver, by registering
// a default ViewResolver if no other resolvers are found.
if (this.viewResolvers == null) {
// 使用默认的 InternalResourceViewResolver
this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("No ViewResolvers declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
/**
* Initialize the {@link FlashMapManager} used by this servlet instance.
* <p>If no implementation is configured then we default to
* {@code org.springframework.web.servlet.support.DefaultFlashMapManager}.
*/
private void initFlashMapManager(ApplicationContext context) {
try {
// 从Spring容器中获取名称为 flashMapManager && 类型是 FlashMapManager 的 FlashMapManager
this.flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
if (logger.isTraceEnabled()) {
logger.trace("Detected " + this.flashMapManager.getClass().getSimpleName());
}
else if (logger.isDebugEnabled()) {
logger.debug("Detected " + this.flashMapManager);
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
// 使用默认的 DefaultFlashMapManager
this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class);
if (logger.isTraceEnabled()) {
logger.trace("No FlashMapManager '" + FLASH_MAP_MANAGER_BEAN_NAME +
"': using default [" + this.flashMapManager.getClass().getSimpleName() + "]");
}
}
}
/**
* Return the default strategy object for the given strategy interface.
* <p>The default implementation delegates to {@link #getDefaultStrategies},
* expecting a single object in the list.
* @param context the current WebApplicationContext
* @param strategyInterface the strategy interface
* @return the corresponding strategy object
* @see #getDefaultStrategies
*/
// 3、获取 DispatcherServlet.properties 文件中定义的默认策略
protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
List<T> strategies = getDefaultStrategies(context, strategyInterface);
if (strategies.size() != 1) {
// 默认策略大于1时抛出异常
throw new BeanInitializationException(
"DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
}
return strategies.get(0);
}
/**
* Create a List of default strategy objects for the given strategy interface.
* <p>The default implementation uses the "DispatcherServlet.properties" file (in the same
* package as the DispatcherServlet class) to determine the class names. It instantiates
* the strategy objects through the context's BeanFactory.
* @param context the current WebApplicationContext
* @param strategyInterface the strategy interface
* @return the List of corresponding strategy objects
*/
@SuppressWarnings("unchecked")
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
// 类全限定名作为key
String key = strategyInterface.getName();
// 从配置文件获取key对应的值
String value = defaultStrategies.getProperty(key);
if (value != null) {
// 以逗号分隔多个值
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<>(classNames.length);
for (String className : classNames) {
try {
// 反射实例化对象
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
// 创建默认的策略
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Unresolvable class definition for DispatcherServlet's default strategy class [" +
className + "] for interface [" + key + "]", err);
}
}
return strategies;
}
else {
return new LinkedList<>();
}
}
DispatcherServlet 初始化期间完成了所有策略的初始化,源码注释写的很详细,这里就不在赘述了
接下来我们看 DispatcherServlet 处理 request 请求过程
3.2 处理请求
DispatcherServlet 处理 request 请求的入口在 doService 方法中,源码如下:
/**
* Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
* for the actual dispatching.
*/
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 记录Request请求日志
logRequest(request);
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
// 保存请求快照,以便恢复request的原始属性
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
// request 中添加一些属性,比如 org.springframework.web.servlet.DispatcherServlet.CONTEXT 等
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
// 真正处理 request 请求逻辑
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
// 从保存的快照中恢复request的原始属性
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
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 {
// 检测 request 的 header 中的 ContentType 属性值是否以 multipart/ 开头,如果是 request 转成 MultipartHttpServletRequest
processedRequest = checkMultipart(request);
// 记录是否是 MultipartHttpServletRequest
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 1、根据 request 从 handlerMappings 中获取 Handler,即 HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 2、根据 Handler 从 handlerAdapters 中获取 HandlerAdapter(RequestMappingHandlerAdapter)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 获取请求方法,例如 GET、POST、PUT、DELETED 等
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
// 获取最近更新时间
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
// 最近更新时间没有变化的话,说明是重复请求 request,则不需要做处理
return;
}
}
// 3、对request请求做前置拦截处理,即调用处理器链中的所有拦截器 HandlerInterceptor 的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 4、调用 RequestMappingHandlerAdapter 的 handle 方法处理 request,并返回 ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// ModelAndView 中设置默认 viewName 属性
applyDefaultViewName(processedRequest, mv);
// 5、对request请求做后置拦截处理,即调用处理器链中的所有拦截器 HandlerInterceptor 的 postHandle 方法
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);
}
// 6、处理请求结果,即通过 ViewResolver 将 ModelAndView 转成 View,并调用 View 的 render 方法渲染 view
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
// 调用处理器链中的所有异步拦截器 AsyncHandlerInterceptor 的 afterConcurrentHandlingStarted 方法
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
// 清除 MultipartHttpServletRequest 使用的任何资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
DispatcherServlet 处理 request 共经过了以下六个步骤:
1)、根据 request 从 handlerMappings 中获取 Handler,即 HandlerExecutionChain
2)、根据 Handler 从 handlerAdapters 中获取 HandlerAdapter,这里指的是 RequestMappingHandlerAdapter
3)、对request请求做前置拦截处理,即调用处理器链中的所有拦截器 HandlerInterceptor 的 preHandle 方法
4)、调用 RequestMappingHandlerAdapter 的 handle 方法处理 request,并返回 ModelAndView
5)、对request请求做后置拦截处理,即调用处理器链中的所有拦截器 HandlerInterceptor 的 postHandle 方法
6)、处理请求结果,即通过 ViewResolver 将 ModelAndView 转成 View,并调用 View 的 render 方法渲染 view
下面从源码方面分别对这六个步骤解析
3.2.1 获取 Handler(HandlerExecutionChain)
获取 Handler 的业务逻辑在 DispatcherServlet 的 getHandler 的方法实现了,getHandler 源码如下:
/**
* Return the HandlerExecutionChain for this request.
* <p>Tries all handler mappings in order.
* @param request current HTTP request
* @return the HandlerExecutionChain, or {@code null} if no handler could be found
*/
// 1、DispatcherServlet 的 getHandler 方法
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
// 调用 AbstractHandlerMapping 的 getHandler 方法获取 HandlerExecutionChain
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
/**
* Look up a handler for the given request, falling back to the default
* handler if no specific one is found.
* @param request current HTTP request
* @return the corresponding handler instance, or the default handler
* @see #getHandlerInternal
*/
// 2、AbstractHandlerMapping 的 getHandler 方法
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 调用 AbstractHandlerMethodMapping 的 getHandlerInternal 方法获取 HandlerMethod
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;
// String 类型的 ,直接从上下文中根据名字获取实例
handler = obtainApplicationContext().getBean(handlerName);
}
// 根据 request 请求 url 获取匹配的所有拦截器,并将 handler 和拦截器封装到 HandlerExecutionChain 对象中
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
// 存在跨域配置
if (hasCorsConfigurationSource(handler)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
// 调用 AbstractHandlerMapping 的 getCorsHandlerExecutionChain 方法
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
// AbstractHandlerMapping 的 getHandlerExecutionChain 方法
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
// 获取请求url
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
// HandlerInterceptor 是 MappedInterceptor 类型 && 请求url 匹配符合 HandlerInterceptor 的 拦截路径规则
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
// 添加 HandlerInterceptor 到 HandlerExecutionChain 中
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
// 不需要匹配url路径规则的 HandlerInterceptor 直接添加到 HandlerExecutionChain 中
chain.addInterceptor(interceptor);
}
}
return chain;
}
// AbstractHandlerMapping 的 getCorsHandlerExecutionChain 方法
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
HandlerExecutionChain chain, @Nullable CorsConfiguration config) {
if (CorsUtils.isPreFlightRequest(request)) {
// request 的 method 是 OPTIONs && request 的 header 中有 Access-Control-Request-Method
HandlerInterceptor[] interceptors = chain.getInterceptors();
chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
}
else {
// 否则的话,将 CorsInterceptor 拦截器设置为第一个元素
chain.addInterceptor(0, new CorsInterceptor(config));
}
return chain;
}
/**
* Look up a handler method for the given request.
*/
// 3、AbstractHandlerMethodMapping 的 getHandlerInternal 方法
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 获取请求 url
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
// 对映射关系注册对象加锁,防止获取HandlerMethod的时候注册对象被其他线程读取
this.mappingRegistry.acquireReadLock();
try {
// 调用 lookupHandlerMethod 方法 获取 HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
/**
* Look up the best-matching handler method for the current request.
* If multiple matches are found, the best match is selected.
* @param lookupPath mapping lookup path within the current servlet mapping
* @param request the current request
* @return the best-matching handler method, or {@code null} if no match
* @see #handleMatch(Object, String, HttpServletRequest)
* @see #handleNoMatch(Set, String, HttpServletRequest)
*/
// AbstractHandlerMethodMapping 的 lookupHandlerMethod 方法
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 根据请求url获取直接匹配列表
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
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()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
// 匹配排序
matches.sort(comparator);
Match bestMatch = matches.get(0);
// 请求url匹配到多个规则时,取前两个规则比较,不相同的话,取第一个匹配规则作为最终结果
if (matches.size() > 1) {
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
// 多个都匹配请求url时,比较前两个是否相等,相等的话抛出异常
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
// 添加匹配的 HandlerMethod 到 request 的 attribute 属性中
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
RequestMapping 注解对应的url和Controller中的方法映射关系如下图:
获取 Handler 的逻辑相对来说不太复杂,代码注释写的很明白了,直接看源码就可以理解整个过程了
3.2.2 获取 HandlerAdapter(RequestMappingHandlerAdapter)
获取 HandlerAdapter 的业务逻辑入口在 DispatcherServlet 的 getHandlerAdapter 方法,真个过程源码如下:
/**
* 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.
*/
// 1、DispatcherServlet 的 getHandlerAdapter 方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
// 调用的是 AbstractHandlerMethodAdapter 的 supports 方法
if (adapter.supports(handler)) {
// HandlerAdapter 支持 handler,返回该 HandlerAdapter,这里是 RequestMappingHandlerAdapter
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
/**
* 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
*/
// 2、AbstractHandlerMethodAdapter 的 supports 方法
@Override
public final boolean supports(Object handler) {
// 判断 handler 是否是 HandlerMethod 类型
// 调用 RequestMappingHandlerAdapter 的 supportsInternal 方法,永远返回 true
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
/**
* Always return {@code true} since any method argument and return value
* type will be processed in some way. A method argument not recognized
* by any HandlerMethodArgumentResolver is interpreted as a request parameter
* if it is a simple type, or as a model attribute otherwise. A return value
* not recognized by any HandlerMethodReturnValueHandler will be interpreted
* as a model attribute.
*/
// 3、RequestMappingHandlerAdapter 的 supportsInternal 方法
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
获取 HandlerAdapter 逻辑十分简单,主要就是根据 Handler 获取到了 RequestMappingHandlerAdapter,这里不在赘述
3.2.3 调用 (HandlerAdapter)RequestMappingHandlerAdapter 的 handle 方法返回 ModelAndView
这个过程是整个 SpringMVC 的核心所在,这个过程体现了通过浏览器发起的请求是怎么样最后交给 Controller 的 方法处理的,整体debug栈信息如下:
invoke:498, Method (java.lang.reflect)
doInvoke:205, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:133, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:97, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:849, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:760, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:85, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:967, DispatcherServlet (org.springframework.web.servlet)
doService:901, DispatcherServlet (org.springframework.web.servlet)
processRequest:970, FrameworkServlet (org.springframework.web.servlet)
doPost:872, FrameworkServlet (org.springframework.web.servlet)
service:660, HttpServlet (javax.servlet.http)
service:846, FrameworkServlet (org.springframework.web.servlet)
service:741, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:31, AccessControlFilter (com.ideacome.black.pearl.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:197, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:199, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:490, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:139, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:668, AbstractAccessLogValve (org.apache.catalina.valves)
invoke:74, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:408, Http11Processor (org.apache.coyote.http11)
process:66, AbstractProcessorLight (org.apache.coyote)
process:770, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1415, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)
通过栈信息可以得出如下结论:
1)、request 请求首先进入到 tomcat(使用的是tomcat web容器)容器中,经过了 tomcat 的层层处理
2)、tomcat 处理请求后将 request 交给了 Spring 容器的 FrameworkServlet 处理
3)、request 最终被 Spring 容器的 DispatcherServlet(继承 FrameworkServlet) 处理
4)、在 DispatcherServlet 中 RequestMappingHandlerAdapter 通过请求url定位到具体的Controller的具体方法
5)、最后通过反射调用对象方法,即调用到了Controller的具体方法
调用 HandlerAdapter 的 handle 方法入口是 AbstractHandlerMethodAdapter 的 handle 方法,整个过程源码如下:
/**
* This implementation expects the handler to be an {@link HandlerMethod}.
*/
// 1、AbstractHandlerMethodAdapter 的 handle 方法
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 调用 RequestMappingHandlerAdapter 的 handleInternal 方法处理请求
return handleInternal(request, response, (HandlerMethod) handler);
}
// 2、RequestMappingHandlerAdapter 的 handleInternal 方法
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
// 检测是否支持 request 的 method 方法
checkRequest(request);
// 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) {
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...
// 继续调用 RequestMappingHandlerAdapter 的 invokeHandlerMethod
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
// response 中的缓存 Cache-Control 设置
prepareResponse(response);
}
}
return mav;
}
/**
* Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
* if view resolution is required.
* @since 4.2
* @see #createInvocableHandlerMethod(HandlerMethod)
*/
// 3、RequestMappingHandlerAdapter 的 invokeHandlerMethod
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// 构建 ServletWebRequest 对象
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 构建 ServletInvocableHandlerMethod 对象
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
// 构建 ModelAndView 容器
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// 构建异步web请求
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();
LogFormatUtils.traceDebug(logger, traceOn -> {
String formatted = LogFormatUtils.formatValue(result, !traceOn);
return "Resume with async result [" + formatted + "]";
});
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 调用 ServletInvocableHandlerMethod 的 invokeAndHandle 方法处理请求
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 调用 getModelAndView 方法获取 ModelAndView
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
/**
* Invoke the method and handle the return value through one of the
* configured {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}.
* @param webRequest the current request
* @param mavContainer the ModelAndViewContainer for this request
* @param providedArgs "given" arguments matched by type (not resolved)
*/
// 4、ServletInvocableHandlerMethod 的 invokeAndHandle 方法
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 调用 InvocableHandlerMethod 的 invokeForRequest 方法处理请求并获取返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 设置请求响应状态
setResponseStatus(webRequest);
// 返回值为null
if (returnValue == null) {
// 重复请求 或者 响应状态不为空 或者 已经全部处理好了
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
// requestHandled 设置为 true,即不需要返回 ModelAndView
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
// 响应状态有原因时,requestHandled 设置为 true,即不需要返回 ModelAndView
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
// 调用 HandlerMethodReturnValueHandlerComposite 的 handleReturnValue 对返回值处理
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(formatErrorForReturnValue(returnValue), ex);
}
throw ex;
}
}
// 5、InvocableHandlerMethod 的 invokeForRequest 方法
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 获取请求方法的参数值
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
// 调用 InvocableHandlerMethod 的 doInvoke 方法执行方法调用
return doInvoke(args);
}
/**
* Invoke the handler method with the given argument values.
*/
// 6、InvocableHandlerMethod 的 doInvoke
@Nullable
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 通过反射调用 Method 的 invoke 方法,最终调用的是某个Controller的某个方法
// 例如:TestController 的 test 方法
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(formatInvokeError(text, 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 {
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
}
}
}
/**
* Iterate over registered {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers} and invoke the one that supports it.
* @throws IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found.
*/
// 7、HandlerMethodReturnValueHandlerComposite 的 handleReturnValue 对返回值处理
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 根据返回值和返回对象类型选择返回值对应的处理器,由于请求的Controller的方法是带有 ResponseBody 注解的 && 返回值类型是 Object
// 因此这里获取的是 RequestResponseBodyMethodProcessor
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
// 调用 RequestResponseBodyMethodProcessor 的 handleReturnValue 方法,将返回值转换为客户端需要的数据格式
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
// 调用 RequestResponseBodyMethodProcessor 的 supportsReturnType 方法
if (handler.supportsReturnType(returnType)) {
// 选择处理器支持处理的返回对象类型对应的处理器,这里指 RequestResponseBodyMethodProcessor
return handler;
}
}
return null;
}
// RequestResponseBodyMethodProcessor 的 supportsReturnType 方法
@Override
public boolean supportsReturnType(MethodParameter returnType) {
// 返回对象上是否有 ResponseBody 注解
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
// 8、RequestResponseBodyMethodProcessor 的 handleReturnValue 方法
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 将内部处理标识设置为 true,后续就不需要做额外的处理了,这里指的是获取 ModelAndView
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// Try even with null return value. ResponseBodyAdvice could get involved.
// 将返回值转换为客户端需要的数据格式
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
// 9、RequestMappingHandlerAdapter 的 getModelAndView 方法
@Nullable
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
modelFactory.updateModel(webRequest, mavContainer);
if (mavContainer.isRequestHandled()) {
// 如果返回数据已经做了相应的处理了,这里就直接返回了
return null;
}
// 获取填充数据 ModelMap
ModelMap model = mavContainer.getModel();
// 创建 ModelAndView
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
if (!mavContainer.isViewReference()) {
// 非String类型的 View,添加到 ModelAndView 属性中
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (request != null) {
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
}
// 返回 ModelAndView
return mav;
}
整个过程比较复杂,我是通过源码调试来学习整个过程的,希望大家多调试源码。代码中有详细的注释,这里就不再使用文字啰嗦了
3.2.4 对request请求做前后置拦截
1)、request 前置拦截
前置拦截就是调用处理器链中的所有拦截器 HandlerInterceptor 的 preHandle 方法,入口是 HandlerExecutionChain 的 applyPreHandle 方法,源码如下:
/**
* Apply preHandle methods of registered interceptors.
* @return {@code true} if the execution chain should proceed with the
* next interceptor or the handler itself. Else, DispatcherServlet assumes
* that this interceptor has already dealt with the response itself.
*/
// HandlerExecutionChain 的 applyPreHandle 方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
// 调用具体拦截器的 preHandle 方法
if (!interceptor.preHandle(request, response, this.handler)) {
// 如果前置拦截执行失败的话,则触发拦截器的最终处理
triggerAfterCompletion(request, response, null);
// 返回 false
return false;
}
this.interceptorIndex = i;
}
}
// 拦截器为空 或者 所有前置拦截执行成功,则返回 true
return true;
}
2)、request 后置拦截
前置拦截就是调用处理器链中的所有拦截器 HandlerInterceptor 的 postHandle 方法,入口是 HandlerExecutionChain 的 applyPostHandle方法,源码如下:
/**
* Apply postHandle methods of registered interceptors.
*/
// HandlerExecutionChain 的 applyPostHandle 方法
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
// 调用具体拦截器的 postHandle 处理逻辑
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
3)、request 完成之后拦截
完成之后拦截就是调用处理器链中的所有拦截器 HandlerInterceptor 的 afterCompletion 方法,入口是 HandlerExecutionChain 的 triggerAfterCompletion 方法,源码如下:
// HandlerExecutionChain 的 triggerAfterCompletion 方法
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
// 调用具体拦截器的 afterCompletion 方法
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
拦截器 HandlerInterceptor 接口中定义了三个方法,即 preHandler、postHandler 和 afterCompletion
preHandler : Handler 执行前执行
postHandler : Handler 执行后执行
afterCompletion : view 渲染完成后执行
这里有一个注意的地方,如下:
当有一个 preHandler 执行失败返回 false 时,当前的请求将会 afterCompletion 方法,执行完后直接返回,handler 也将不会执行了
3.2.5 处理请求结果
DispatcherServlet 处理请求结果,这里有两个步骤,如下:
1)、ViewResolver 将 ModelAndView 转成 View
2)、调用 View 的 render 方法渲染 view
入口在 DispatcherServlet 的 processDispatchResult 方法,整个过程源码如下:
/**
* Handle the result of handler selection and handler invocation, which is
* either a ModelAndView or an Exception to be resolved to a ModelAndView.
*/
// 1、DispatcherServlet 的 processDispatchResult 方法
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
// 存在异常
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
// 调用异常处理解析器来处理异常,并返回 ModelAndView
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
// 是否返回要呈现给用户的视图
if (mv != null && !mv.wasCleared()) {
// 调用 DispatcherServlet 的 render 方法
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
// 触发请求request的完成之后的拦截处理
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
/**
* Render the given ModelAndView.
* <p>This is the last stage in handling a request. It may involve resolving the view by name.
* @param mv the ModelAndView to render
* @param request current HTTP servlet request
* @param response current HTTP servlet response
* @throws ServletException if view is missing or cannot be resolved
* @throws Exception if there's a problem rendering the view
*/
// 2、DispatcherServlet 的 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 != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
response.setLocale(locale);
View view;
String viewName = mv.getViewName();
if (viewName != null) {
// We need to resolve the view name.
// 根据视图名称 和 Locale 解析成 View 对象
view = resolveViewName(viewName, 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.
// 直接从 ModelAndView 中获取 View 对象
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.isTraceEnabled()) {
logger.trace("Rendering view [" + view + "] ");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
// 调用 AbstractView 的 render 方法渲染视图
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "]", ex);
}
throw ex;
}
}
/**
* Prepares the view given the specified model, merging it with static
* attributes and a RequestContext attribute, if necessary.
* Delegates to renderMergedOutputModel for the actual rendering.
* @see #renderMergedOutputModel
*/
// 3、AbstractView 的 render 方法
@Override
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("View " + formatViewName() +
", model " + (model != null ? model : Collections.emptyMap()) +
(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
}
// 合并填充数据 Model
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
// 模板方法,即调用具体的视图渲染器的 renderMergedOutputModel 方法来渲染视图
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
整个过程不复杂,至于具体的视图渲染器是怎么来渲染视图的,这里不做源码分析了,感兴趣的可以自己分析
四、总结
SpringMVC 的核心处理逻辑在 DispatcherServlet 中,如果你对 DispatcherServlet 源码了解了,SpringMVC 的工作原理自然就理解了,在学习过程中,还是希望大家尽量 debug 调试源码,以便自己更好地理解源码意图。如有不正之处,请大家指正,谢谢