1.引入

1.1Tomcat 应用在哪里,作用是什么

  • tomcat 应用于 web 开发中,面向客户端和服务端充当中间者角色,相当于一个有着平台兼容性的收(请求)发(资源)器;

Tomcat 系统学习 - 图2

1.2.Tomcat 服务器与容器属性

1.2.1 容器与服务器的联系与区别

  • 容器与服务器的关系
    • 容器是位于应用程序/组件和服务器平台之间的接口集合,使得应用程序/组件可以方便部署到服务器上运行;

Tomcat 系统学习 - 图3

  • 服务器
    • 服务器的一般概念:服务器是提高计算服务的设备,应具备承担和保障服务的能力;
    • 应用服务器与 web 服务器
      • 应用服务器:通过各种协议把业务逻辑暴露给客户端,提供应用程序所实现的服务;
      • web 服务器:向浏览器等 web 客户端提供文档浏览、数据文件下载等服务;
  • 容器

    • 容器的一般概念:部署运行应用程序环境,就应用程序而言是位于应用程序和平台间的接口集合
    • 功能
      • 管理组件的生命周期;
      • 向应用程序组件分派请求;
      • 提供接口获取与当前请求信息相关的上下文数据;

        1.2.2 Tomcat 的服务器与容器属性

  • Tomcat 是Java Servlet,JavaServer Pages,Java Expression Language 和 Java WebSocket(Java EE)技术的开源实现,具有多重属性

    • web 服务器:通过 HTTP 提供 HTML 页面等静态内容的请求访问;
    • servlet 容器:实现了servlet 规范,可以运行 Servlet 程序;
    • 应用服务器:可通过 servlet 容器,调用 servlet 处理动态请求;
  • tomcat 与其它服务器的关系

Tomcat 系统学习 - 图4

  • tomcat servlet 与其它容器的关系

Tomcat 系统学习 - 图5

  • Tomcat 与其它服务器的组合
    • Nginx + Tomcat
      • 先是通过 Nginx 反向代理服务器接收请求,匹配分离动态/静态请求(动静分离),如果是静态请求,则转发到另外的 Nginx WEB 服务器上,返回静态内容;如果是动态请求,则转发到后面的 Tomcat 应用服务器,处理动态请求的业务逻辑;

Tomcat 系统学习 - 图6

1.3 Tomcat 工具使用

1.3.1 基础配置

  • 安装及配置 详见
  • 下载:http://tomcat.apache.org/
  • 安装/卸载:解压压缩包; 删除目录;
  • 启动
  • (正常)关闭:bin/shutdown.bat 或者 Ctrl+C;
  • 配置
    • 部署项目的方式
      • 直接将项目(打包成 war 包)放到 webapps 目录下,war 包会自动解压缩;
      • [不安全]配置 conf/server.xml 文件:在 host 标签中
        • docBase:项目存放的路径; path:虚拟目录;
      • 在 conf\Catalina\localhost 创建任意名称的 xml 文件,并编写
        • 注意:此时对应的虚拟目录为 xml 文件的名称;
  • Java 动态项目目录结构

    • 项目名称
      • WEB-INF
        • web.xml:该项目的核心配置文件;
        • classes 目录:放置字节码文件;
        • lib 目录:放置项目依赖的 jar 包;

          1.3.2 Tomcat 与 IDEA 集成

  • IDEA 插件下载地址

    2.Tomcat 静态架构

    2.1文件目录结构

  • bin:该目录下存放的是二进制可执行文件,安装版会有两个exe文件,解压版会有 startup.bat 和shutdown.bat 文件,startup.bat 用来启动 Tomcat,但需先配置 JAVA_HOME 环境变量;

  • conf
    • server.xml:配置整个服务器信息,如修改端口号,添加虚拟主机等;
    • tomcatusers.xml:存储 tomcat 用户的文件,保存着 tomcat 的用户名、密码及角色信息;
    • web.xml:部署描述符文件,该文件中注册了很多 MIME 类型,客户端浏览器通过 MIME类型处理响应结果,如显示 html(mime=text/html) 或弹出下载窗口(mime=exe);
    • context.xml:对所有应用的统一配置,通常不去配置;
  • lib:Tomcat的类库,里面是一大堆 jar 文件,建议只把 Tomcat 需要的 Jar 包放到这个目录下;
  • logs:日志文件,记录 Tomcat 启动和关闭的信息,启动异常也会记录在日志文件中;
  • temp:存放 Tomcat 的临时文件,可在停止 Tomcat 后删除;
  • webapps:存放 web 项目,每个文件夹对应一个应用项目;
    • 静态网站:1)在 webapps下创建一个 xx 目录;2)在 webapps\xx\下创建 index.html;
    • 动态网站:1)在 webapps下创建一个 xx 目录;2)在 webapps\xx\下创建 WEB-INF 目录;3)在 webapps\xx\WEB-INF\ 下创建 web.xml;4)在webapps\hello1\下创建 index.html;
    • 注意
      • 动态网站相比静态网站,在项目名目录下多了一个 WEB-INF 子文件,其里边存放着当前项目的 web.xml;
      • webapps 存放的是内部应用,若要调用 webapps 以外的外部应用,需在 tomcat 中配置: conf/server.xml 或 conf/catalana/localhost/itcast_hello.xml 的 path、docBase;
  • work:webapps 中的项目每次运行都会生成的文件;
  • LICENSE:许可证;
  • NOTICE:说明文件;

    2.2 两个重要的配置文件

    2.2.1 server.xml

  • server.xml 的每一个元素都对应于 tomcat 中的一个组件,主要用于对各个组件和端口进行配置;

  • 结构图

