前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >走进JavaWeb技术世界5:初探Tomcat的HTTP请求过程

走进JavaWeb技术世界5:初探Tomcat的HTTP请求过程

原创
作者头像
Java技术江湖
修改2019-10-22 10:34:58
7360
修改2019-10-22 10:34:58
举报
文章被收录于专栏:微信公众号【Java技术江湖】

本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

https://github.com/h2pl/Java-Tutorial

喜欢的话麻烦点下Star哈

文章首发于我的个人博客:

www.how2playlife.com

本文是微信公众号【Java技术江湖】的《走进JavaWeb技术世界》其中一篇,本文部分内容来源于网络,为了把本文主题讲得清晰透彻,也整合了很多我认为不错的技术博客内容,引用其中了一些比较好的博客文章,如有侵权,请联系作者。

该系列博文会告诉你如何从入门到进阶,从servlet到框架,从ssm再到SpringBoot,一步步地学习JavaWeb基础知识,并上手进行实战,接着了解JavaWeb项目中经常要使用的技术和组件,包括日志组件、Maven、Junit,等等内容,以便让你更完整地了解整个Java Web技术体系,形成自己的知识框架。

为了更好地总结和检验你的学习成果,本系列文章也会提供每个知识点对应的面试题以及参考答案。

如果对本系列文章有什么建议,或者是有什么疑问的话,也可以关注公众号【Java技术江湖】联系作者,欢迎你参与本系列博文的创作和修订。

文末赠送8000G的Java架构师学习资料,需要的朋友可以到文末了解领取方式,资料包括Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南、Java程序员面试指南等干货资源)

<!-- more -->

走进JavaWeb技术世界5:初探Tomcat的HTTP请求过程

初探Tomcat的HTTP请求过程

图片描述
图片描述

前言:

1.作为Java开发人员,大多都对Tomcat不陌生,由Apache基金会提供技术支持与维护,因为其免费开源且易用,作为Web服务器深受市场欢迎,所以有必要对其进行深入的研究,本系列皆以Tomcat 8.5为研究课题,下载地址:https://tomcat.apache.org/download-80.cgi

2.下图为 apache-tomcat-8.5.23.zip 在windows解压后的目录。

图片描述
图片描述

下面是解压后的一些关键目录:

代码语言:txt
复制
* /bin - 启动和停止服务等批处理文件. ( *.sh) 文件 (为Unix系统)、 (*.bat) 文件 (for Windows系统)是一个功能性的复制文件. 自从Win32 command-line 开始是一些单一的,缺乏功能的组件, 现在有一些拓展性的功能
* /conf - 配置文件和一些相关的DTD文件. 最重要的是 server.xml. 它是这个容器最主要的配置文件.
* /logs - 日志文件会打印到这里
* /webapps - 这里是你的应用程序部署的地方.

3.从最本质上讲,tomcat为一个servlet容器,首先研究一下Tomcat的架构,如下图:

图片描述
图片描述

架构诠释:

1.Server(服务器)是Tomcat构成的顶级构成元素,所有一切均包含在Server中,Server的实现类StandardServer可以包含一个到多个Services,Service的实现类为StandardService调用了容器(Container)接口,其实是调用了Servlet Engine(引擎),而且StandardService类中也指明了该Service归属的Server;

2.Container: 引擎(Engine)、主机(Host)、上下文(Context)和Wraper均继承自Container接口,所以它们都是容器。但是,它们是有父子关系的,在主机(Host)、上下文(Context)和引擎(Engine)这三类容器中,引擎是顶级容器,直接包含是主机容器,而主机容器又包含上下文容器,所以引擎、主机和上下文从大小上来说又构成父子关系,虽然它们都继承自Container接口。

3.连接器(Connector)将Service和Container连接起来,首先它需要注册到一个Service,它的作用就是把来自客户端的请求转发到Container(容器),这就是它为什么称作连接器的原因。

从功能的角度将Tomcat源代码分成5个子模块,分别是:

Jsper模块: 这个子模块负责jsp页面的解析、jsp属性的验证,同时也负责将jsp页面动态转换为java代码并编译成class文件。在Tomcat源代码中,凡是属于org.apache.jasper包及其子包中的源代码都属于这个子模块;

Servlet和Jsp模块: 这个子模块的源代码属于javax.servlet包及其子包,如我们非常熟悉的javax.servlet.Servlet接口、javax.servet.http.HttpServlet类及javax.servlet.jsp.HttpJspPage就位于这个子模块中;

Catalina模块: 这个子模块包含了所有以org.apache.catalina开头的java源代码。该子模块的任务是规范了Tomcat的总体架构,定义了Server、Service、Host、Connector、Context、Session及Cluster等关键组件及这些组件的实现,这个子模块大量运用了Composite设计模式。同时也规范了Catalina的启动及停止等事件的执行流程。从代码阅读的角度看,这个子模块应该是我们阅读和学习的重点。

