zoukankan      html  css  js  c++  java
  • Tomcat学习笔记


    title: tomcat源码学习日志
    date: 2018-07-07 23:32:43
    tags:
    - tomcat
    - 源码学习
    categories: 技·术

    Tomcat是什么

    Tomcat是ServletJSP、java EL表达式、WebSocket的实现。

    Tomcat 7.0实现了Servlet 3.0JSP 2.2。提供了更多feature来开发和部署web应用和web服务。

    官方资源汇总

    编译源码

    • 下载Tomcat7源码
    • 配置JDK1.6
    • 配置1.9.x版本的Ant
    • 将build.xml中的base-apache.loc.1=https://www.apache.org/dyn/closer.lua?action=download&filename=替换为base-apache.loc.1=https://archive.apache.org/dist
    • 在tomcat目录下执行ant

    源码阅读日志

    整体理解

    • 主类/主方法:org.apache.catalina.startup包下的Bootstrap类。
    • 几个重要的目录(或者说环境变量):
    主目录 含义
    { $CATALINA_HOME } Tomcat安装目录
    { $CATALINA_BASE } 每个实例分别的根目录(可选,默认情况等同于{ $CATALINA_HOME })
    CATALINA_HOME
        ├─bin       // 诸如启动、停止等脚本。
        ├─conf      // 配置文件
        ├─logs      // 默认日志文件路径
        └─webapps   // web应用路径
    

    架构理解

    名称 意义
    Server 代表整个容器。用户基本不会变动它。提供了Server接口。
    Service 作为一个生存在Server中的组件,将许多Connector与一个Engine连接,起媒介作用。
    Engine 代表某个Service的请求过程。一个Service连接着多个ConntectorEngine接收这些Connector的请求,处理请求,并返回。提供了Engine接口。
    Host 一个Tomcat可包含多个域名,Host则维护这些域名。t提供了Host接口和完善的实现。
    Connector 用于处理与客户端的通信。如Http Connector
    Context 代表一个Web应用。一个Host包含多个Context,分别处于唯一的路径。提供了Context和完善的实现。

    按照以上概念可以绘图:

    启动步骤

    根据官方文档,tomcat启动序列分为两个步骤:1)从命令行启动 2)处理命令行参数

    一、从命令行启动

    类:org.apache.catalina.startup.Bootstrap

    执行内容:

    1. 安装一系列classLoader
    2. (以反射)读取启动类;
    3. 完成Bootstrap.daemon.init()方法。

    二、处理命令行参数(start,stop)

    类:org.apache.catalina.startup.Bootstrap

    执行内容(start):

    1. Catalina.setAwait(true)
    2. Catalina.load():
      1. 初始化基本文件夹:initDirs() -> 设置诸如catalina.home/case等属性;
      2. 初始化命名服务:setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,org.apache.naming.java.javaURLContextFactory ->default)
      3. 创建xml文件转化器:createStartDigester()
      4. 读取server.xml并用转化器(digester)将其解析。digester是一个“XML-对象”映射器,将根据server.xml定义的内容创建对象。到目前为止,容器其实还没有开始初始化。
      5. System.outSystem.err分配给SystemLogHandler类。
      6. 调用所有组件的初始化方法。此步骤将令每个对象通过JMX代理注册其本身。在此步骤中,Connector也将初始化适配器。适配器也是一种组件,用来执行请求预处理。例如HTTP1.1适配器:org.apache.coyote.http11.Http11Protocol
    3. Catalina.start():
      1. 启动NamingContext,将所有JNDI引用绑定其中。
      2. 启动Server下的所有service。此步骤启动引擎(Engine)。
      3. 启动主机:StandardHost
        1. 配置一个错误阀门,用于将不同的HTTP错误码为HTML。
        2. 设置标准主机阀门,将web应用的类加载器与线程上下文绑定,它也用来为请求找到相应的session
        3. 启动HostConfig组件。此组件部署所有web应用,即webappconf/Catalina/localhost/*.xml
        4. HostConfig将为上下文创建一个Digester,它将调用ContextConfig.start()。这个方法将处理默认的web.xmlconf/web.xml,然后处理所有的应用web.xmlWEB-INF/web.xml
      4. 在容器的生命周期中,存在一个后台线程,用来不断检查上下文(context)是否改变,即war文件、context文件、web.xml文件等的改变。如果改变,则重新加载。(stop/remove/deploy/start
    4. 当Tomcat(在HTTP端口)接收到一个请求时:
      1. 该请求将被一个独立的线程接收。此线程在ThreadPoolExecutor类中。它在一个ServerSocket.accpet()方法中等待请求。
      2. ThreadPoolExecutor分配一个TaskThread来处理此请求。
      3. 处理器(processor)处理该请求。如果是HTTP请求,则是Coyote Http11Processor来处理。调用了process方法。此处理器将继续检查socket的输入流,直到连接断开,或者达到keep alive point
      4. 此HTTP请求将被内部的缓冲类(Http11InputBuffer)解析。此解析类将解析出请求行、请求头等等,将结果存储在一个Coyote请求中。此request包含所有的HTTP信息,如servernameportscheme等。
      5. 处理器维护着一个Adapter(引用),在本例中是CoyoteAdapter。一旦请求已经被解析,那么Http11Processor调用该adapterservice()方法。在此service方法中,Request包含一个CoyoteRequest和一个CoyoteResponse(第一次则为null)。CoyoteRequest(Response)实现了HttpRequest(Response)HttpServletRequest(Response)。适配器通过Mapper来处理requestcontext等。
      6. 当解析完成之后,CoyoteAdapter调用它的容器(StandardEngine),调用所有的invoke()方法。
      7. StandardEngine.invoke()方法调用容器的pipeline.invoke()方法。
      8. StandardHostValve调用与request相关的context上的pipeline
      9. Context pipeline调用的第一个阀门是FormAuthenticator阀门。接下来是StandardContextValveStandardContextValve调用与context相关的所有上下文监听器。然后调用Wrapper组件的所有pipeline
      10. 编译JSP,调用实际的servlet
    5. servlet类的调用

    优美代码

    观察到,一个典型的类中,可以被分成:

        // ------------------------------------------------------- Static Variables
        // -------------------------------------------------------------- Variables
        // -------------------------------------------------------- Private Methods
        // ----------------------------------------------------------- Main Program
    

    典型的生命周期方法有:

        public void init()
        public void init(String[] arguments)
        public void start()
        public void stop()
        public void stopServer()
        public void stopServer(String[] arguments)
        public void destroy()
    
  • 相关阅读:
    webpack基础
    LeetCode232. 用栈实现队列做题笔记
    mysql 时间加减一个月
    leetcode 1381. 设计一个支持增量操作的栈 思路与算法
    LeetCode 141. 环形链表 做题笔记
    leetcode 707. 设计链表 做题笔记
    leetcode 876. 链表的中间结点 做题笔记
    leetcode 143. 重排链表 做题笔记
    leetcode 1365. 有多少小于当前数字的数字 做题笔记
    LeetCode1360. 日期之间隔几天 做题笔记
  • 原文地址:https://www.cnblogs.com/liyeliang/p/9338858.html
Copyright © 2011-2022 走看看