Tomcat 系统学习 - 图7

  • 实例

    1. <?xml version='1.0' encoding='utf-8'?>
    2. <!--Server:最顶层,代表整个Tomcat容器 port:指定负责监听的关闭端口 主要用于tomcat服务关闭时回调给应用程序的监听 -->
    3. <Server port="8005" shutdown="SHUTDOWN">
    4. <!-- Listener:监听器 可以在特定事件发生时执行特定的操作;被监听的事件通常是Tomcat的启动和停止-->
    5. <!-- VersionLoggerListener:当Tomcat启动时,该监听器记录TomcatJava和操作系统的信息。该监听器必须是配置的第一个监听器 -->
    6. <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    7. <!-- JasperListener:在Web应用启动之前初始化JasperJasperJSP引擎,把JVM不认识的JSP文件解析成java文件,
    8. 然后编译成class文件供JVM使用。 -->
    9. <Listener className="org.apache.catalina.core.JasperListener" />
    10. <!-- JreMemoryLeakPreventionListener:类加载器导致的内存泄露有关 -->
    11. <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    12. <!-- GlobalResourcesLifecycleListener:初始化< GlobalNamingResources>标签中定义的全局JNDI资源;
    13. 如果没有该监听器,任何全局资源都不能使用 -->
    14. <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    15. <!-- ThreadLocalLeakPreventionListener:当Web应用因thread-local导致的内存泄露而要停止时,该监听器会触发线程池中线程的更新。当线程执行完任务被收回线程池时,
    16. 活跃线程会一个一个的更新。只有当Web应用(即Context元素)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效。 -->
    17. <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    18. <!-- 服务器的全局JNDI资源 -->
    19. <GlobalNamingResources>
    20. <Resource name="UserDatabase" auth="Container"
    21. type="org.apache.catalina.UserDatabase"
    22. description="User database that can be updated and saved"
    23. factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    24. pathname="conf/tomcat-users.xml" />
    25. </GlobalNamingResources>
    26. <!-- service:服务组件,对外提供服务,一个service代表一个服务 -->
    27. <Service name="Catalina">
    28. <!--Connector 接收连接请求,创建RequestResponse对象用于和请求端交换数据;
    29. 然后分配线程让Engine来处理这个请求,并把产生的RequestResponse对象传给Engine
    30. 可以配置多个Connector 通过创建不同的Connector指定不同的port和协议访问Tomcat服务
    31. 常见的属性有:
    32. protocol:协议,有HTTPAJP等各种协议等
    33. connectionTimeout:链接超时时间
    34. redirectPort:指定服务器正在处理http请求时,收到了一个SSL传输请求后,重定向的端口号
    35. -->
    36. <Connector
    37. keepAliveTimeout="10000"
    38. namePrefix="catalina-exec-"
    39. maxThreads="1024"
    40. minSpareThreads="4"
    41. maxIdleTime="6000"
    42. connectionTimeout="1000"
    43. compression="on"
    44. compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
    45. enableLookups="false"
    46. maxKeepAliveRequests="1"
    47. maxConnections="1024"
    48. acceptCount="2000"
    49. port="8008"
    50. protocol="org.apache.coyote.http11.Http11NioProtocol"
    51. redirectPort="8444"
    52. />
    53. <!--Engine:请求处理组件,在service组件中有且只有一个,Service组件中的请求处理组件。
    54. Engine组件从一个或多个Connector中接收请求并处理,并将完成的响应返回给Connector,最终传递给客户端
    55. 他有以下属性:
    56. nameEngine的逻辑名称,在日志和错误消息中会用到
    57. defaultHost:指定默认主机,如果没有分配哪个Host来执行用户请求,由这个值所指定的主机来处理,
    58. 这个值必须和<Host>元素中的其中一个的name值相同
    59. -->
    60. <Engine name="Catalina" defaultHost="localhost">
    61. <!--
    62. Host:可以有一或多个Host组件,每个Host组件代表Engine中的一个虚拟主机。
    63. Host的作用是可以运行多个Web应用(一个Context代表一个Web应用),并负责安装、展开、启动和结束每个Web应用,
    64. 它的属性有:
    65. name:指定虚拟主机的主机名,一般情况下,主机名需要是在DNS服务器中注册的网络名,但是Engine指定的defaultHost不需要
    66. unpackWARs:是否将代表Web应用的WAR文件解压;如果为true,通过解压后的文件结构运行该Web应用,如果为false,直接使用WAR文件运行Web应用
    67. appBase:应用程序基本目录,即存放应用程序的目录,可以是计算机中的绝对目录,也可以是相对CATALINA_HOME的相对目录,不填则默认为tomcatwebapps目录
    68. alias:指定主机别名
    69. autoDeploy:是否自动发布;用于检测appBase下的文件,如果有新增或者修改,为true则会自动重新启动项目
    70. -->
    71. <Host
    72. name="localhost"
    73. appBase=""
    74. unpackWARs="true"
    75. autoDeploy="false">
    76. <!--
    77. Context:指当前Host上运行的一个Web应用 ,每个Host中可以定义任意多的Context元素。
    78. 它有以下属性:
    79. path:访问该Web应用的上下文路径
    80. docBase:指定了该Web应用使用的WAR包路径,或应用目录。
    81. reloadabletomcat是否在运行时监控在WEB-INF/classesWEB-INF/lib目录下class文件的改动
    82. -->
    83. <Context
    84. path=""
    85. docBase="/Users/jaybril-pro/Documents/workspace/neno/BlackEye-SCAN/web"
    86. reloadable="true" />
    87. </Host>
    88. </Engine>
    89. </Service>
    90. </Server>

    元素的属性表 详见

    • 属性:shutdown-关闭 server; port-server接收 shutdown 指令的端口号(-1表示端口禁用);
    • 功能:1)提供访问到 service 集合的端口;2)维护所包含 service 的生命周期;
  • :一个 server 可有多个 service,将 connector 和 Engine 包在一起以对外提供服务;
  • :一个 service 可有多个 connector
    • 属性:port-请求端口,protocol-请求协议,redirectPort-当协议不一致时重定向端口,connectionTimeout-连接超时时间,minProcessors/maxProcessors-服务器启动时创建的处理请求的最少/最多线程数,enableLookups- 为 true 表示调用 request.getRemoteHost()进行 DNS 查询来得到远程客户端的实际主机名否则返回其 ip 地址,acceptCount-处理队列中允许放的请求数(超过这个数的请求将不予处理);
    • 功能:1)表明客户端可通过 xx 端口使用 xx 协议访问 tomcat;2)接收连接请求,创建 Request 和 Response 对象;3)分配线程让 Engine 处理请求,且把生成的 Request 和 Response 对象传给 Engine;
  • :一个service 只有一个 Engine
    • 属性:name-server 唯一,defaultHost-找不到指定 host 时使用默认 host(要求 defaultHost 的值必须与 Engine 中的一个 Host 组件【默认主机】的 name 值匹配);
    • 功能:从一个或多个 connector 中接收请求并处理,并将完成的响应返回给 connector;
  • : 一个 Engine 可有多个 Host
    • 属性:name-主机名(对应注册在 DNS 上的网络名),unpackWARs-是否将代表 Web 应用的WAR 文件解压,appBase-存放应用程序的目录;
    • 功能:运行多个 Web 应用,并负责安装、展开、启动和结束每个 Web 应用;
  • :一个 host 可有多个 context

    • 属性:docBase-应用程序的路径或 WAR 文件存放的路径,path-此 web 应用程序的 url 的前缀,reloadable-为 true 时 tomcat 会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化实现无需重启而自动装载新的应用程序;
    • 功能:一个 context 表示一个 web 应用程序;

      2.2.2 web.xml

  • 配置参数说明

  • 启动一个 web 项目时 web.xml 加载顺序
    • web 容器从配置文件 web.xml 读取两个结点;
    • 容器创建一个ServletContext(servlet上下文),被 web 项目的所有部分共享;
    • 容器将转换为键值对,并交给 servletContext;
    • 容器创建中的类实例,创建监听器;
  • conf/web.xml 和 WEB-INF/web.xml 的关系
    • tomcat 部署应用程序时,先读取通用的 conf/web.xml,然后再读取 web应用程序中的 WEB-INF/web.xml;
    • conf/web.xml 中的设定会应用于所有 web 应用程序,而某些 web 应用程序的 WEB-INF/web.xml 中的设定只应用于该应用程序本身;
    • 所有 JavaWeb 项目中 web.xml 都继承自服务器下的 web.xml;
  • WEB-INF/web.xml 的功能

    • 配置 web 应用名称,图标,描述,ServletContext 上下文参数,Fliter 配置,Listener 配置,Servlet 配置,会话超时配置,MIME 类型配置等;

      2.3 Tomcat 启动时加载资源的三个主要阶段

  • 第一阶段:JVM 相关资源

