美文网首页javaWeb
DispatchServlet请求处理流程源码解析

DispatchServlet请求处理流程源码解析

作者: fanyank | 来源:发表于2018-01-15 17:35 被阅读1191次

DispatchServlet的service()

一个请求是从一个客户端发出,经过容器然后将请求交与合适的servlet,servlet调用service()方法来处理这个请求。
如下是 DispatchServlet 继承关系图。

dispatchServlet继承关系

我们主要关心上图中各类的 service() 方法。看看 DispatchServlet 中的 service() 方法来自哪里。

  • Servlet: Servlet为接口,只是声明了 service()方法。
  • GenericServlet: 抽象类,service() 方法交由子类实现。
  • HttpServlet: 抽象类,实现了 service() 方法,根据请求方式的不同,判断调用什么方法来处理请求。如果我们不用框架的话,那么只需要继承自 HttpServlet,然后重写 doGet()或者 doPost() 方法即可,重写的代码就是处理请求的过程所要执行的代码。
  • HttpServletBean: 继承HttpServlet 的service() 方法。
  • FramworkServlet: 重写 HttpServlet 的 service() 方法,目的是为了能够处理 PATCH 请求。什么是PATCH请求
  • DispatchServlet: 继承 FramworkServlet 的 service() 方法.

总结,DispatchServlet的 service() 方法来自父类 FramworkServlet,该方法既可以处理已知的请求(如GET,POST),又可以处理 PATCH 请求,然后根据请求方式的不同执行不同的处理过程。

DispatchServlet的doGet()等方法

我们知道一个servlet要想处理请求,必须重写doGet() doPost()等方法,DispatchServlet当然也不例外,那么DispatchServlet的 doGet(),doPost() 方法重写在哪里呢?答案是在其父类 FramworkServlet 中。DispatchServlet 直接继承即可。我们来看一下 FramworkServlet 部分源码。

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
        //增加对 PATCH 请求的处理
            if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
                processRequest(request, response);
            }
            else {
                super.service(request, response);
            }
      }

//重写doGet()方法
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
      processRequest(request, response);
    }
//重写doPost()方法
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);
}

好,通过以上代码,我们了解了无论什么样的请求方法,DispatchServlet 全部都委托给了一个 processRequest() 方法进行处理。如下是 processRequest() 方法源代码。

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        long startTime = System.currentTimeMillis();
        Throwable failureCause = null;

        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        LocaleContext localeContext = buildLocaleContext(request);

        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

        initContextHolders(request, localeContext, requestAttributes);

        try {
      //doService() FramworkServlet没有实现,只是简单定义,交由 DispatchServlet实现
            doService(request, response);
        }
        catch (ServletException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (IOException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (Throwable ex) {
            failureCause = ex;
            throw new NestedServletException("Request processing failed", ex);
        }

        finally {
            resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
                requestAttributes.requestCompleted();
            }

            if (logger.isDebugEnabled()) {
                if (failureCause != null) {
                    this.logger.debug("Could not complete request", failureCause);
                }
                else {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        logger.debug("Leaving response open for concurrent processing");
                    }
                    else {
                        this.logger.debug("Successfully completed request");
                    }
                }
            }

            publishRequestHandledEvent(request, response, startTime, failureCause);
        }
    }

深入了解 doService() 方法:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
  ...

  //设置上下文及其他属性,方便其他方法需要时从request获取
  request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
  request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
  request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
  request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

  FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
  if (inputFlashMap != null) {
    request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
  }
  request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
  request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

  try {
    //深入了解
    doDispatch(request, response);
  }
  finally {
    if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
      // Restore the original attribute snapshot, in case of an include.
      if (attributesSnapshot != null) {
        restoreAttributesAfterInclude(request, attributesSnapshot);
      }
    }
  }
}

