Tomcat架构及源码学习笔记

一,Tomcat介绍

1,Tomcat官网:https://tomcat.apache.org

The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies.

Tomcat可以称为Web容器或Servlet容器。


计算机网络模型

2,怎么让Tomcat具有Servlet容器的功能呢?
tomcat的lib包中有servlet-api.jar包,对servlet规范进行了了实现。进而封装一个个的Servlet,实现方式如下:

public interface Servlet { 
      void init(ServletConfig config) throws ServletException; 
      ServletConfig getServletConfig(); 
      void service(ServletRequest req, ServletResponse res)throws ServletException, IOException; 
      String getServletInfo(); void destroy(); 
}

自定义servlet举例:

class LoginServlet extends HttpServlet{ 
      doGet(request,response){};
      doPost(request,response){}; 
}

web.xml中的配置

 <servlet>
        <servlet-name>LoginServlet</servlet-name> 
        <servlet-class>com.xxx.web.servlet.LoginServlet</servlet-class> 
</servlet> 
<servlet-mapping> 
        <servlet-name>LoginServlet</servlet-name> 
        <url-pattern>/login</url-pattern> 
</servlet-mapping>

3,Tomcat的代码原理:

class MyTomcat{ 
        List list=new ArrayList(); 
        //监听端口
        ServerSocket server=new ServerSocket(8080); 
        //接收请求
        Socket socket=server.accept(); 
        // 把请求和响应都封装在业务代码中的servlet 
        // 只要把业务代码中一个个servlets添加到tomcat中即可 
        list.add(servlets); 
}
tomcat容器

二,Tomcat源码

1,源码下载:https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.11/src/
2,产品目录文件含义

  • bin:主要用来存放命令,.bat是windows下,.sh是Linux下
  • conf:用来存放tomcat的一些配置文件
  • lib:存放tomcat依赖的一些jar包
  • log:存放tomcat在运行时产生的日志文件
  • temp:存放运行时产生的临时文件
  • webapps:存放应用程序
  • work:存放tomcat运行时编译后的文件,比如JSP编译后的文件
    3,源码导入与调试
    (1) 根据上面的链接下载对应的tomcat源码
    (2) 创建pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion> 
    <groupId>org.apache.tomcat</groupId> 
    <artifactId>Tomcat8.0</artifactId> 
    <name>Tomcat8.0</name> 
    <version>8.0</version>
    <build>
        <finalName>Tomcat8.0</finalName>
        <sourceDirectory>java</sourceDirectory> 
        <testSourceDirectory>test</testSourceDirectory> 
        <resources> 
            <resource> 
                <directory>java</directory> 
            </resource> 
        </resources> 
        <testResources> 
            <testResource> 
                <directory>test</directory> 
            </testResource> 
        </testResources>
        <plugins> 
            <plugin> 
                <groupId>org.apache.maven.plugins</groupId> 
                <artifactId>maven-compiler-plugin</artifactId> 
                <version>2.3</version> 
                <configuration> 
                    <encoding>UTF-8</encoding> 
                    <source>1.8</source> 
                    <target>1.8</target> 
                </configuration> 
            </plugin> 
        </plugins>
    </build>
    <dependencies> 
        <dependency> 
            <groupId>junit</groupId> 
            <artifactId>junit</artifactId> 
            <version>4.12</version> 
            <scope>test</scope> 
        </dependency> 
        <dependency>
            <groupId>org.easymock</groupId> 
            <artifactId>easymock</artifactId> 
            <version>3.4</version>
        </dependency>
        <dependency> 
            <groupId>ant</groupId> 
            <artifactId>ant</artifactId> 
            <version>1.7.0</version> 
        </dependency> 
        <dependency> 
            <groupId>wsdl4j</groupId> 
            <artifactId>wsdl4j</artifactId> 
            <version>1.6.2</version> 
        </dependency> 
        <dependency> 
            <groupId>javax.xml</groupId> 
            <artifactId>jaxrpc</artifactId> 
            <version>1.1</version> 
        </dependency>
        <dependency> 
            <groupId>org.eclipse.jdt.core.compiler</groupId> 
            <artifactId>ecj</artifactId> 
            <version>4.5.1</version> 
        </dependency> 
    </dependencies>
</project>

(3) 将源码导入到idea中
(4) 创建application,并填写name, Main class,VM options信息:


创建application

(5) 在当前源码目录创建apache-tomcat-8.0.11文件夹,并将一些文件拷贝到该目录下,如bin、conf、lib、logs、temp、webapps、work
(6) 启动,发现报错,找不到CookieFileter,直接删除
(7) 打开浏览器访问:localhost:8080

4,web端口监听验证
org.apache.catalina.connector.Connector#initInternal()--- org.apache.coyote.ProtocolHandler#init---org.apache.coyote.AbstractProtocol#init---org.apache.tomcat.util.net.AbstractEndpoint#init
--- org.apache.tomcat.util.net.JIoEndpoint#bind
--- org.apache.tomcat.util.net.DefaultServerSocketFactory#createSocket(int)

 @Override
    public ServerSocket createSocket (int port, int backlog)
            throws IOException {
        //Java IO | Socket
        return new ServerSocket (port, backlog);
    }

5,servlets容器验证
Context标签就是代表一个web项目。http://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

A Context represents a web application.

所以web项目的加载是从Context开始的。
org.apache.catalina.core.StandardContext#loadOnStartup

