SpringMVC源码-执行流程
1. Dispatcher核心执行方法:
2.doDispatcher详细细节:
1)、所有请求过来,Dispatcher收到请求;
2)、调用doDispatcher()方法进行处理;
》1.getHandler():根据当前请求地址找到能处理这个请求目标处理器类
根据当前请求在HandlerMapping找到那个请求的映射信息,获取到目标处理器类
》2.getHandlerAdapter():根据当前处理器类获取到能够执行这个处理器类的适配器;
根据当前的处理器类,找到当前类的适配器(HandlerAdapter)
》3.使用刚才获取到的适配器执行目标方法;
》4.目标方法执行完后会返回一个ModelAndView对象;
》5.将ModelAndView的信息转发到具体的页面,然后在请求域中取出ModelAndView中的模型数据;
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 {
//1.检查是否为文件上传请求 processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request;
//2.根据当前的请求地址找到哪个类能来处理 mappedHandler = this.getHandler(processedRequest);
//3.如果没有找到对应的处理器(控制器)来处理这个请求,就报404或抛异常
if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; } //4.拿到能执行这个类所有方法的适配器(反射工具);
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; } //处理器方法被调用;控制器(Controller)、处理器(Handler)
//5.适配器来执行目标方法,将目标方法执行完成后的返回值作为视图名,设置保存到ModelAndView中
//目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装到ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //6.如果没有视图名,设置一个默认的视图名 this.applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException("Handler dispatch failed", var21); } //转发到目标页面
//7.根据方法最终执行完成后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取 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); } } }
3、getHandler()细节:怎么根据当前请求找到那个类来处理
》1.getHandler()会返回目标处理器类的执行链;
mappedHandler = this.getHandler(processedRequest);
》2.HandlerMapping:处理器映射,HandlerMappings里面保存了每一个处理器能处理哪些方法的映射信息;
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable 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; }
4、如何找到目标处理器类 额适配器,要拿适配器去执行目标方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { Iterator var2 = this.handlerAdapters.iterator(); while(var2.hasNext()) { HandlerAdapter adapter = (HandlerAdapter)var2.next(); 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"); }
5、DispatcherServlet中有几个引用类型的属性:
SpringMVC的九大组件:
SpringMVC在工作的时候,关键位置都是由这些组件完成的;共同点:九大组件全部是接口,接口就是规范,提供了非常强大的扩展性;
/** 文件上传解析器 */
private MultipartResolver multipartResolver;
/** 区域解析器和国际化有关 */
private LocaleResolver localeResolver;
/** 主题解析器;强大的主题效果切换 */
private ThemeResolver themeResolver;
/** handler映射信息;HandlerMapping */
private List<HandlerMapping> handlerMappings;
/** handler适配器 */
private List<HandlerAdapter> handlerAdapters;
/** SpringMVC强大的异常解析功能:异常解析器 */
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** 请求到视图名转换器 */
private RequestToViewNameTranslator viewNameTranslator;
/** FlsahMap+Manager:SpringMVC中进行重定向携带数据的功能 */
private FlashMapManager flashMapManager;
/** 视图解析器 */
private List<ViewResolver> viewResolvers;
DispatcherServlet中九大组件初始化的地方:服务器启动就初始化
组件的初始化:
去容器中找这个组件,如果没有找到就用默认配置;有些组件是用类型找的,有些组件使用bean-id找的;
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}