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);
    }

  

posted @ 2019-06-23 19:36  SweetBaby。  阅读(677)  评论(0编辑  收藏  举报