(1) $JAVA_HOME/jre/lib/ext/.jar
(2) 系统 classpath 环境变量中的
.jar和*.class

  • 第二阶段:Tomcat 自身相关资源

(1) $CATALINA_HOME/common/classes/.class
(2) $CATALINA_HOME/commons/endorsed/
.jar
(3) $CATALINA_HOME/commons/i18n/.jar
(4) $CATALINA_HOME/common/lib/
.jar
(5) $CATALINA_HOME/server/classes/.class
(6) $CATALINA_HOME/server/lib/
.jar
(7) $CATALINA_BASE/shared/classes/.class
(8)$CATALINA_BASE/shared/lib/
.jar

  • 第三阶段:Web 应用相关资源

(1) 具体应用的 webapp 目录: /WEB-INF/classes/.class
(2) 具体应用的 webapp: /WEB-INF/lib/
.jar

2.4 Tomcat 重要组件

2.4.1 各组件之间的关系图

Tomcat 系统学习 - 图8Tomcat 系统学习 - 图9

  • 补充:service 容器中除了 connector 和 Engine 外,还包括 session、loging 等组件;
  • 注意:Executor 的线程池大小是为 Engine 组件设置,而不是为 Connector 设置的,Connector 的线程数量由Connector 组件的 acceptorThreadCount 属性来设置,若在配置文件中设置该组件,则必须设置在 Connector组件的前面,以便在 Connector 组件中使用 executor 属性来引用配置好的 Executor 组件。

    2.4.2 连接器 connector

  • connector 是 tomcat 的主干,其运行效率在一定程度上影响了 tomcat 的整体性能;

  • connector 主要功能:1)接收连接请求;2)创建 request 和 response 对象用于和请求端交换数据;3)分配线程给 engine 处理请求,并把 request 和 response 对象传递给 engine 引擎;4)将 engine 处理后的 response 返回给客户端;
  • 连接与请求的关系
    • 连接是 TCP 层面的(传输层),对应 socket;
    • 请求是 HTTP 层面的(应用层),必须依赖于 TCP 的连接实现;
    • 一个 TCP 连接中可能传输多个 HTTP 请求;
  • 两类 connector :HTTPConnector 和 AJPConnector;