Connector模块: 如果说上面三个子模块实现了Tomcat应用服务器的话,那么这个子模块就是Web服务器的实现。所谓连接器(Connector)就是一个连接客户和应用服务器的桥梁,它接收用户的请求,并把用户请求包装成标准的Http请求(包含协议名称,请求头Head,请求方法是Get还是Post等等)。同时,这个子模块还按照标准的Http协议,负责给客户端发送响应页面,比如在请求页面未发现时,connector就会给客户端浏览器发送标准的Http 404错误响应页面。

Resource模块: 这个子模块包含一些资源文件,如Server.xml及Web.xml配置文件。严格说来,这个子模块不包含java源代码,但是它还是Tomcat编译运行所必需的。

Tomcat的组织结构

  • Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的是Catalina servlet容器,其他组件按照一定的格式要求配置在这个顶层容器中。  Tomcat的各种组件都是在Tomcat安装目录下的/conf/server.xml文件中配置的。

由Server.xml的结构看Tomcat的体系结构

代码语言:txt
复制
<Server>                                                //顶层类元素,可以包括多个Service   
代码语言:txt
复制
    <Service>                                           //顶层类元素,可包含一个Engine,多个Connecter
代码语言:txt
复制
        <Connector>                                     //连接器类元素,代表通信接口
代码语言:txt
复制
                <Engine>                                //容器类元素,为特定的Service组件处理客户请求,要包含多个Host
代码语言:txt
复制
                        <Host>                          //容器类元素,为特定的虚拟主机组件处理客户请求,可包含多个Context
代码语言:txt
复制
                                <Context>               //容器类元素,为特定的Web应用处理所有的客户请求
代码语言:txt
复制
                                </Context>
代码语言:txt
复制
                        </Host>
代码语言:txt
复制
                </Engine>
代码语言:txt
复制
        </Connector>
代码语言:txt
复制
    </Service>
代码语言:txt
复制
</Server>

实际源码如下:

代码语言:txt
复制
<?xml version='1.0' encoding='utf-8'?>
代码语言:txt
复制
<Server port="8005" shutdown="SHUTDOWN">
代码语言:txt
复制
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
代码语言:txt
复制
  <!-- Security listener. Documentation at /docs/config/listeners.html
代码语言:txt
复制
  <Listener className="org.apache.catalina.security.SecurityListener" />
代码语言:txt
复制
  -->
代码语言:txt
复制
  <!--APR library loader. Documentation at /docs/apr.html -->
代码语言:txt
复制
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
代码语言:txt
复制
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
代码语言:txt
复制
  <Listener className="org.apache.catalina.core.JasperListener" />
代码语言:txt
复制
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
代码语言:txt
复制
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
代码语言:txt
复制
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
代码语言:txt
复制
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
代码语言:txt
复制
  <!-- Global JNDI resources
代码语言:txt
复制
       Documentation at /docs/jndi-resources-howto.html
代码语言:txt
复制
  -->
代码语言:txt
复制
  <GlobalNamingResources>
代码语言:txt
复制
    <!-- Editable user database that can also be used by
代码语言:txt
复制
         UserDatabaseRealm to authenticate users
代码语言:txt
复制
    -->
代码语言:txt
复制
    <Resource name="UserDatabase" auth="Container"
代码语言:txt
复制
              type="org.apache.catalina.UserDatabase"
代码语言:txt
复制
              description="User database that can be updated and saved"
代码语言:txt
复制
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
代码语言:txt
复制
              pathname="conf/tomcat-users.xml" />
代码语言:txt
复制
  </GlobalNamingResources>
代码语言:txt
复制
  <!-- A "Service" is a collection of one or more "Connectors" that share
代码语言:txt
复制
       a single "Container" Note:  A "Service" is not itself a "Container",
代码语言:txt
复制
       so you may not define subcomponents such as "Valves" at this level.
代码语言:txt
复制
       Documentation at /docs/config/service.html
代码语言:txt
复制
   -->
代码语言:txt
复制
  <Service name="Catalina">
代码语言:txt
复制
    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
代码语言:txt
复制
    <!--
代码语言:txt
复制
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
代码语言:txt
复制
        maxThreads="150" minSpareThreads="4"/>
代码语言:txt
复制
    -->
代码语言:txt
复制
    <!-- A "Connector" represents an endpoint by which requests are received
代码语言:txt
复制
         and responses are returned. Documentation at :
代码语言:txt
复制
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
代码语言:txt
复制
         Java AJP  Connector: /docs/config/ajp.html
代码语言:txt
复制
         APR (HTTP/AJP) Connector: /docs/apr.html
代码语言:txt
复制
         Define a non-SSL HTTP/1.1 Connector on port 8080
代码语言:txt
复制
    -->
代码语言:txt
复制
    <Connector port="8080" protocol="HTTP/1.1"
代码语言:txt
复制
               connectionTimeout="20000"
代码语言:txt
复制
               redirectPort="8443" />
代码语言:txt
复制
    <!-- A "Connector" using the shared thread pool-->
