我是靠谱客的博主 腼腆山水,最近开发中收集的这篇文章主要介绍Tomcat 源码分析 (Tomcat请求处理流程) (五),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

      • 0.前记
      • 1.请求处理流程分析
        • 1.1 EngineValve
        • 1.2 HostValve
        • 1.3 ContextValve
        • 1.4 WrapperValve
      • 2.Valve

0.前记

本章主要内容为在请求转交给Coyote适配器后的流程分析

紧接上文中请求交由Processor处理.

CoyoteAdapter.service()
此时在service方法中会调用CoyoteAdapter.service(),至此请求就即将被发送给Engine引擎.

 //获取Coyote适配器,并调用其service方法
getAdapter().service(request, response); 

在这里插入图片描述

1.请求处理流程分析

CoyoteAdapter.service()

在这里插入图片描述

这里先将CoyoteRequest转换为HttpServletRequest, 然后HttpServletRequest里设置CoyoteRequest

然后就是一系列的invoke方法

在这里插入图片描述

在这里插入图片描述

  1. 请求被Connector组件接收,创建RequestResponse对象。

  2. ConnectorRequestResponse交给Container,先通过Enginepipeline组件流经内部的每个Valve

  3. 请求流转到Hostpipeline组件中,并且经过内部Valve的过滤。

  4. 请求流转到Context的pipeline组件中,并且经过内部的Valve的过滤。

  5. 请求流转到Wrapperpipeline组件中,并且经过内部的Valve的过滤。

  6. Wrapper内部的WrapperValve创建FilterChain实例,调用指定的Servlet实例处理请求。

  7. 返回

1.1 EngineValve

得到EnginePipeline

在这里插入图片描述

得到管道的阀门, 默认为basicStandardEngineValve

StandardEngineValve.invoke()

在这里插入图片描述

1.2 HostValve

ErrorReportValve -> StandardHostValve

ErrorReportValve .invoke()

在这里插入图片描述

StandardHostValve.invoke()

在这里插入图片描述

1.3 ContextValve

AuthenticatorBase -> NonLoginAuthenticator -> StandardContextValue

StandardContextValve.invoke()

在这里插入图片描述

在这个方法中解释了为什么 /WEB-INF/下的资源不可以直接请求的原因

        MessageBytes requestPathMB = request.getRequestPathMB();
        if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/META-INF"))
                || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND); //解释了 /WEB-INF/下的资源为什么不能直接请求
            return;
        }

1.4 WrapperValve

Wrapper封装了Servlet的信息

StandardWrapperValve.invoke()

  1. 创建了Servlet对象
  2. 初始化了Servlet对象
  3. 准备FIlter链, 并执行Filter链
  4. 最后执行了Servlet.service()

在这里插入图片描述

创建并初始化Servlet

在这里插入图片描述

准备了一个FIlterChain

在这里插入图片描述

执行FilterChain

所以Tomcat在请求到达Servlet之前会执行FilterChain

ApplicationFilterChain.doFilter()

在这里插入图片描述

ApplicationFilterChain.internalDoFilter()

在这里插入图片描述

最后执行了Servlet.service()

然后执行了HttpServlet.service()

@Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {
 
        HttpServletRequest  request;
        HttpServletResponse response;
 
        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        service(request, response);
    }

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
 
        String method = req.getMethod();
 
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }
 
        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
 
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
 
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
 
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
 
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
 
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
 
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //
 
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
 
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

在转换完Response和Request后,service会调用重载的service方法,此时则开始正式执行Get,Post等等.

2.Valve

为阀门, 为一个责任链模式

在这里插入图片描述
通过getNext()获取到下一个阀门

在这里插入图片描述
实现类:

  • StandardWrapperValve
  • StandardContextValve
  • StandardHostValve
  • StandardEngineValve

最后

以上就是腼腆山水为你收集整理的Tomcat 源码分析 (Tomcat请求处理流程) (五)的全部内容,希望文章能够帮你解决Tomcat 源码分析 (Tomcat请求处理流程) (五)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部