栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

tomcat看源码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

tomcat看源码

一.环境搭建
1.官网下载tomcat9
2.idea打开
新建pom文件




    4.0.0
    org.apache.tomcat
    tomcat9
    tomcat-9.0.41
    9.0.41
    
        tomcat-9.0.41
        java
        
        
            
                java
            
        
        
            
                test
            
        
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.6.0
                
                    UTF-8
                    1.8
                    1.8
                
            
            
                org.apache.maven.plugins
                maven-jar-plugin
                3.0.2
            
        
    
     
        
            org.apache.ant
            ant
            1.9.5
        
         
         
         
             biz.aQute.bnd
             biz.aQute.bndlib
             5.2.0
             provided
         

         
         
         
             org.apache.tomcat
             tomcat-jasper
             9.0.41
         
         
            org.apache.ant
            ant-apache-log4j
            1.9.5
        
        
            org.apache.ant
            ant-commons-logging
            1.9.5
        
        
            javax.xml.rpc
            javax.xml.rpc-api
            1.1
        
        
            wsdl4j
            wsdl4j
            1.6.2
        
        
            org.eclipse.jdt.core.compiler
            ecj
            4.6.1
        
    

3.乱码解决
idea20

idea2018

-Duser.language=en
-Duser.region=US
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=UTF-8

4.webapps
目录下放自己项目 如建的icoding

5.conf下server.xml虚拟主机使用



如果把应用不放在webapps下 需要新建个虚拟主机

  

  
  

context对应一个应用 部署时还可以放在其他路径,自己配路径

二.架构




Wrapper 里可以放servlet 一个servlet可以有多个请求

public interface Wrapper extends Container {

    
    public static final String ADD_MAPPING_EVENT = "addMapping";

    
    public static final String REMOVE_MAPPING_EVENT = "removeMapping";

请求流程

6)


三.核心组件

Lifecycle 生命周期Container:EngineHostContextWrapperServletPipelineVavleConnectorLifecycleListener -》 HostConfig

都是模板模式
请求进来 容器执行阀门 阀门获取下个容器

1.基础设计
Tomcat要实现两个核心功能:
1) 处理Socket连接,负责网络字节流与Request和Response对象的转化。
2) 加载和管理Servlet,以及具体处理Request请求。
因此Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流,容器负责内部处理逻辑
2.协议处理器与适配器
接上文,连接器并不能直接处理数据。利用协议处理器与适配器完成工作
Tomcat 支持的IO模型(自8.5/9.0 版本起,Tomcat 移除了 对 BIO 的支持):

IO模型(传输层) 描述
NIO : 非阻塞I/O,采用Java NIO类库实现。
NIO2 : 异步I/O,采用JDK 7最新的NIO2类库实现。
APR : 采用Apache可移植运行库实现,是C/C++编写的本地库。如果选择该方 案,需要单独安装APR库。

应用层协议 描述
HTTP/1.1 : 这是大部分Web应用采用的访问协议。
AJP : 用于和Web服务器集成(如Apache),以实现对静态资源的优化以及 集群部署,当前支持AJP/1.3。
HTTP/2 : HTTP 2.0大幅度的提升了Web性能。下一代HTTP协议 , 自8.5以及9.0 版本之后支持。

3、连接器组件
连接器中的各个组件的作用如下:
1、EndPoint

1) EndPoint : Coyote 通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的。
2) Tomcat 并没有EndPoint 接口,而是提供了一个抽象类AbstractEndpoint ,里面定义了两个内部类:Acceptor和SocketProcessor。Acceptor用于监听Socket连接请求。SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到
线程池来执行。而这个线程池叫作执行器(Executor)。

2、Processor

Processor : Coyote 协议处理接口 ,如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。

3、ProtocolHandler

ProtocolHandler: Coyote 协议接口, 通过Endpoint 和 Processor , 实现针对具体协议的处理能力。Tomcat 按照协议和I/O 提供了6个实现类 : AjpNioProtocol ,AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol ,Http11AprProtocol。我们在配置tomcat/conf/server.xml 时 , 至少要指定具体的ProtocolHandler , 当然也可以指定协议名称 , 如 : HTTP/1.1 ,如果安装了APR,那么
将使用Http11AprProtocol , 否则使用 Http11NioProtocol 。

4、Adapter

由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类来“存放”这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,也就意味着,不能用TomcatRequest作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是TomcatRequest对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法。

