Tomcat基本原理

思考 :怎样让Tomcat具备Web服务的功能呢?

在服务端用HTTP来监听,协议不好写,不妨用Java封装好的Socket作为监听。

class MyTomcat{
    ServerSocket server=new ServerSocket(8080);
    // 等待客户端的连接请求 Socket socket=server.accept();
 }

  

1.2.3 Servlet容器

思考 :怎样让Tomcat具有Servlet容器的功能呢?说白了就是能够装一个个的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();
}
class LoginServlet extends HttpServlet {
    doGet(request,response){} doPost(request,response){}
}
<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.gupao.web.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

1.2.4 优化MyTomcat

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

1.2.5 画个图

1.2.6 获得的信息

(1)tomcat需要支持servlet规范

tomcat/lib/servlet-api.jar

(2)web容器

希望tomcat源码中也有new ServerSocket(8080)的代码,一会儿验证

(3)servlet容器

希望tomcat源码中也有list.add(servlets)的代码,一会儿验证

02 产品和源码

2.1 Version choose

Tomcat版本:Tomcat8.0.11
各个版本下载地址 :https://archive.apache.org/dist/tomcat

2.2 产品目录文件含义

(1)bin:主要用来存放命令,.bat是windows下,.sh是Linux下

(2)conf:主要用来存放tomcat的一些配置文件

(3)lib:存放tomcat依赖的一些jar包

(4)logs:存放tomcat在运行时产生的日志文件

(5)temp:存放运行时产生的临时文件

(6)webapps:存放应用程序

(7)work:存放tomcat运行时编译后的文件,比如JSP编译后的文件

2.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,名称为gp-tomcat,并且填写相关信息

name:gp-tomcat Main class:org.apache.catalina.startup.BootstrapVM options:-Dcatalina.home="apache-tomcat-8.0.11

(5)在当前源码目录创建apache-tomcat-8.0.11文件夹,并且将一些文件拷贝到该目录下

比如bin conf lib logs temp webapps work

(6)启动,发现报错,找不到CookieFilter,直接删除

(7)打开浏览器访问:localhost:8080

03 验证上述猜想

(1)web容器 (2)servlet容器

3.1 Web容器

Connector.initInternal()->

protocolHandler.init()->

AbstractProtocol.init()->

endpoint.init()->

bind()->

Apr,JIo,NIO,NIO2->

JIo即Socket实现方式

3.2 Servlet容器

web项目--->Context标签--->Context.class--->StandardContext--->loadOnStartup()

证明Wrapper就是Servlet :

加载:ContextConfifig.webConfifig()—>getContextWebXmlSource()—>Constants.ApplicationWebXml

解析:ContextConfifig.webConfifig()—>confifigureContext(webXml)—>context.createWrapper()

3.3. 进一步思考

既然Context表示标签能够表示Web项目,那按照server.xml文件来看的话,不就能够把tomcat架构图画出来

了吗?或者按照之前的简略版推导出来。

Context,Host,Engine,Service等

为什么知道找Connector?

再次回到conf/web.xml文件,发现有一个Connector标签,而且还可以配置port端口,我们能够联想到监听端口,

按照配置文件到源码类的经验,源码中一定会有这样一个Connector类用于端口的监听。

conclusion :架构图<--->server.xml<--->源码 三者有一一对应的关系

04 Tomcat架构设计
4.1 各个组件含义
官网 :https://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

4.2 两个核心组件

Connector:主要负责处理Socket连接,以及Request与Response的转化

Container:包括Engine、Host、Context和Wrapper,主要负责内部的处理以及Servlet的管理

4.2.1 Connector

设计思想 :高内聚、低耦合

EndPoint:提供字节流给Processor

Processor:提供Tomcat Request对象给Adapter

Adapter:提供ServletRequest给容器

4.2.1.1 EndPoint

监听通信端口,是对传输层的抽象,用来实现 TCP/IP 协议的。

对应的抽象类为AbstractEndPoint,有很多实现类,比如NioEndPoint,JIoEndPoint等。在其中有两个组件,一个

是Acceptor,另外一个是SocketProcessor。

Acceptor用于监听Socket连接请求,SocketProcessor用于处理接收到的Socket请求。

4.2.1.2 Processor

Processor是用于实现HTTP协议的,也就是说Processor是针对应用层协议的抽象。

Processor接受来自EndPoint的Socket,然后解析成Tomcat Request和Tomcat Response对象,最后通过Adapter

提交给容器。

对应的抽象类为AbstractProcessor,有很多实现类,比如AjpProcessor、Http11Processor等。

4.2.1.3 Adpater

ProtocolHandler接口负责解析请求并生成 Tomcat Request 类。

需要把这个 Request 对象转换成 ServletRequest。

Tomcat 引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用 CoyoteAdapter 的 sevice 方法,传入的是

Tomcat Request 对象,CoyoteAdapter 负责将 Tomcat Request 转成 ServletRequest,再调用容器的 service 方

法。

4.2.1.4 优化图解

Endpoint接收Socket连接,生成一个SocketProcessor任务提交到线程池去处理
SocketProcessor的run方法会调用Processor组件去解析应用层协议,Processor通过解析生成Request对象后,会调 用Adapter的service方法。

4.2.2 Container

通过Connector之后,我们已经能够获得对应的Servlet

4.3 Request Process Flow
官网 :https://tomcat.apache.org/tomcat-8.0-doc/architecture/requestProcess/request-process.png

05 思维扩展

5.1 自定义类加载器

WebAppClassLoader,打破了双亲委派模型:先自己尝试去加载这个类,找不到再委托给父类加载器。

通过复写findClass和loadClass实现。

5.2 Session管理

Context中的Manager对象,查看Manager中的方法,可以发现有跟Session相关的。

