tomcat处理请求

6 篇文章 0 订阅
2 篇文章 0 订阅

Tomcat是一个基于组件的服务器,它的构成组件都是可配置的

其各个组件都在Tomcat安装目录下的../conf/server.xml文件中配置,server.xml文件源代码如下:

Tomcat主要组件服务器Server,服务Service(Catalina),连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。

一个Container容器和一个或多个Connector组合在一起,加上其他一些支持的组件共同组成一个Service服务,有了Service服务便可以对外提供能力了,但是Service服务的生存需要一个环境,这个环境便是Server,Server组件为Service服务的正常使用提供了生存环境,Server组件可以同时管理一个或多个Service服务。

  • 一个Tomcat只有一个server,server服务器有多个service。
  • 一个service有一个engine(即一个Container):engine是service组件中用来分析协议的引擎机器,它从一个或多个connector上接收请求,并将请求交给对应的虚拟主机进行处理,最后返回完整的响应数据给connector,通过connector将响应数据返回给客户端。只有一个engine元素必须嵌套在每个service中,且engine必须在其所需要关联的connector之后,这样在engine前面的connector都可以被此engine关联,而在engine后面的connector则被忽略,因为一个service中只允许有一个engine
  • service 由多个connector  和一个container 组成。一个Container可以选择多个Connector。加上其他一些支持的组件共同组成一个Service服务
  • connector  是请求接收器,负责接收请求和把socket转化为request及response转化
<?xml version="1.0" encoding="UTF-8"?>
<!--顶层类元素,可以包含多个Service-->
<Server port="8005" shutdown="SHUTDOWN">  
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <!--顶层类元素,可包含一个Engine(container),多个connector-->
  <Service name="Catalina">
  <!--连接器类元素,代表通信接口-->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <!--容器类元素,为特定的service组件处理客户请求-->
    <Engine name="Catalina" defaultHost="localhost">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
        </Realm>
        <!--容器类元素,为特定的虚拟主机组件处理客户请求-->
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>

tomcat

1.Connector组件

一个Connector组件将在某个指定的端口上侦听客户请求,接收浏览器发过来的tcp连接请求,创建一个Request和一个Response对象分别用于和其你去端交换数据,然后会产生一个线程来处理这个请求并把产生的Request和Response对象传给Engine,从Engine中获得响应并返回给客户端。 Tomcat有两个经典的Connector,一个直接侦听来自浏览器的HTTP请求,另外一个侦听来自其他的WebServer的请求。Cotote HTTP/1.1 Connector在端口8080处侦听来自客户浏览器的HTTP请求,Coyote JK2 Connector在端口8009处侦听其他WebServer的Servlet/JSP请求。 Connector 最重要的功能就是接收连接请求然后分配线程让 Container来处理这个请求,所以这必然是多线程的,多线程的处理是 Connector 设计的核心。

  • 不同协议的请求有不同的ProtocolHandler处理,ProtocolHandler由endpoint,processor,Adapter  组成。

  • Endpoint 接收请求,处理底层的socket网络请求,交由Hander接口处理。

  • Handler 调用Processor将socket请求封装成request,.

  • 最后由Adapter 适配对应的Servlet容器进行处理请求。

  • AsyncTimeout 处理异步超时的请求。

  • Container 负责具体的请求处理和返回请求结果。

2、Container

