先看下整个方法:
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; mappedHandler = this.getHandler(processedRequest); 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 ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } 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); } 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); } } }
首先是:
HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
看下HandlerExecutionChain的成员变量:
handler 即对应的处理器,interceptors即对应的拦截器,interceptorList即集合化的拦截器。multipartRequestParsed判断这个请求是不是文件流的请求,即multipartFile。
asyncManager,异步管理器:
if (asyncManager.isConcurrentHandlingStarted()) { return; }
这个地方还未具体研究。
二、然后是:
processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; }
判断是不是文件流请求,以及获取处理器映射器:
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { Iterator var2 = this.handlerMappings.iterator(); while(var2.hasNext()) { HandlerMapping mapping = (HandlerMapping)var2.next(); HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
总共有五个处理器映射器:
我们主要用到的是SimpleUrlHandlerMapping与RequestMappingHandlerMapping。其中SimpleUrlHandlerMapping是我们在最初使用配置文件的形式,并继承Controller接口时,来处理这些继承该接口的类的:如其他作者写的博文:https://blog.csdn.net/qq_26464179/article/details/79042989
我们可以看到我们要实现handleRequestInternal接口。
而关于RequestMappingHandlerMapping,是我们现在常用的@Controller以注解的方式实现的。
并且,在SimpleUrlHandlerMapping处理器映射器获取到的处理器是ResourceHttpRequestHandler。
而在RequestMappingHandlerMapping处理器映射器获取到的处理器是HandlerMethod:
三、如果没有获取到对应的处理器,则直接返回:
if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; }
四、如果获取到处理器,则获取到对应的适配器(这里是有用到适配器模式):
适配器有三个,与处理器映射器是对应的:
if (this.handlerAdapters != null) { Iterator var2 = this.handlerAdapters.iterator(); while(var2.hasNext()) { HandlerAdapter adapter = (HandlerAdapter)var2.next(); if (adapter.supports(handler)) { return adapter; } } }
我们看先adapter.supports(handler)方法:
1、SimpleControllerHandlerAdapter的supports方法是
public boolean supports(Object handler) { return handler instanceof Controller; } 2、HttpRequestHandlerAdapter的是:
public boolean supports(Object handler) { return handler instanceof HttpRequestHandler; }
上面提到的ResourceHttpRequestHandler,就实现了HttpRequestHandler接口,
3、RquestMappingHandlerAdapter的是:
public final boolean supports(Object handler) { return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler); }
我们现在的这个请求就是用的这个 Adapter:
五、拿到Adaper后就会执行处理器执行链中的过滤器,不通过则直接返回:
if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { this.triggerAfterCompletion(request, response, (Exception)null); return false; } } } return true; }
六、通过则通过Adapter执行该处理器。
我们可以看到在通过adapter进行执行是会进行强转,这个与获取适配器是是对应的:
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return this.handleInternal(request, response, (HandlerMethod)handler); }
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler)handler).handleRequest(request, response); return null; }
七、关于适配器中处理器的执行执行:
(以我用的@Controller与@RquestMapping注解,注解的方法为例)我们可以看到,在处理器中,已经有RquestMapping注解的方法了。所以,适配器就执行该方法,获取Model,与View的名称,为了理解方便,这里将Model与view分开来,其实他们本身也是分开的。因此适配器通过执行对应的method,获取对应的Model,与view名称(单单就是一个名称,这时候还没有与themeleaf模版相结合):
如果没有获取到对应的ModelAndView,就使用默认的视图:
this.applyDefaultViewName(processedRequest, mv);
private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception { if (mv != null && !mv.hasView()) { String defaultViewName = this.getDefaultViewName(request); if (defaultViewName != null) { mv.setViewName(defaultViewName); } } }
八、获取到ModelAndView后,再执行过滤器的postHandle方法。
九、获取到ModelAndView后,就通过Model与View中名称,找到对应的themeleaf模板,并将模板中的字段填充到模板想要替代的字段中,同时将themeleaf模板以流的方式写入到Response中:
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
自此,关于doDispacher方法的执行、解析过程就大致完成。