通过DispatcherServlet源码分析SpringMVC执行流程
前言:分析SpringMVC执行过程我们只需要关注DispatcherServlet的doDispatch()方法即可。SpringMVC的执行过程这里先简单的总结为以下几点,具体的可以看代码里面的注释。
- 前端发起请求进入DispatcherServlet的doDispatch()方法
- 调用HandlerMapping处理器映射器处理url,返回HandlerExecutionChain
- 通过mappedHandler获取HandlerAdapter
- HandlerAdapter处理器适配器找到具体的Controller的具体方法处理,方法处理完后返回ModelAndView
- 将ModelAndView传给ViewReslover视图解析器,返回View,根据返回的View渲染视图
- 前端展示渲染的页面
如果是Restful风格的Api,返回的是JSON数据,那么第4步返回的ModelAndView为null,后面的步骤就不会执行。其实返回JSON数据第4步处理完成之后就已经通过HttpServletResponse的OutputStream写出数据了。
具体请看代码里面的注释:
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);
multipartRequestParsed = processedRequest != request;
// 1、调用HandlerMapping处理器映射器处理url,返回HandlerExecutionChain
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
// 2、通过mappedHandler获取HandlerAdapter
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 ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 3、HandlerAdapter处理器适配器找到具体的Controller的具体方法处理,方法处理完后返回ModelAndView
// 注: 如果添加了@ResponseBody或者@RestController返回的mv为null,直接通过HttpServletResponse的OutputStream响应json数据
// handle方法源码很复杂,这里就不展开说明了
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
// 具体实现processDispatchResult看下面代码
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} 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);
}
}
}
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) {
this.logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException)exception).getModelAndView();
} else {
Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
mv = this.processHandlerException(request, response, handler, exception);
errorView = mv != null;
}
}
// 注:除了返回ModelAndView的方法外, 添加了@ResponseBody注解的方法或者@RestController下方法都不会进入下面方法
// 无论是否添加@ResponseBody或者@RestController,只要返回ModelAndView都会执行this.render()方法
if (mv != null && !mv.wasCleared()) {
// 4、将ModelAndView传给ViewReslover视图解析器,返回View,根据返回的View渲染视图;
this.render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("No view rendering, null ModelAndView returned.");
}
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}