读取配置:org.apache.catalina.startup.ContextConfig#configureContext

 for (ServletDef servlet : webxml.getServlets().values()) {
            Wrapper wrapper = context.createWrapper();
            // Description is ignored
            // Display name is ignored
            // Icons are ignored
            if (servlet.getLoadOnStartup() != null) {
                wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
            }
            .....
            context.addChild(wrapper);
        }

读取web.xml:
org.apache.catalina.startup.ContextConfig#createWebXml

private static final StringManager sm =
        StringManager.getManager(Constants.PACKAGE_NAME);
public class Constants {
    public static final String PACKAGE_NAME =
            Constants.class.getPackage().getName();
    public static final String WEB_XML_LOCATION = "/WEB-INF/web.xml";
}

三,Tomcat架构分析

1,tomcat核心架构图:

tomcat核心架构图

架构图----源码----server.xml 一一对应的关系:
http://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

  • Server:代表整个容器
  • Service:是一个中间的桥梁,用于连接server和一个或多个Connector。
  • Connector:处理和客户端交互的请求。
  • Executor:代表一个线程池
  • Engine:作为pipeline,管理多个虚拟主机
  • Host:代表一个域名,可以支持多个虚拟主机。
  • Cluster:用于管理集群
  • Manager:用于管理session。

Tomcat两个核心组件:
对外:Connector
对内:Containner,源码中的关系:Container--Engine--Host--Context--Wrapper
SpringBoot内置的tomcat:
也有Connector,去掉了JIO的绑定。内置tomcat的源码和tomcat的架构基本一致。

2,Connector:

 <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8443" />

<Connector port="8481" protocol="AJP/1.3" redirectPort="8443" />
Connector

(1),EndPoint:监听通信端口,是对传输层的抽象,用来实现TCP/IP协议的。
对应的抽象类为AbstractEndPoint,有很多实现类,如NioEndPoint,JIoEndPoint。在其中有2个组件,一个是Acceptor,另一个是SocketProcessor。
Acceptor用来监听Socket连接请求,SocketProcessor用来处理接收到的Socket请求。

  • BIO/JIO:同步阻塞的IO,针对并发量较大的时候,效率很低,一个连接一个线程
  • NIO:同步非阻塞IO,并发量比较大的时候,比较占优势,单独一个线程,处理并发
  • Apr:与本地方法库进行交互
    Tomcat8默认使用NIO的方式,Tomcat默认使用BIO的方式。
    org.apache.catalina.connector.Connector#setProtocol
 public void setProtocol(String protocol) {
    if ("HTTP/1.1".equals(protocol)) {
         setProtocolHandlerClassName ("org.apache.coyote.http11.Http11NioProtocol");
    } else if ("AJP/1.3".equals(protocol)) {
         setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");
    } else if (protocol != null) {
       setProtocolHandlerClassName(protocol);
    }
}

(2),Processor:Processor是用于实现HTTP协议的,也就是说Processor是针对应用层协议的抽象。Processor接受来自EndPoint的Socket,然后解析成Tomcat Request和Tomcat Response对象,最后通过Adapter提交给容器。
对应的抽象类为AbstractProcessor,有很多实现类,比如AjpProcessor、Http11Processor等。
(3),Adapter:ProtocolHandeler接口负责解析请求并生成Tomcat Request类。需要把这个Requert对象转换成ServletRequest。 Tomcat引入CoyoteAdapert,这是适配器模式的应用,连接器调用CoyoteAdapter的service方法,传入的是Tomcat Request对象,CoyoteAdapert负责将Tomcat Request转成ServletRequest,再调用容器的service方法。

优化后的Connector

3,request请求
UML图:http://tomcat.apache.org/tomcat-8.0-doc/architecture/requestProcess/request-process.png

Connector UML图

四,Tomcat启动流程

1,BootStrap:
BootStrap是Tomcat的入口类:org.apache.catalina.startup.Bootstrap#main

//bootstrap.inin()
initClassLoaders(); //初始化自定义的类加载器
Thread.currentThread().setContextClassLoader(catalinaLoader); //启动线程
 SecurityClassLoad.securityClassLoad(catalinaLoader); //安全相关
//初始化组件,并进行协同工作
daemon.load(args);
daemon.start();

2,Catalina:
解析server.xml文件
创建server组件,并且调用其init和start方法
3,Lifecycle:
用于管理各组件的生命周期,包含init、start、stop、destroy方法
LifecycleBase实现了Lifecycle,利用的是模板设计模式
4,Server:
管理Service组件,并用调用其init和start方法
5,Service:
管理连接器和Engine
启动全流程:http://tomcat.apache.org/tomcat-8.0-doc/architecture/startup.html
启动流程的UML:http://tomcat.apache.org/tomcat-8.0-doc/architecture/startup/serverStartup.pdf

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

  • 1.基础 1.1 web概念 1).软件架构 1.c/s:客户端/服务器端 2.b/s:浏览器/服务器端 2) ....
    Cairo_fb29阅读 433评论 0 0
  • 前言: 先说明本人是小白进阶阶段,以写简书学习笔记的方式促进学习,如果有写的不恰当的或者不对的地方,请各位大佬帮忙...
    Manecho阅读 668评论 6 14
  • Tomcate笔记 最后模块作业是手写代码,实现tomcat的加载webapp目录下的项目,根据访问路径进行访问s...
    Shaun_41de阅读 370评论 0 0
  • 本文内容Web概述与Tomcat的安装及注意事项tomcat的目录结构与项目发布Eclipse集成Tomcat发布...
    Vincilovfang阅读 657评论 0 0
  • 1. WEB 服务器 按功能分类,Web Server可以分为: HTTP ServerApacheNginx.....
    专职跑龙套阅读 276评论 0 0