Http11NIOProtocol表示非阻塞模式Http协议的通信,它主要包含NioEndpoint组件和Http11NioProcessor组件。一个连接到来时,将被注册到NioChannel队列中,由Poller负责检测通道的读写事件,并在创建任务后扔进线程池中。
4、Catalina

Catalina负责管理Server,而Server表示着整个服务器。Server下面有多个服务Service,每个服务都包含着多个连接器组件Connector(Coyote 实现)和一个容器组件Container。在Tomcat 启动的时候,会初始化一个Catalina的实例。
组件 职责
Catalina : 负责解析Tomcat的配置文件 , 以此来创建服务器Server组件,并根据 命令来对其进行管理
Server : 服务器表示整个Catalina Servlet容器以及其它组件,负责组装并启动 Servlet引擎,Tomcat连接器。Server通过实现Lifecycle接口,提供了 一种优雅的启动和关闭整个系统的方式
Service : 服务是Server内部的组件,一个Server包含多个Service。它将若干个 Connector组件绑定到一个Container(Engine)上
Connector : 连接器,处理与客户端的通信,它负责接收客户请求,然后转给相关 的容器处理,最后向客户返回响应结果
Container : 容器,负责处理用户的servlet请求,并返回对象给web用户的模块

四.运行原理
1.启动原理图

Bootstrap.main()

—>Catalina.load()

—>parseServerXml(true);

—>逐行解析文件

—>创建Lifecycle对象

—>对象创建结束

Bootstrap 里main方法 init初始化 会

2.Tomcat里面的模板模式

Lifecycle(Server、Service、Engine、Host、Context、Wrapper)

abstract Lifecyclebase
【init()-abstract void initInternal()】
【start()-abstract void startInternal()】
【stop()-abstract void stopInternal()】
【destroy()-abstract void destroyInternal()】
以下的所有组件都会实现真正的生命周期方法而被调用

StandardServerStandardServiceStandardEngineStandardHostStandardContextStandardWrapper

3、请求处理流程

    Connector组件Endpoint中的Acceptor监听客户端套接字连接并接收Socket。将连接交给线程池Executor处理,开始执行请求响应任务。Processor组件读取消息报文,解析请求行、请求体、请求头,封装成Request对象。Mapper组件根据请求行的URL值和请求头的Host值匹配由哪个Host容器、Context容器、Wrapper容器处理请求。CoyoteAdaptor组件负责将Connector组件和Engine容器关联起来,把生成的Request对象和响应对象Response传递到Engine容器中,调用 Pipeline。Engine容器的管道开始处理,管道中包含若干个Valve、每个Valve负责部分处理逻辑。执行完Valve后会执行基础的 Valve–StandardEnginevalve,负责调用Host容器的Pipeline。Host容器的管道开始处理,流程类似,最后执行 Context容器的Pipeline。Context容器的管道开始处理,流程类似,最后执行 Wrapper容器的Pipeline。Wrapper容器的管道开始处理,流程类似,最后执行 Wrapper容器对应的Servlet对象的处理方法

1、请求被Acceptor(socket.accept())接受到数据

2、Acceptor把请求封装成 SocketWrapperbase,直接发给线程池

3、SocketWrapperbase的run开始执行。使用 poller 拿到通道东西进行处理。

4、拿到协议处理器【ProtocolHandler】》AbstractProtocol里面有 Http11NioProtocol。处理HTTP1.1的

5、ProtocolHandler 创建出 Processor来处理请求

6、Http11Processor 里面有 CoyoteAdapter

7、Http11Processor 调用 service 方法

1、准备CoyoteRequest对象,并且分配buffer空间准备来读取Channel里面的数据2、解析请求头、请求行等信息3、准备请求prepareRequest();校验之前解析的请求数据是否合法4、Http11Processor 调用 getAdapter().service(request, response);

1、拿到适配器 CoyoteAdapter,调用service()。主要就是CoyoteRequest和HttpRequest的互转

1、没有转换过,connector创建一个新的HttpServletRequest对象,保存CoyoteRequest的内容

装饰模式 HttpServletRequest.getMethod–》CoyoteRequest.getMethod。不用挨个属性搬家

调用容器;CoyoteAdapter 的 343 行请求开始流转。拿到每个容器里面的管道的阀门,开始执行请求处理

connector.getService().getContainer().getPipeline().getFirst().invoke(
        request, response);
//得到Service?里面的容器也就是Engine?

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/726527.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号