继续深入了解 doDispatch() 方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  HttpServletRequest processedRequest = request;
  //HandlerExecutionChain,执行链,后面会详细说明
  HandlerExecutionChain mappedHandler = null;
  boolean multipartRequestParsed = false;

  WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

  try {
    //逻辑视图对象
    ModelAndView mv = null;
    Exception dispatchException = null;

    try {
      //检查请求是否为文件上传请求,如果是使文件上传解析器可用
      processedRequest = checkMultipart(request);
      //如果是文件上传请求multipartRequestParsed值为true
      multipartRequestParsed = (processedRequest != request);

      //获取处理该请求的handler
      //深入了解
      mappedHandler = getHandler(processedRequest);
      if (mappedHandler == null || mappedHandler.getHandler() == null) {
        noHandlerFound(processedRequest, response);
        return;
      }

      // Determine handler adapter for the current request.
      HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

      // Process last-modified header, if supported by the handler.
      String method = request.getMethod();
      boolean isGet = "GET".equals(method);
      if (isGet || "HEAD".equals(method)) {
        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
        if (logger.isDebugEnabled()) {
          logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
        }
        if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
          return;
        }
      }

      if (!mappedHandler.applyPreHandle(processedRequest, response)) {
        return;
      }

      // Actually invoke the handler.
      mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

      if (asyncManager.isConcurrentHandlingStarted()) {
        return;
      }

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

HandlerExecutionChain:
包含一个处理请求的处理器(Handler),同时包含若干个对该请求实施拦截的拦截器(HandlerInterceptor),当HandlerMapping 返回 HandlerExecutionChain 后, DispatchServlet 将请求交给定义在 HandlerExecutionChain 中的拦截器和处理器一并处理。

HandlerExecutionChain

拦截器可以在三个地方对请求进行处理,分别是:

  • boolean preHandler(request,response,handler): 请求到达 adapter 之前。返回 true 继续传递请求,false 不传递请求,将请求驳回。
  • void postHandler(request,response,handler): adapter 处理完之后。
  • void afterCompletion(request,response,handler,exception): 响应已经被渲染之后。
  1. 深入了解 DispatchServlet.getHandler() 方法。

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //循环遍历默认的处理器映射,如果找到handler,直接返回
            for (HandlerMapping hm : this.handlerMappings) {
                ...
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
            return null;
        }
    

    HandlerMapping 本身是一个接口,只有一个方法 getHandler(),本例中的 this.handlerMappings 中包含3个 HandlerMapping 的实现,他们将按照先后顺序查找该请求的处理器映射,找到即返回。

    如下是本例中包含的3个处理器映射实现类:

    1. RequestMappingHandlerMapping
    2. BeanNameUrlHandlerMapping
    3. SimpleUrlHandlerMapping

    如下是 HandlerMapping 继承关系图

    HandlerMappingInherice

    每个实现类都继承了HandlerMapping接口,故每个处理器映射都有一个用来查找handler的getHandler()方法,我们以本例的 RequestMappingHandlerMapping 类为例子来了解该类的 getHandler() 方法。

    我们由上面的继承关系图可得知:
    RequestMappingHandlerMapping 是 AbstractHandlerMapping 和 AbstractHandlerMethodMapping 的子类。
    以下是 AbstractHandlerMapping 的部分源码.

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
      //主要调用了 getHandlerInternal() 方法
      Object handler = getHandlerInternal(request);
        if (handler == null) {
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // Bean name or resolved handler?
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = getApplicationContext().getBean(handlerName);
        }
      //根据请求的路径将handler和对应的拦截器包装成一个handlerExecutionChain对象
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        if (CorsUtils.isCorsRequest(request)) {
            CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
            CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
            CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
            executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
        }
        return executionChain;
    }
    

    通过查看源代码可知主要调用了 getHandlerInternal() 方法,该方法由子类 AbstractHandlerMethodMapping 实现。如下是子类 AbstractHandlerMethodMapping 的部分源码。

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
      //获取请求的URL路径
      String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
      //获取读锁
        this.mappingRegistry.acquireReadLock();
        try {
        //根据请求路径找到对应的handler方法
            HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        //返回HandlerMethod对象
            return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
        }
        finally {
        //释放获取到的读锁
            this.mappingRegistry.releaseReadLock();
        }
    }
    

    该方法执行完毕之后,继续执行 AbstractHandlerMapping.getHandler()方法中的其余部分。其余部分所做的主要工作就是根据请求的URL路径找到拦截该路径的拦截器,然后将handler和这些拦截器封装成为一个 HandlerExecutionChain 对象返回。

    至此,DispatchServlet.doDispatch() 方法的 mappedHandler 对象初始化完毕。

  2. 深入了解 DispatchServlet.getHandlerAdapter() 方法
    如下是 DispatchServlet.getHandlerAdapter() 方法部分源码。

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
  for (HandlerAdapter ha : this.handlerAdapters) {
          if (ha.supports(handler)) {
              return ha;
          }
      }
  }

HandlerAdapter 为一个接口,该接口内部定义了如下三个方法:

  • supports(): 给出一个 handler,查看该 HandlerAdapter 是否支持该 handler。
  • handle(): 使用本 HandlerAdapter 代理执行这个 handler 中的方法。
  • getLastModified(): 查看该请求的 lastModified 值

this.handlerAdapters 为 实现 HandlerAdapter 接口的实现类集合,默认的实现类有如下三个:

  • RequestMappingHandlerAdapter
  • HttpRequestHandlerAdapter
  • SimpleControllerHandlerAdapter

继承关系如下图所示:


HandlerAdapterInherice

未完待更...

相关文章

网友评论

    本文标题:DispatchServlet请求处理流程源码解析

    本文链接:https://www.haomeiwen.com/subject/xuydoxtx.html