Tomcat 系统学习 - 图10

  • Connector 包含的组件
    • Protocol:协议的抽象,对不同的通信协议进行封装,如 HTTP 协议和 AJP 协议;
    • Endpoint用于处理底层 Socket 的网络连接
      • 接收端的抽象,由于使用了不同的 I/O 模式,因此存在很多类型的 Endpoint,如 BIO 模式的JionPoint、NIO 模式的 NioEndPoint 和本地库 I/O 模式的 APREndpoint;
    • Acceptor:接收客户端连接的接收器组件;
    • Executor:处理客户端请求的线程池,既能使用 Service 的共享线程池,也可使用私有线程池;
    • Processor将 Endpoint 接收到的 Socket 封装成 Request
      • 组件是处理客户端请求的处理器,不同的协议和不同的 I/O 模式都有不同的处理方式,所以存在不同类型的 Processor;
    • Mapper:路由器,提供了对客户端请求 URL 的映射功能,即可以通过它将请求转发到对应的 Host 组件、Context 组件、Wrapper 组件以进行处理并响应客户端;
    • CoyoteAdapter将封装好的 Request 交给 Container 进行具体处理
      • 适配器,负责将 Connector 组件和 Engine 容器适配连接起来,把接收到的客户端请求报文解析生成的请求对象 Request 和响应对象 Response 传递到 Engine 容器来处理;
  • 组件之间的关系图

Tomcat 系统学习 - 图11Tomcat 系统学习 - 图12

  • 四个子容器的关系图及作用
    • Engine :引擎,用来管理多个站点, 一个 Service 最多只能有一个Engine;
    • Host :代表一个站点,也可以叫虚拟主机,通过配置 Host 就可以添加站点;
    • Context :代表一个应用程序,对应平时开发的一套程序或一个 WEB-INF 目录以及下面的 web.xml 文件;
    • Wrapper :每个 Wrapper 封装着一个servlet;

