DispatcherServlet的具体工作流程

1.前端控制器的架构?DispatcherServlet

在这里插入图片描述
分析得到处理流程

请求一来,先到达HttpServlet的service方法,service决定调用具体的doGet,doPost等方法,然后由于我们DispatcherServlet的父抽下类FrameworkServlet重写了HttpServlet的doGet等方法,于是就会调用FrameworkServlet的doGet等方法,然后在doGet等方法中都会调用本类的processRequest(request, response)这个方法,方法内的关键代码就是调用doService(request, response)由于doService在FrameworkServlet中为抽象方法,所以调用的DispatcherServlet重写的doService方法,在doService方法中调用了最为关键的doDispatch方法,所以我们主要来研究
DispatcherServlet的doDispatch方法
在这里插入图片描述

DispatcherServlet的doDispatch源码(分析在代码中)

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    //声明变量,没啥意思
   HttpServletRequest processedRequest = request;
   HandlerExecutionChain mappedHandler = null;
   boolean multipartRequestParsed = false;

   //拿到一个异步管理器。。
   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

   try {
      ModelAndView mv = null;
      Exception dispatchException = null;

      try {
         //检查当前请求是否为文件上传请求   若是,就包装request
         processedRequest = checkMultipart(request);
         multipartRequestParsed = (processedRequest != request);

         //决定我们当前请求用哪一个处理器(controller)
         mappedHandler = getHandler(processedRequest);
         //如果没找到能处理当前请求的处理器  这执行以下代码(抛异常或者404)
         if (mappedHandler == null) {
            noHandlerFound(processedRequest, response);
            return;
         }

         //决定当前请求要用哪一个处理器的适配器(拿到controller的适配器,适配器来反射执行方法)
         //适配器名:AnnotationMethodHandlerAdapter
         HandlerAdapter ha = 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的方法被调用,用适配器ha执行的)
         //返回一个ModelAndView实例  将目标方法返回值作为试图名,保存到其内View中
         //目标方法不论怎么写,最终适配器执行后都会将执行后的信息封装成ModelAndView
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
          
		//异步处理器判断是否异步方法,如果是,直接请求借书结束
         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }
		//如果方法执行完返回了一个void,没有视图名,则用默认视图名
         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 NestedServletException("Handler dispatch failed", err);
      }
       //转发到目标页面(渲染)
       //根据方法最终执行完后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
   catch (Exception ex) {
      triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
   }
   catch (Throwable err) {
      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 {
         // Clean up any resources used by a multipart request.
         if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
         }
      }
   }
}
  

怎么根据当前请求就能找到哪个类能来处理?:getHandler()细节

getHandler()会返回目标处理器类的执行链——HandlerExecutionChain的一个实例

//其内DefaultAnnotationHandlerMapping中的hanlderMap保存了所有的请求——控制器映射信息
private List<HandlerMapping> handlerMappings;

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   //handlerMappings保存了每一个处理器能处理哪些请求的映射信息
   if (this.handlerMappings != null) {
      for (HandlerMapping mapping : this.handlerMappings) {
         HandlerExecutionChain handler = mapping.getHandler(request);
         if (handler != null) {
            return handler;
         }
      }
   }
   return null;
}

hanlderMap:ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的hanlderMap属性中

如何找到目标处理器类的适配器?:getHandlerAdapter()细节

三种适配器

  • HttpRequestHandlerAdapter
  • SimpleControllerHandlerAdapter
  • RequstMappingHandlerAdapter(spingmvc低版本是AnnotationMethodHandlerAdapter)
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        //遍历所有的适配器(三种)
        //最终拿到AnnotationMethodHandlerAdapter(能解析注解方法)的适配器
        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");
}

HttpRequestHandlerAdapter的supports()方法——以HttpRequestHandlerAdapter为例:

public boolean supports(Object handler) { return (handler instanceof HttpRequestHandler);}

就是判断你当前的handler是不是某类型的,这里我们是注解的Controller,是RequstMappingHandlerAdapter类型

RequstMappingHandlerAdapter的supports()方法

public final boolean supports(Object handler) {
   return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

适配器怎么执行的方法?:handler()细节

调用的是RequstMappingHandlerAdapter的父抽象类的handler()方法,然后调用了子类的handleInternal()实现方法

protected ModelAndView handleInternal(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   ModelAndView mav;
   checkRequest(request);

   //如果需要,在synchronized块中执行invokeHandlerMethod.
   if (this.synchronizeOnSession) {
      HttpSession session = request.getSession(false);
      if (session != null) {
         Object mutex = WebUtils.getSessionMutex(session);
         synchronized (mutex) {
            mav = invokeHandlerMethod(request, response, handlerMethod);
         }
      }
      else {
         //执行目标方法(没有HttpSession可用)
         mav = invokeHandlerMethod(request, response, handlerMethod);
      }
   }
   else {
      //执行目标方法(不需要同步会话)
      mav = invokeHandlerMethod(request, response, handlerMethod);
   }

   if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
      if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
         applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
      }
      else {
         prepareResponse(response);
      }
   }
   //返回ModelAndView
   return mav;
}

怎么来到目标页面的?: processDispatchResult方法

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
      @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
      @Nullable Exception exception) throws Exception {

   boolean errorView = false;

   if (exception != null) {
      if (exception instanceof ModelAndViewDefiningException) {
         logger.debug("ModelAndViewDefiningException encountered", exception);
         mv = ((ModelAndViewDefiningException) exception).getModelAndView();
      }
      else {
         Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
         mv = processHandlerException(request, response, handler, exception);
         errorView = (mv != null);
      }
   }

   // Did the handler return a view to render?
   if (mv != null && !mv.wasCleared()) {
       //解析完毕,来到页面
      render(mv, request, response);
      if (errorView) {
         WebUtils.clearErrorRequestAttributes(request);
      }
   }
   else {
      if (logger.isTraceEnabled()) {
         logger.trace("No view rendering, null ModelAndView returned.");
      }
   }

   if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
      // Concurrent handling started during a forward
      return;
   }

   if (mappedHandler != null) {
      // Exception (if any) is already handled..
      mappedHandler.triggerAfterCompletion(request, response, null);
   }
}

render(mv, request, response);方法执行解析完毕,来到页面

视图解析具体的流程在后续文章会分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大恐龙的小弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值