Spring MVC的请求处理流程
DispatcherServlet的处理流程图
核心处理流程步骤
- 检测是否是文件上传, 并处理
- 根据 Request 获取 HandlerExecutionChain
2-1: 首先解析 Request 的请求的Path
2-2: 根据 Path 在返回 HanlderMethod
2-3: 将 HanlderMethod + HandlerInterceptor 包装成 HandlerExecutionChain 返回. - 执行Chain的preHanlde方法
- 根据Chain的HandlerMethod, 调用对应的Controller的method, 并返回ModelAndView对象(如果ModelAndView对象为null或者没有View, 那么直接使用默认实现值返回).
- 执行Chain的postHandle方法
- 根据vm返回值渲染页面
6-1: 根据viewName解析View对象
6-2: 根据view对象渲染页面
// 从代码中解读
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request); // 步骤1
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest); // 步骤2
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) { // 步骤3
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // 步骤4
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv); // 步骤5
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); //步骤6
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
DispatcherServlet 的初始化过程
-
initMultipartResolver: 文件上传处理器
从容器中获取名为multipartResolver的Bean做该类型的组件, 没有则不拥有该类型组件
默认实现: 没有默认实现 -
initLocaleResolver: 国际化处理器
从容器中获取名为localeResolver的Bean做该类型的组件, 没有则调用默认实现
默认实现: org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver -
initThemeResolver: 主题管理处理器 对应容器中的Bean是: themeResolver
从容器中获取名为themeResolver的Bean做该类型的组件, 没有则调用默认实现
默认实现: org.springframework.web.servlet.theme.FixedThemeResolver -
initHandlerMappings: 处理映射器 主要做url到处理类的映射
如果 detectAllHandlerMappings = true (默认实现), 查找类型匹配机制及父Spring容器中类型为HanlderMapping的Bean, 作为该类型组件
否则 查找名称为handlerMapping的Bean, 作为该类型的组件
如果都没有找到, 则调用默认实现
默认实现:
1. org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping()
2. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
initHandlerAdapters: 处理适配器 处理器的真正实现
如果 detectAllHandlerAdapters = true (默认实现), 查找类型匹配机制及父Spring容器中类型为HandlerAdapter的Bean, 作为该类型组件
否则 查找名称为handlerAdapter的Bean, 作为该类型的组件
如果都没有找到, 则调用默认实现
默认实现:
1. org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
2. org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
3. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter -
initHandlerExceptionResolvers: 异常处理器
如果 detectAllHandlerExceptionResolvers = true (默认实现), 查找类型匹配机制及父Spring容器中类型为HandlerAdapter的Bean, 作为该类型组件
否则 查找名称为handlerExceptionResolver的Bean, 作为该类型的组件
如果都没有找到, 则调用默认实现
默认实现:
1. org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
2. org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
3. org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver -
initRequestToViewNameTranslator: 视图名称翻译器
查找名称为viewNameTranslator的Bean作为该类型的组件, 没有则调用默认实现
默认实现: org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator -
initViewResolvers: 视图解析器
如果 detectAllViewResolvers = true (默认实现), 查找类型匹配机制及父Spring容器中类型为HandlerAdapter的Bean, 作为该类型组件
否则 查找名称为viewResolver的Bean, 作为该类型的组件
如果都没有找到, 则调用默认实现
默认实现: org.springframework.web.servlet.view.InternalResourceViewResolver -
initFlashMapManager: 重定向数据管理器
查找名称为flashMapManager的Bean作为该类型的组件, 没有则调用默认实现
默认实现: org.springframework.web.servlet.support.SessionFlashMapManager