一、DispatcherServlet执行流程及相关源码分析
1、springmvc时序图
1、用户请求发送至DispatcherServlet类进行处理。
2、DispatcherServlet类遍历所有配置的HandlerMapping类请求查找Handler。
3、HandlerMapping类根据request请求的URL等信息查找能够进行处理的Handler,以及相关拦截器interceptor并构造HandlerExecutionChain。
4、HandlerMapping类将构造的HandlerExecutionChain类的对象返回给前端控制器DispatcherServlet类。
5、前端控制器拿着上一步的Handler遍历所有配置的HandlerAdapter类请求执行Handler。
6、HandlerAdapter类执行相关Handler并获取ModelAndView类的对象。
7、HandlerAdapter类将上一步Handler执行结果的ModelAndView 类的对象返回给前端控制器。
8、DispatcherServlet类遍历所有配置的ViewResolver类请求进行视图解析。
9、ViewResolver类进行视图解析并获取View对象。
10、ViewResolver类向前端控制器返回上一步骤的View对象。
11、DispatcherServlet类进行视图View的渲染,填充Model。
12、DispatcherServlet类向用户返回响应。
Spring MVC的四大组件:DispatcherServlet、HandlerMapping、HandlerAdapter以及ViewResolver
2、打开DispatcherServlet.class的源码
- DispatcherServlet入口doService()方法
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
/*
将当前Servlet的子IoC容器放入request请求中
由此,我们可以访问到当前IoC子容器以及根IoC容器中的Bean
*/
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());
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 {
//真正进行用户请求的处理
doDispatch(request, response);
}
doService() 方法主要进行一些参数的设置,并将部分参数放入request请求中,真正执行用户请求并作出响应的方法则为doDispatch()方法
- 分析主要业务处理的方法doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//用户的request请求
HttpServletRequest processedRequest = request;
//HandlerExecutionChain局部变量
HandlerExecutionChain mappedHandler = null;
//判断是否解析了文件类型的数据,如果有最终需要清理
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
//ModelAndView局部变量
ModelAndView mv = null;
//处理异常局部变量
Exception dispatchException = null;
try {
//检查是否包含文件等类型的数据
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
//向HandlerMapping请求查找HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
//如果HandlerExecutionChain为null,则没有能够进行处理的Handler,抛出异常
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//根据查找到的Handler请求查找能够进行处理的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;
}
}
/*
按顺序依次执行HandlerInterceptor的preHandle方法
如果任一HandlerInterceptor的preHandle方法没有通过则不继续进行处理
*/
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
//通过HandlerAdapter执行查找到的handler
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//逆序执行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);
}
//渲染视图填充Model,如果有异常渲染异常页面
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
//如果有异常按倒序执行所有HandlerInterceptor的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
//如果有异常按倒序执行所有HandlerInterceptor的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
//倒序执行所有HandlerInterceptor的afterCompletion方法
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
//如果请求包含文件类型的数据则进行相关清理工作
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
doDispatch()方法通过调用getHandler()方法并传入reuqest通过HandlerMapping查找HandlerExecutionChain
- getHandler()源码如下
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
1)getHandler()方法遍历了开发者配置的所有HandlerMapping类,springmvc拥有多个HandlerMapping类;springmvc默认包含SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping两种处理器映射器类;
2)处理用户请求时逐一查找用户配置的所有HandlerMapping类,找到后立即返回跳出for (HandlerMapping hm : this.handlerMappings)循环,故最后只会返回第一个能够处理的HandlerMapping类构造用户请求的HandlerExecutionChain ;
3)注意:在配置HandlerMapping类时需要注意不要对同一请求多次进行处理,即只配置一种HandlerMapping类即可。
- 没有获取到HandlerExecutionChain 对象,会执行noHandlerFound()方法
protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (pageNotFoundLogger.isWarnEnabled()) {
pageNotFoundLogger.warn("No mapping found for HTTP request with URI [" + getRequestUri(request) +
"] in DispatcherServlet with name '" + getServletName() + "'");
}
if (this.throwExceptionIfNoHandlerFound) {
throw new NoHandlerFoundException(request.getMethod(), getRequestUri(request),
new ServletServerHttpRequest(request).getHeaders());
}
else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
若没有找到对应的HandlerExecutionChain 则会抛出异常NoHandlerFoundException。
- 获取到HandlerExecutionChain 后DispatcherServlet会调用getHandlerAdapter()方法来查找能够对Handler进行处理的HandlerAdapter
DispatcherServlet.class中getHandlerAdapter()方法源码:
// Determine handler adapter for the current request.
//根据查找到的Handler请求查找能够进行处理的HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
1)遍历所有的HandlerAdapter类,springmvc默认有以下几种适配器:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter。
2)HandlerAdapter类是一个接口包含一个supports()方法,该方法用来判断当前遍历得到的HandlerAdapter类是否有处理当前处理器类请求的资格来得到方法的返回值,如果具备此资格,则返回当前的HandlerAdapter类,不行则继续遍历;
3)注意:HttpRequestHandlerAdapter只能 处理 实现了org.springframework.web.HttpRequestHandler接口的处理器类 SimpleControllerHandlerAdapter只能 处理 实现了org.springframework.web.servlet.mvc.Controller接口的处理器类
/*
按顺序依次执行HandlerInterceptor的preHandle方法
如果任一HandlerInterceptor的preHandle方法没有通过则不继续进行处理
*/
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
HandlerInteceptor的preHandle()方法源码
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
判断获取的HandlerExecutionChain 处理器执行链对象是否符合任一HandlerInterceptor的preHandle方法顺利通过这一条件,如果通过了则就绪向下执行。
- HandlerExecutionChain 没有问题以及获取了HandlerAdapter对象后,继续调用processDispatchResult()方法
// Actually invoke the handler.
//通过HandlerAdapter执行查找到的handler
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//逆序执行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);
}
//渲染视图填充Model,如果有异常渲染异常页面
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
- processDispatchResult()源码,此步骤是在通过控制器执行逻辑顺利执行后获取到了ModelAndView视图后执行,主要作用是渲染视图并填充model:
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
//判断HandlerMapping、HandlerAdapter处理时的异常是否为空
if (exception != null) {
//上述两个组件处理时的异常不为空
//如果为ModelAndViewDefiningException异常,则获取一个异常视图
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
//如果不为ModelAndViewDefiningException异常,进行异常视图的获取
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?
//判断mv是否为空,不管是正常的ModelAndView还是异常的ModelAndView,只要存在mv就进行视图渲染
if (mv != null && !mv.wasCleared()) {
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;
}
//执行相关HandlerInterceptor的afterCompletion()方法
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
processDispatchResult()方法主要用于针对产生的异常来构造异常视图,接着不管视图是正常视图还是异常视图均调用render()方法来渲染。
二、总结
通过分析springmvc的执行流程的源码,我们发现springmvc的主要执行逻辑均在DispatcherServlet类中的doDispatch方法中,通过源码分析+时序图我们可以更好的理解springmvc的执行流程以及它的底层处理机制;最后奉上本文参考博客:https://www.jianshu.com/p/0f981efdfbbd
- 查找到了对应的HandlerAdapter类后就会调用HandlerExecutionChain的applyPreHandle()方法来执行配置所有HandlerInteceptor的preHandle()方法