SpringMVC流程
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
下面主要看一下2-5环节的执行流程及源码:
请求处理的核心方法是DispatcherServlet的doDispatch()方法:
/** 中央控制器,控制请求的转发 */
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
// 请求处理链,包括interceptor和controller
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 检查是否是文件上传的请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 获取请求对应的处理器,实际返回的是HandlerExecutionChain处理器链
// DispatcherServlet是FrameworkServlet的子类,实现了其onRefresh()方法
// 在webApplicationContext初始化阶段执行DispatcherServlet相关策略对象的初始化
// 其中会初始化url和requestMappingMethod的对应关系以及处理器适配器等等)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 获取请求的处理器适配器,可以简单认为HandlerAdapter就是我们平时定义的controller
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 获取请求方式,如GET, POST, PUT
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;
}
}
// 请求处理-1:从处理器链中取出所有的interceptor对请求执行preHandle()方法
// 记录当前已处理的interceptor的索引,每执行interceptor更新一次interceptorIndex
// 如果preHandle()返回false,则开始反向执行afterCompletion()方法
// 从interceptorIndex反向执行,interceptorIndex--
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 请求处理-2:根据处理器适配器执行真正的业务逻辑,即执行controller中的方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 请求处理-3:执行所有interceptor的postHandle()方法,和preHandle()的执行顺序相反
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 处理请求调度执行结果,包括model、view处理还有所有的interceptor的afterCompletion()方法
// 从interceptorIndex反向执行,interceptorIndex--
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 发生异常时执行afterCompletion()方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
// 发生异常时执行afterCompletion()方法
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// 文件上传请求的临时资源清理
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
从以上的代码分析可以了解到SpringMVC请求处理的一些逻辑:
1、spring的拦截器interceptor执行顺序如下:
interceptor1.preHandle() -> interceptor2.preHandle() -> interceptor3.preHandle()
interceptor3.postHandle() -> interceptor2.postHandle() -> interceptor1.postHandle()
2、整个请求处理器链HandlerExecutionChain执行完后,文件临时资源会被清理,会清除multipartfile在tmp临时文件目录创建的文件,如果在controller方法中要异步处理一个文件,需要使用文件流的方式或者先将文件保存到一个自定义存储目录,否则在controller执行完后此临时文件删除,异步线程中将获取不到文件而出现异常
3、DispatcherServlet初始化的时候将一个请求对应的所有拦截器和处理器适配器封装到一个HandlerExecutionChain中,处理请求的时候再从HandlerExecutionChain中拿出所有拦截器以及处理器适配器进行请求的处理