Tomcat 系统学习 - 图13

  • 一个 Host 里可有不同 Context,对应不同 contextPath,默认 Context 的 contextPath 为空格(“”) 或 斜杠(/);
  • 源码解析1 源码解析2

    2.4.4 Listener 详见

  • 监听器是一个实现特定接口的普通 java 程序,专门用于监听另一个 java 对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行;

  • 设计到的设计模式:监听者模式
  • JavaWeb 中的监听器是 Servlet 规范中定义的一种特殊类,它用于监听 web 应用程序中的 ServletContext, HttpSession 和 ServletRequest 域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。
  • JavaWeb 三大域对象:内置 map 集合 和 Attribute 的 get/set,实现数据共享
    • 生命周期是对象从创建到销毁;
    • ServletRequest
      • 作用域:只在当前请求有效,每一次请求都是一个新的 request 对象,如果在 web 组件之间需要共享同一个请求中的数据,只能使用请求转发;
    • HttpSession
      • 作用域:只在一次会话中有效,每一次会话都是一个新的 session 对象,如果一次会话中的多个请求之间需要共享数据,只能使用 session;
    • ServletContext(application)
      • 作用域:tomcat 从启动到关闭表示一个应用,在一个应用中只有一个 application 对象,作用于整个 web 应用,可以实现多次会话之间的数据共享;
    • 作用域共享数据的方式:setAttribute getAttribute removeAttribute
      • 注:在哪一个作用域中设置共享数据,只能从该作用域中取数据;
      • 在选择域对象的时候,能用范围小的绝不用范围大的;
  • 四组监听器
    • 第一组:用于监听 Servlet 三个域对象的创建与销毁
      • ServletRequestListner
      • HttpSessionListener
      • ServletContextListener
        • 创建:服务器启动针对每一个 web 应用创建 ServletContext;【contextInitialized】
        • 销毁:服务器关闭前先关闭代表每一个 web 应用的 ServletContext;【contextDestroyed】
    • 第二组:用于监听 Servlet 三个域对象的属性变化(设置、删除、修改)
      • ServletRequestAttributeListener
      • HttpSessionAttributeListener
      • ServletContextAttributeListener
    • 第三组:用于通知被绑定到 Session 对象的属性
      • HttpSessionBindingListener
    • 第四组:用于监听 Session 的钝化与活化
      • HttpSessionActivationListener
  • Tomcat 系统学习 - 图14
  • 多个监听器的执行顺序:按照监听器在 web.xml 中注册顺序执行;
  • 自定义监听器 案例

    • 创建 Java 类,实现上述八个监听器接口之一, 重写该接口提供的所有方法;
    • 在 web.xm l文件中配置 Listener:
       <listener>
         <listener-class>自定义Listener的完整路径</listener-class>
       </listener>
      

      2.4.5 Filter

  • 用于 Web 容器对请求和响应做统一处理,例如统一改变 HTTP 请求内容和响应内容,可以作用在某个 Servlet 或一组 Servlet;

  • 本质:JSP、Filter 都是 Servlet 的进化版,JSP 负责视图展示,Filter 负责过滤;
  • 作用:拦截请求与响应;