Session 的核心原理是通过 Filter 拦截 Servlet 请求,将标准的 ServletRequest 包装一下,换成 Spring 的

Request 对象,这样当我们调用 Request 对象的 getSession 方法时,Spring 在背后为我们创建和管理

Session。

06 Tomcat源码解读

6.1 BootStrap

BootStrap是Tomcat的入口类

bootstrap.init() 和 创建Catalina

6.2 Catalina

解析server.xml文件

创建Server组件,并且调用其init和start方法

6.3 Lifecycle

用于管理各个组件的生命周期

init、start、stop、destroy

LifecycleBase实现了Lifecycle,利用的是模板设计模式

6.4 Server

管理Service组件,并且调用其init和start方法

6.5 Service

管理连接器和Engine

原文地址:https://www.cnblogs.com/flgb/p/12081713.html

时间: 2024-08-08 03:05:41

Tomcat基本原理的相关文章

《Java推荐书籍吐血整理推荐技术书50本pdf》已拿BAT,网易,头条Offer大佬力荐

前言:Java开发工程师一般负责后端开发,当然也有专门做Java Web的工程师,但是随着前后端的分离,越来越多的Java工程师需要往大后端方向发展.今天我们就来介绍一下Java后端开发者的书单.首先要感谢一下某大佬力推的后端书架,初学阶段读到了很多好书直到现在都让他印象深刻. 大佬说他在两年的学习历程中看了很多的书,其中不乏XXX入门到精通,XXX王者归来,XXX指南什么的. 虽然这类书确实毛病很多,但是作为非科班的他来说,当时还是看的津津有味.直到后来我他看到一些优秀的书籍,以及大佬的大佬哥

Java工程师必备书单

Java开发工程师一般负责后端开发,当然也有专门做Java Web的工程师,但是随着前后端的分离,越来越多的Java工程师需要往大后端方向发展. 今天我们就来介绍一下Java后端开发者的书单. 首先要感谢一下江南白衣大大的后端书架,让我在初学阶段读到了很多好书,直到现在都印象深刻. 我在两年的学习历程中看了很多的书,其中不乏XXX入门到精通,XXX王者归来,XXX指南什么的. 虽然这类书确实毛病很多,但是作为非科班的我来说,当时还是看的津津有味.直到后来我看到一些优秀的书籍,以及白衣哥的书架,我

【转】Java工程师必备书单

江湖路险,你我同行. Java开发工程师一般负责后端开发,当然也有专门做Java Web的工程师,但是随着前后端的分离,越来越多的Java工程师需要往大后端方向发展. 今天我们就来介绍一下Java后端开发者的书单. 首先要感谢一下江南白衣大大的后端书架,让我在初学阶段读到了很多好书,直到现在都印象深刻. 我在两年的学习历程中看了很多的书,其中不乏XXX入门到精通,XXX王者归来,XXX指南什么的. 虽然这类书确实毛病很多,但是作为非科班的我来说,当时还是看的津津有味.直到后来我看到一些优秀的书籍

CentOS7+Tomcat 生产系统部署

1 准备OS账户 安全起见,本着最小权限原则,生产系统决不同意使用root账户来执行tomcat.为此,建立新账户tomcat,并设定登录password. useradd tomcat passwd tomcat 2 配置防火墙放行8080port并做80port映射 在/etc/firewalld/services/文件夹下新建一个名为tomcat.xml的文件,内容例如以下: <? xml version="1.0" encoding="utf-8"?

Tomcat最大连接数问题

Tomcat的server.xml中Context元素的以下参数应该怎么配合适 <Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" acceptCount="100" /> 答曰: maxThreads="150" 表示最多同时处理150个连接 minSpareTh

从零开始写一个Tomcat(贰)--建立动态服务器

上文书说道如何通过http协议建立一个静态的服务器来访问静态网页,但我们选择tomcat最主要的原因还是因为它能动态的执行servlet,这边文章将引导你实现一个能够运行servlet的服务器,这个简易的服务器符合tomcat的基本原理,但真的tomcat远不是这么简单,即使是15年前的tomcat4. 1.主程序逻辑分离 既然要实现动态的服务器,首先我们要实现模式的识别,在tomcat中,tomcat通过读取web.xml,在servlet的配置中通过url的模式来匹配servlet,我们这里

Tomcat安装、配置、优化及负载均衡详解

一.常见JavaWeb服务器      1.WebLogic:是BEA公司的产品.WebSphereAS:是IBM公司的产品.JBossAS:红帽公司的产品,可以自行了解      2.Tomcat服务器:             Sun公司在推出的小型Servlet/JSP调试工具的基础上发展起来的一个优秀的Servlet容器,Tomcat本身完全用java语言编写,所以tomcat的运行需要java的支持,所以要先安装JDK,才能运行.目前是Apache开源软件组织的一个软件项目,它的官网

Tomcat是怎么工作的(2) -- 动手实现山寨版的简单Web Server

本文先讲解一下Java web server都是怎么工作的.web server也叫HTTP server——顾名思义它是用HTTP协议和客户端交互的.客户端一般就是各种各样的浏览器了.相信所有朋友都清楚这个基本事实,否则你也不会看到这个系列文章了. 基于Java的web server必然用到两个极其重要的类:java.net.Socket和java.net.ServerSocket,然后以HTTP消息进行交互. 1. HTTP协议简介(The Hypertext Transfer Protoc

cas协议,以及tomcat搭建cas服务器

1.      CAS 简介 1.1.  What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(属于 Web SSO ). CAS 开始于 2001 年, 并在 2004 年 12 月正式成为 JA-SIG 的一个项目. 1.2.  主要特性 1.   开源的.多协议的 SSO 解决方案: Protocols : Custom Protoc