Container是容器的父接口,该容器的设计用的是典型的责任链的设计模式,它由四个自容器组件构成,分别是Engine、Host、Context、Wrapper。这四个组件是负责关系,存在包含关系。通常一个Servlet class对应一个Wrapper,如果有多个Servlet则定义多个Wrapper,如果有多个Wrapper就要定义一个更高的Container,如Context。 Context定义在父容器 Host 中,其中Host 不是必须的,但是要运行 war 程序,就必须要 Host,因为 war 中必有 web.xml 文件,这个文件的解析就需要 Host 了,如果要有多个 Host 就要定义一个 top 容器 Engine 了。而 Engine 没有父容器了,一个 Engine 代表一个完整的 Servlet 引擎。

  • engine: engine 表示管理器,管理多个站点,一个service只有一个engine。
  • Host: 站点,虚拟主机。可以配置多个。
  • Context: 代表tomcat下运行的一套程序,比如 doc,Root.Root  默认是主应用程序。即访问时默认的访问。
  • Wrapper: 封装Servlet。
  • 那么container是如何通过这四个容器进行处理请求的呢?
  • 责任链模式:Pipeline-Value  管道的责任链模式。
  • 每个Pipeline都有一个基础的Value,而且是在管道的最后一个执行,这个Value叫做BaseValue,BaseValue是不可删除的;在上层容器的管道的BaseValue中会调用下层容器的管道。
  • 那么请求就是一层层的从上到下进行处理,每层只处理自己处理的事情。
  • 处理完成后就可以返回response给Connector,由Connector返回给客户端。

 tomcatserver

3、Context

Context 代表 Servlet 的 Context,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢? Tomcat5 以前是通过一个 Mapper 类来管理的,Tomcat5 以后这个功能被移到了 request 中,在前面的时序图中就可以发现获取子容器都是通过 request 来分配的

4、Tomcat Server处理一个HTTP请求的过程如下图所示: 

1.用户在浏览器中输入网址localhost:8080/test/index.jsp,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得;

2.Connector把该请求交给它所在的Service的Engine(Container)来处理,并等待Engine的回应;

3.Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host

4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理);

5.path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL Pattern为*.jsp的Servlet,对应于JspServlet类;

6.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等;

7.Context把执行完之后的HttpServletResponse对象返回给Host;

8.Host把HttpServletResponse对象返回给Engine;

9.Engine把HttpServletResponse对象返回Connector;

10.Connector把HttpServletResponse对象返回给客户Browser。

----------------

在HttpllProcessor的process方法里,会先从socket里读取http请求数据,并解析请求头,构造Request对象和Response对象,然后调用Adapter.service()方法。

Adapter.service()完成请求行以及请求体的解析,并把解析出来的信息封装到Request和Response对象中,Adapter(确切说是org.apache.catalina.connector.CoyoteAdapter)是connector和container的桥梁,经过这一步,请求就从connector传递到container里了,

Adapter.service()方法之后便将封装了Request以及Response对象的Socket传给Container容器了。

到了Container,Container容器是子容器的父接口,所有的子容器都必须实现这个接口。在Tomcat中Container容器的设计是典型的责任链设计模式,其有四个子容器:Engine、Host、Context和Wrapper。这四个容器之间是父子关系,Engine容器包含Host,Host包含Context,Context包含Wrapper。

Engine容器处理请求调用了StandardEngineValve的invoke方法。在StandardEngineValve的invoke方法中,选择可用的Host容器处理当前的请求,选择Host容器后,就调用其invoke方法,所以具体的处理就转移到了Host容器。

在Host容器的invoke中,为特定的请求URL选择一个Context容器。

Context容器是一个Web项目的代表,主要管理Servlet实例,在Tomcat中Servlet实例是以Wrapper出现的。

在StandardContextValve的invoke()方法中,做了这几件事:
1.禁止直接访问WEB-INF或者META-INF目录下的资源
2.选择具体的Wrapper处理请求
3.返回一个确认响应
4.调用Wrapper容器的invoke方法,把处理请求交给StandardWrapperValve处理。
Wrapper容器负责管理一个Servlet,包括Servlet的装载、初始化、资源回收。Wrapper是最底层的容器,其不能在添加子容器了。Wrapper是一个接口,其标准实现类是StandardWrapper。调用loadServlet的allocate方法的时候调用了StandardWrapperValve的invoke方法,在Wrapper容器获得请求后,通过allocate方法从实例池栈中弹出一个servlet实例来处理这个请求,servlet实例被封装成filterChain对象,紧接着通过一系列的过滤器过滤到达servlet.service()方法。之后发生的过程就是我们熟悉的request获取参数并用response进行响应的过程了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值