• Tomcat源码分析-请求流程(一)


    调试分析

    由于源码一步一步调试效率太低了,所以我这里就直接在自定义的Filter类上的doFilter方法中打上断点

    先通过线程栈来大致看一下,请求的过程中执行了哪些步骤
    每一个方法点进去,然后给它整理成一张表格,如下:
    分析:
    • 上图执行执行次数最多的方法是invoke
    • 所有调用invoke方法的类都以Valve结尾
    • 调用invoke方法都是通过getNext和getFirst
     
    第一步
     
    首先从invoke方法执行多的地方开始,我们来分析一个Valve这个到底是什么东西?
    通过上面,我们可以看出,调用invoke方法的所有的类,都是以Valve结尾的,说明这些类都有valve特征?那到底valve有什么特征呢?
    Valve下面有一个ValveBase基类,所有的类都继承于该基类,并且Valve下面有两个重要的方法,getNext 和 invoke
    public interface Valve {
        public Valve getNext();
        public void setNext(Valve valve);
        public void invoke(Request request, Response response) throws IOException, ServletException;
        // 省略其它...
    }
    根据类中的描述,valve所有的方法都和pipeline有关,那么pipeline到底是什么东西呢?
    pipeline意为管道,valve为阀门,这两个东西当然密不可分了。但是还是不明白这两个东西是什么?具体有什么功能?
    我们先来看一下Pipeline接口
    public interface Pipeline {
        public Valve getBasic();
        public void setBasic(Valve valve);
        public void addValve(Valve valve);
        public Valve[] getValves();
        public void removeValve(Valve valve);
        public Valve getFirst();
        public boolean isAsyncSupported();
        public Container getContainer();
        public void setContainer(Container container);
    }

    既然有管道、有阀门,那是不是应该也有一个容器的东西,那这样一来就好理解了,每一个请求好比像是水,它想要进入到容器里是需要通过管道,然后经过阀门的层层过滤,最后到达容器。从这也体现了Tomcat的设计者们将现实生活中的实例引入到程序中的设计思想。

     
    第二步
     
    了解了valve这个是什么东西,我们接下来看看它底下是如何层层过滤的?
    Valve过滤顺序从上至下
    1. StandardEngineValve
    2. AccessLogValve
    3. ErrorReportValve
    4. StandardHostValve
    5. NonLoginAuthenticator
    6. StandardContextValve
    7. StandardWrapperValve
    从上面标红的几个关键字能看出什么来不?
    依次向下传递:Engine --> Host --> Context --> Wrapper  这个是不是和我们的server.xml 文件Engine组件的层级关系一样的
    即,当通过http请求 http://localhost:8080/jsp-web/test/1 访问tomcat的时候执行如下步骤:
    1. 通过localhost主机名称找到Host
    2. /jsp-web找到对应的Context
    3. 通过/test/1 找到对应的Wrapper,最终就能访问到你写的Filter
    备注:上面的AccessLogValve,为访问日志,记录每次访问的url。
     
     
    第三步
     
    在Http11NioProcessor类中的process方法中,通过 getAdapter() 获得CoyoteAdapter对象,然后调用service方法
    接下来我们来看一下CoyoteAdapter这个类是什么东西?coyote 是丛林狼的意思,为什么tomcat设计者要把这个命名为种动物的名称?
    关于官网对coyote介绍:
    Coyote HTTP / 1.1连接器元件代表一个支持HTTP / 1.1协议的连接器组件。除了执行servlet和JSP页面的功能外,它能够充当独立的Web服务器。该组件的特定实例侦听服务器上特定TCP端口号上的连接。可以将一个或多个此类连接器配置为单个服务的一部分,每个连接器都转发到关联的引擎以执行请求处理并创建响应。
    • CoyoteAdapter这个类位于org.apache.catalina.connector 包下
    • tomcat也有一个tomcat-coyote.jar
    • tomcat的Request有两个,一个是coyote包下的,另一个是connector包下的。getAdapter().service(request, response) 方法中request参数属于coyote包下的,它下一步要执行的invoke(request, response) 方法中request参数属于connector包下的
    • Http11NioProtocol 和 Http11NioProcessor 在tomcat-coyote.jar包下
    从上面的几个特点得出结论:
    • CoyoteAdapter 与connector连接有关
    • CoyoteAdapter 是一个适配器
    • CoyoteAdapter 是tomcat-coyote框架的桥梁
     
     
    总结
     
    通过上面步骤,给它简单画了一个流程图:
    Tomcat请求流程如下:
    当用户发送HTTP请求http://localhost/context/wrapper/1 
    1. NioEndPoint接收到请求(执行其内部类SocketProcessor的run方法);
    2. Http11NioProtocol$Http11ConnectionHandler处理
    3. Http11NioProcessor处理
    4. CoyoteAdapter将coyote类型Request/Response转换成Servlet类型的Request/Response对象,把请求交给Pipeline管道
    5. Engine阀门开始处理,拿到对应的Host,开始将请求交给Host处理;
    6. Host阀门开始处理,拿到对应的Context,开始将请求交给Context处理;
    7. Context阀门开始处理,拿到对应的Wrapper,开始将请求交给Wrapper处理;
    8. Wrapper阀门开始处理,拿到对应的FilterChain,交给FilterChain处理;
    9. FilterChain中包含了一个过滤器filters的数组,从该数组中的第一个Filter开始依次执行(filters是在加载web.xml文件的时候设置进去的,这也是过滤器的执行顺序会按照web.xml配置的顺序的执行原因);
     
  • 相关阅读:
    Android进阶之关闭所有activty
    弹出窗口插件欣赏
    关于之前放在google 的资源不能下载的解决方案
    图片垂直居中的使用技巧
    关于采用业务用例视图来展示、归纳、整理业务用例的三点指导原则
    操作系统引导的那点事
    可视化拾色器
    AE中删除属性字段
    AE中添加属性字段
    vs2005c#中用户组件在工具箱中不能自动出现的解决办法
  • 原文地址:https://www.cnblogs.com/caoxb/p/12861206.html
Copyright © 2020-2023  润新知