Tomcat 系统学习 - 图15

  • 应用场景:权限控制、敏感词汇过滤、压缩加密响应信息等;
    • 作用在请求资源执行之前,进行权限检查,检查用户是否有权限,
    • 作用在请求资源执行之前,对 Request 和 Response 对象进行预处理,从而实现一些 web 应用的全局性设置,比如解决中文乱码问题;
    • 作用在最终响应输出之前,对输出 Response 对象中的数据进行处理,例如将输出的数据进行压缩;
  • 作用(以 httpServlet 为例)
    • 从 HTTP 协议中获取信息(这是因为 filterchain.doFilter 传入的参数为解析的 request 和 response)
      • 获取请求头部,如 getHeader、getHeaders;
      • 获取 cookie,如 getCookies;
      • 获取 session,如 getSession,session ;
    • 获取请求路径,如;getContextPath、getServletPath;
      • 之所以能够获取 contextPath,是因为 filter 被部署在 servletContext 中;
      • 能够获取 servletPath 是因为 filter 在部署的时候需标明作用的 servlet 的路径;
  • web.xml 配置以及在分发机制中的使用
  • Tomcat 系统学习 - 图16 image.png
  • 初始化时机
    • Filter 其实是加了 load-on-startup 的 servlet,即 Tomcat 启动时 Filter 就已经加载创建并完成初始化,所以一个应用每种过滤器只有一个
  • 多个 Filter 拦截顺序问题(过滤链)
    • chain.doFilter(req, resp); //如果没有调用,则拦截
      • 注意区分 filter.dofilter 方法和 filter.dofilter 方法
    • 执行顺序取决于 在 web.xml 中的位置,越靠前越优先;
    • 涉及到的设计模式:责任链模式
  • FilterConfig 对象的作用:1)获取 FilterConfig 名称; 2)获取 FilterConfig 初始化参数; 3)获取ServletContext 对象;
  • Filter 映射规则配置:1)精确匹配,以‘/’开头; 2)匹配所有 /;扩展名匹配 .jsp;
  • 单独拦截某个 Servlet
    • 方法一:配置 值 = 值;
    • 方法二:配置 值;
  • Filter+动态代理解决全站编码问题
  • 创建一个 Filter 类,实现 Filter 接口,并重写接口方法;
    • web.xml 配置 Filter
      // 注册   
      <filter> // 对应 filterConfig 对象
           <description>:用于描述标签,非必须
        <init-param>:为过滤器的初始化提供参数,非必须
        <filter-name>userFilter</filter-name>
        <filter-class>com.tuobida.filter.UserFilter</filter-class>//指定该过滤器使用的web工程中的哪一个filter类,包含包名与类名
      </filter>
      // 映射
      <filter-mapping>
        <filter-name>userFilter</filter-name>//必须同<filter>标签下的<filter-name>的值一致
        <url-pattern>/*</url-pattern>//设置过滤器要拦截过滤的请求路径
        <servlet-name>如果只要拦截过滤访问某个Servlet,就可以使用该标签来替代<url-pattern>
        <dispatcher>设置拦截过滤客户端请求的方式,有REQUEST,INCLUDE,FORWARD,ERROR四种(请注意均为大写),
        ,非必须则默认为REQUEST,使用多个<dispatcher>标签来设置多种请求方式;
      </filter-mapping>
      

2.4.6 Servlet

2.4.6.1 背景

  • Servlet 是 JavaEE 规范的一种,主要是为了扩展 Java 作为 Web 服务的功能,统一接口,由其他内部厂商(tomcat、jetty 等)内部实现 web 的功能;
    • Servlet、Listenner 和 Filter 都是由 Tomcat 在解析 web.xml 时通过反射创建的;
    • Servlet 是单实例,其中的 service() 方法是多线程的;
  • servlet 工作模式

Tomcat 系统学习 - 图18

  • 关于 serclet 的基本类图和调用关系

Tomcat 系统学习 - 图19
Tomcat 系统学习 - 图20

2.4.6.2 Servlet 传入的三个参数

  • ServletConfig

image.png

  • Request 和 Response

    • 本质是对 HTTP 请求的类包装;
      • HTTP 请求到了 Tomcat 后,Tomcat 通过字符串解析,把各个请求头(Header),请求地址(URL),请求参数(QueryString)都封装进了 Request 对象中;
      • Tomcat 传给 Servlet 时 response 为空对象,Servlet 逻辑处理(service)后得到结果,最终通过response.write() 方法,将结果写入 response 内部的缓冲区,Tomcat 从缓冲区拿到 response 并遍历里面的信息,组装成 HTTP 响应发给客户端;

        2.4.6.3 如何配置 Servlet

  • 在 web.xml 中对 servlet 进行配置

Tomcat 系统学习 - 图22

  • 利用注解进行配置: 在 servlet 类的上面写入注解 @WebServlet(“/hello”);

    2.4.6.4 如何实现一个 Servlet

  • HttpServlet,继承关系 HttpServlet -> GenericServlet -> Servlet,主要实现了 Service 功能,在继承 HttpServlet 自定义 Servlet 时,不能修改 service,而应重写 doGet() 、doPost() 等;

Tomcat 系统学习 - 图23

  • 涉及到的设计模式:模板模式

Tomcat 系统学习 - 图24

2.4.6.5 Servlet 映射规则

Tomcat 系统学习 - 图25

  • 分配结果
    • 对于静态资源,Tomcat 最后会交由一个叫做 DefaultServlet 的类来处理;
    • 对于 Servlet ,Tomcat 最后会交由一个叫做 InvokerServlet 的类来处理;
    • 对于JSP,Tomcat 最后会交由一个叫做 JspServlet 的类来处理;
  • web.xml 映射规范
    • 以 ‘/‘ 字符开始、以 ‘/*’ 后缀结尾的字符串使用路径匹配;
    • 以 ‘*.’ 为前缀的字符串使用扩展名匹配;
    • 空字符串(””)是一个特殊的 URL 模式,其精确映射到应用的上下文根,即 http://host:port// 请求形式,在这种情况下,路径信息是 ‘/‘ 且 servlet 路径和上下文路径是空字符串(””);
    • 只包含 ‘/‘ 的字符串表示应用的默认 Servlet,在这种情况下,servlet 路径是请求 URL 减去上下文路径且路径信息是 null;
  • 使用 URL 路径匹配 web 应用程序的顺序
    • 精确匹配,查找一个与请求路径完全匹配的 Servlet;
    • 前缀路径匹配,递归的尝试匹配最长路径前缀的 Servlet,通过使用 “/“ 作为路径分隔符,在路径树上一次一个目录的匹配,选择路径最长的;
    • 扩展名匹配,如果 URL 最后一部分包含扩展名,如 .jsp,则尝试匹配处理此扩展名请求的 Servlet;
    • 如果前三个规则没有匹配成功,那么容器要为请求提供一个默认 Servlet;
    • 注意:
      • 只使用第一个匹配的 Servlet,后续不再尝试;
      • 容器在匹配时区分大小写;
  • 实现请求映射的一般方法:首先构建一个路由表,然后按照规范进行匹配,最后返回匹配结果;
    • Mapper:存储请求路由表并执行匹配;
    • MapperListener:负责监听所有的 Host、Context、Wrapper 构建路由表;
    • MappingData:请求映射结果;
  • 源码分析1 源码分析2

    2.4.6.6 发生在 Servlet 之间的转发与重定向

  • 转发和重定向都能让浏览器获得另外一个 URL 所指向的资源,但两者的内部运行机制区别较大;

Tomcat 系统学习 - 图26

  • 转发
    • 案例:request.getRequestDispatcher (“demo.jsp”). forward(request, response);//转发到demo.jsp
    • 获得转发对象(RequestDispatcher) 的两种方式:
      • 通过 HttpServletRequest 的 getRequestDispatcher() 方法;
      • 通过 ServletContext 的 getRequestDispatcher() 方法;
      • 补充:这说明 Dispatcher 也在 ServletContext 容器中,且在分配请求给 Servlet 的时候,Servlet 会保留对该 Dispatcher 的引用;
    • 特点:转发是由 tomcat 内部完成的,不会影响客户端的请求操作,客户端也无法获得转发过程;
  • 重定向
    • 案例:response.sendRedirect(“demo.jsp”); //重定向到demo.jsp
    • 特点:由 response 将重定向的地址发给客户端,客户端会对返回的新地址再次发出请求并等待响应;
  • 转发(forword())和重定向(sendRedirect())的主要区别

    • 跨域性
      • sendRedirect() 方法可作用于同一主机的不同 web 应用程序甚至其他服务器,而 forward() 方法只能将请求转发给同一 web 应用的组件;
    • 跳转 jsp
      • sendRedirect() 方法不能转发到“/WEB-INF/”路径下的 jsp 页面资源,而 forword() 可以,如 request.getRequestDispatcher(“/WEB-INF/jsp/login.jsp”).forward(request, response);
    • 客户端操作
      • forword() 时浏览器 URL 的地址栏不变,而sendRedirect() 对应的浏览器 URL 的地址栏改变;

        2.4.7 Realm

  • Realm 是 Tomcat 中为 web 应用程序提供访问认证和角色管理的机制,若配置了 Realm,则不需要在程序中写web 应用登陆验证代码以及管理用户角色,甚至不需要手写登陆界面 ;

  • 如何自定义 realm

    3.Tomcat 动态运行

    3.1 运行一次请求的过程

    Tomcat 系统学习 - 图27

  • 用户在浏览器输出网站:http://www.xxx.com/customer/index.html

  • 浏览器解析出域名 www.xxx.com 并且去请求 DNS 服务器,通过 DNS 获取相应的域名对应的 IP 地址和端口,例如(123.1.1.1:8099);
  • 通过 IP 地址找到 IP 对应的服务器后,要求建立 TCP 连接;
  • 通讯双方连接之后,请求被发送到服务器端口 8099;
  • 根据请求的协议,将请求传给 server.xml 中端口号 port 为 8099 的 Connectort;
  • 该 Connector 把请求分配到对应 service 下的 Engine 组件,由 Engine 处理请求,Cinnector 等待响应;
  • Engine 收到请求之后,根据请求路径匹配到相应的 host,并将请求交给 host 处理;
  • host 匹配相对路径 /customer/index.html,找到相应的 context;
  • 匹配到相应 context 后,根据路径访问相应的 servlet;【这部分需要通过 web.xml 的 context 结点吗?】
  • 根据请求构造 HttpServletRequest 和 HttpServletResponse 对象,并调用 Servlet 的 doGet 或 doPost 方法;
  • servlet 中处理逻辑之后,把 HttpServletResponse 对象返回给 Host;
  • host 把 HttpServletResponse 逐级传递到 Engine、Connector;
  • Connector 把响应结果返回到客户端的浏览器,同时告知浏览器展示的文件格式是什么;
  • 浏览器把结果渲染呈现;

    3.2 相关传输协议

    3.2.1 http/https

  • 浏览器请求时的请求头信息

    GET / HTTP/1.1 
    Host: www.ramki.com 
    Proxy-Connection: keep-alive 
    User-Agent: Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11 
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9
    Accept-Encoding: gzip,deflate,sdch 
    Accept-Language: en-US,en;q=0.8
    
  • 背景知识

    • 超文本:
      • 由信息结点和表示信息结点间相关性的链构成的一个具有一定逻辑结构和语义的网络;详见
    • http 和 https 详见
      • 关联:两者为超文本传输协议,传输两端为:本地 Web 浏览器 和 WWW 服务器;
      • 区别:
        • http 明文传输,https = http + SSL or TLS -加密协议(加密传输、身份认证);

Tomcat 系统学习 - 图28

     - http 和 https 使用的连接方式不同,连接端口不同,前者是 80,后者是 443;
  • http 请求格式与响应格式
    • TCP/IP、http、Socket 的关系
  • TPC/IP 是传输层协议,主要解决数据如何在网络中传输,而 HTTP 是应用层协议,主要解决如何包装数据;
  • Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,是一组接口,封装了复杂的 TCP/IP 协议;
    • 延伸 - WebSocket
  • 产生背景 - http 用于及时通讯的局限
    • 通过轮询在特定的时间间隔,由浏览器向服务器发送 Request 请求,然后将最新数据返回给浏览器;
    • 产生过多不必要请求,浪费流量和服务器资源,每一次请求应答,都浪费一定流量在相同头部信息上;
  • WebSocket 与 HTTP 的关系
    • 同:1)建立在 TCP 之上,可靠传输; 2)应用层协议
    • 异:1)HTTP 是单向通信(浏览器->服务端);2)WebSocket 全双工通信,且需通过握手建立连接;
    • 联系:WebSocket 握手连接通过 HTTP 请求完成,再单独建立一条 TCP 的通信通道进行数据传输;
  • WebSocket 与 Socket 的关系
    • 异:Socket 是传输控制层协议,WebSocket 是应用层协议;
    • 联系:WebSocket 类似 Socket 的 TCP 长连接的通讯模式,一旦 WebSocket 连接建立后,后续数据都以帧序列的形式传输;
    • Tomcat 系统学习 - 图29

      3.2.2 ajp

  • AJP 是 Apache 与其他服务器之间的通信协议,通常在集群环境中,例如前端 web 服务器和后端应用服务器或servlet 容器,使用 AJP 会比 HTTP 有更好的性能;

    3.3 Tomcat 运行原理

    3.3.1 Tomcat 的启动过程

  • tomcat 假如有 main 函数,其处理流程应该为:

Tomcat 系统学习 - 图30

  • 请求处理流程线Tomcat 系统学习 - 图31
  • 启动流程的时序图Tomcat 系统学习 - 图32
  • 参考 tomcat8 源码分析 | 组件及启动过程

    3.3.2 connector 的并发处理

  • Connector 处理请求的流程

    • 在 accept 队列中接收连接(当客户端向服务器发送请求时,如果客户端与 OS 完成三次握手建立了连接,则 OS 将该连接放入 accept 队列);
    • 在连接中获取请求的数据,生成 request 和 response;
    • 调用 servlet 容器处理请求,返回 response;
  • JIoEndpoint(BIO 实现的 Connector)
    • Acceptor 接收 socket 后,从 Worker 线程池中找出空闲的线程处理 socket,如果 worker 线程池没有空闲线程,则 Acceptor 将阻塞;
      • Worker 为 Tomcat 自带的线程池,可通过配置其他线程池;

Xml代码 Tomcat 系统学习 - 图33

  1. <Executor name=”tomcatThreadPool” namePrefix=”catalina-exec-“
  2. maxThreads=”150” minSpareThreads=”4”/>
  • NIoEndpoint(NIO 实现的 Connector)
    • Acceptor 接收 socket 后,通过队列将请求发送给 Poller,当 Poller 从队列中取出 socket 后,先注册到Selector 中,然后通过遍历 Selector,找出其中可读的 socket,再使用 Worker 中的线程处理相应请求;
      • 读取 socket 并交给 Worker 中的线程,为非阻塞模式;
      • Acceptor 接收 socket,以及使用 worker 线程处理请求,均为阻塞方式;
    • Tomcat 系统学习 - 图34
  • 并发处理过程的源码图示

    3.3.3 lifeCircle 和 valueBase

    3.3.3.1 lifeCircle

    org.apache.catalina.Lifecycle 是一个接口,org.apache.catalina.util.LifecycleBase 实现了 Lifecycle 接口,而 Server / Service / Engine / Host / Context / Wrapper 等组件都继承了 LifecycleBase,也就是说这些组件在发生生命周期事件的时候都可以被监听器监控

    Tomcat 系统学习 - 图35

    在tomcat中容器相关的好多组建都实现了Lifecycle接口,当tomcat启动时,其依赖的下层组件会全部进行初始化。 并且可以对每个组件生命周期中的事件添加监听器

Tomcat 系统学习 - 图36

3.3.3.2 valueBase

3.3.4 Tomcat 的类加载机制

https://developer.aliyun.com/ask/62429?spm=a2c6h.13159736
https://www.jianshu.com/p/51b2c50c58eb
加载类和资源的顺序为:
1、/Web-INF/classes
2、/Web-INF/lib/.jar
3、Bootstrap
4、System
5、$CATALINA_HOME/common/classes
6、$CATALINA_HOME/common/endores/
.jar
7、$CATALINA_HOME/common/lib/.jar
8、$CATALINA_HOME/shared/classes
9、$CATALINA_HOME/shared/lib/
.jar