代码语言:txt
复制
    <!--
代码语言:txt
复制
    <Connector executor="tomcatThreadPool"
代码语言:txt
复制
               port="8080" protocol="HTTP/1.1"
代码语言:txt
复制
               connectionTimeout="20000"
代码语言:txt
复制
               redirectPort="8443" />
代码语言:txt
复制
    -->
代码语言:txt
复制
    <!-- Define a SSL HTTP/1.1 Connector on port 8443
代码语言:txt
复制
         This connector uses the BIO implementation that requires the JSSE
代码语言:txt
复制
         style configuration. When using the APR/native implementation, the
代码语言:txt
复制
         OpenSSL style configuration is required as described in the APR/native
代码语言:txt
复制
         documentation -->
代码语言:txt
复制
    <!--
代码语言:txt
复制
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
代码语言:txt
复制
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
代码语言:txt
复制
               clientAuth="false" sslProtocol="TLS" />
代码语言:txt
复制
    -->
代码语言:txt
复制
    <!-- Define an AJP 1.3 Connector on port 8009 -->
代码语言:txt
复制
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
代码语言:txt
复制
    <!-- An Engine represents the entry point (within Catalina) that processes
代码语言:txt
复制
         every request.  The Engine implementation for Tomcat stand alone
代码语言:txt
复制
         analyzes the HTTP headers included with the request, and passes them
代码语言:txt
复制
         on to the appropriate Host (virtual host).
代码语言:txt
复制
         Documentation at /docs/config/engine.html -->
代码语言:txt
复制
    <!-- You should set jvmRoute to support load-balancing via AJP ie :
代码语言:txt
复制
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
代码语言:txt
复制
    -->
代码语言:txt
复制
    <Engine name="Catalina" defaultHost="localhost">
代码语言:txt
复制
      <!--For clustering, please take a look at documentation at:
代码语言:txt
复制
          /docs/cluster-howto.html  (simple how to)
代码语言:txt
复制
          /docs/config/cluster.html (reference documentation) -->
代码语言:txt
复制
      <!--
代码语言:txt
复制
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
代码语言:txt
复制
      -->
代码语言:txt
复制
      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
代码语言:txt
复制
           via a brute-force attack -->
代码语言:txt
复制
      <Realm className="org.apache.catalina.realm.LockOutRealm">
代码语言:txt
复制
        <!-- This Realm uses the UserDatabase configured in the global JNDI
代码语言:txt
复制
             resources under the key "UserDatabase".  Any edits
代码语言:txt
复制
             that are performed against this UserDatabase are immediately
代码语言:txt
复制
             available for use by the Realm.  -->
代码语言:txt
复制
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
代码语言:txt
复制
               resourceName="UserDatabase"/>
代码语言:txt
复制
      </Realm>
代码语言:txt
复制
      <Host name="localhost"  appBase="webapps"
代码语言:txt
复制
            unpackWARs="true" autoDeploy="true">
代码语言:txt
复制
        <!-- SingleSignOn valve, share authentication between web applications
代码语言:txt
复制
             Documentation at: /docs/config/valve.html -->
代码语言:txt
复制
        <!--
代码语言:txt
复制
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
代码语言:txt
复制
        -->
代码语言:txt
复制
        <!-- Access log processes all example.
代码语言:txt
复制
             Documentation at: /docs/config/valve.html
代码语言:txt
复制
             Note: The pattern used is equivalent to using pattern="common" -->
代码语言:txt
复制
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
代码语言:txt
复制
               prefix="localhost_access_log." suffix=".txt"
代码语言:txt
复制
               pattern="%h %l %u %t "%r" %s %b" />
代码语言:txt
复制
      </Host>
代码语言:txt
复制
    </Engine>
代码语言:txt
复制
  </Service>
代码语言:txt
复制
</Server>

由上可得出Tomcat的体系结构: 

图一:Tomcat的体系结构

由上图可看出Tomca的心脏是两个组件:Connecter和Container。一个Container可以选择多个Connecter,多个Connector和一个Container就形成了一个Service。Service可以对外提供服务,而Server服务器控制整个Tomcat的生命周期。

Tomcat Server处理一个HTTP请求的过程

图三:Tomcat Server处理一个HTTP请求的过程

Tomcat Server处理一个HTTP请求的过程

1、用户点击网页内容,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得。2、Connector把该请求交给它所在的Service的Engine来处理,并等待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。  

参考文章

http://www.360doc.com/content/10/0730/19/61151_42573873.shtml

https://my.oschina.net/leamon/blog/210133

https://www.cnblogs.com/xll1025/p/11366264.html

https://www.cnblogs.com/small-boy/p/8042860.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 走进JavaWeb技术世界5:初探Tomcat的HTTP请求过程
    • 初探Tomcat的HTTP请求过程
      • Tomcat的组织结构
        • 由Server.xml的结构看Tomcat的体系结构
      • Tomcat Server处理一个HTTP请求的过程
        • 参考文章
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档