@SuppressWarnings("deprecation")
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 实际处理时用的请求,如果不是上传请求,则直接使用接收到的 request,否则封装成上传的 request
HttpServletRequest processedRequest = request;
// 处理请求的处理器链(包括处理器和对应的 interceptor)
HandlerExecutionChain mappedHandler = null;
// 上传标志
boolean multipartRequestParsed = false;
// 获取异步处理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
// 检查是否是上传请求
// 如果是上传请求,则将其封装成 multipartRequestParsed
// 内有九个组件之一 MultipartResolver
processedRequest = checkMultipart(request);
// 上传请求标志位
// 通过对象是否更改过进行判断
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 获得请求对应的 HandlerExecutionChain 对象(HandlerMethod(Controller 的具体方法) 和 HandlerInterceptor 拦截器们)
// 重要 拦截器链
// 循环遍历三个 HandlerMapping 进行匹配
mappedHandler = getHandler(processedRequest);
// 获取不到控制器
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 通过适配器的方式进行调用,因为有多个选择。
// 根据
// 获取与当前 handler 匹配的 Adapter
// 重要
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理GET、HEAD请求的Last-Modified,当浏览器第一次跟服务器请求资源时,服务器会在返回的请求头里包含一个 last_modified 的属性,
// last_modified 代表资源最后时什么时候修改的,在浏览器以后发送请求的时候,会同时发送之前接收到的 Last_modified .服务器接收到带last_modified的请求后,
// 会跟实际资源的最后修改时间做对比,如果过期了返回新的资源,否则直接返回304表示未过期,直接使用之前缓存的结果即可
// 获取请求方式
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
// 为了减少资源重复获取
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行响应的 Interceptor 的 PreHandle
// 注意:该方法如果有一个拦截器的前置处理器返回 false,则开始倒序触发所有的拦截器的已完成处理
// mappedHandler 是 HandlerExecutionChain
// 重要
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// mv ModelAndView
// 使用适配器执行 handler,并返回视图
// 重要
// AbstractHandlerMethodAdapter
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 如果有异步处理
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 如果 view 为空,根据 request 设置默认的 view
// 默认名字为 请求路径名。
// 组件:RequestToViewNameTranslator
applyDefaultViewName(processedRequest, mv);
// 重要 拦截器的后置处理器
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 ServletException("Handler dispatch failed: " + err, err);
}
// 重要
// 处理返回结果,包括处理异常,页面渲染
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new ServletException("Handler processing failed: " + err, err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
// 触发 Interceptor 的 afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}`
1.getHandel()
@Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { // 默认有三个 for (HandlerMapping mapping : this.handlerMappings) { // BeanNameUrlHandlerMapping 第一次 匹配不到 // RequestMappingHandlerMapping - 第二个 通过@Controller生成的 HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
通过断点可以看到默认会有两个HandlerMapping的实现:RequestMappingHandlerMapping和BeanNameUrlHandlerMapping;
所有加了@Controller的Controller对象会放在RequestMappingHandlerMapping的父类
HandlerExecutionChain即为控制器与连接器
2.由于SpringMVC提供了4种类型的HandlerAdapter,并且他们没有统一的调用接口,所以需要通过适配器来使用。同样适配器的类型也有4种。如下所示:
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
支持当前Handler类型的适配器并返回
3.执行 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());,
4.执行响应的interceptor的postHandler方法
查找视图,并相应View