后面的文章中,咱们介绍了Tomcat的Engine和Host容器,咱们晓得一个Tomcat最多只有一个Engine容器,一个Engine容器能够蕴含多个Host容器,申请中的不同的Host对应不必的Host容器。本章咱们会介绍Tomcat的另外两个容器:Context容器和Wrapper容器。一个Host容器能够蕴含多个Context容器:同一个Host上面能够蕴含多个利用,每个利用对应一个Context容器。一个Context容器又能够蕴含多个Wrapper容器:每个Wrapper容器蕴含一个Servlet容器,意味着Tomcat容许一个利用有多个servlet实现。

Tomcat申请流程

咱们当初晓得Tomcat最重要的组件是连接器和四种类型的容器,上面的图展现了Tomcat的一次申请是如何在连接器和四种容器之间流转的,假如Http申请头为"GET /appB/servletB/some-url HTTP/1.1 Host: www.krishnan.com",当申请拜访到Tomcat容器时,会通过以下流转步骤:

  1. Tomcat的连接器监听SocketServer,发现这个申请,依照指定的协定和IO形式解决申请Socket音讯,解析Socket为对应的Request实体,并提供回写报文的Response实体。
  2. 连接器将Request/Response交给Engine容器,Engine容器存储了申请域名和Host容器之间的映射关系。比方"www.krishnan.com"域名对应于krishnan_webapps Host容器。
  3. Engine容器将申请交给对应的Host容器,Host容器开始解析申请中的门路,如果配置了门路和利用之间的关系,比方"/appB"对应于appB Context容器,Host容器会装置配置将申请交给对应利用的Context容器。
  4. Host容器解析门路并将利用交给Context容器之后,如果一个利用有多个Servlet,那么这个利用的Context容器也会蕴含多个Wrapper容器,咱们能够通过门路来将不同的申请映射到不同的Servlet容器。比方图中的"/servletB"对应servletB Wrapper容器,Context容器将申请交给Wrapper容器。
  5. Context容器依照门路将申请交给对应的Wrapper容器,Wrapper容器会加载对应的Servlet实现类,调用servlet实现类中的逻辑解决Request并将处理结果写入Response中。

Context容器

咱们在配置Tomcat应用程序的时候,总是须要配置一个web.xml文件,这个文件就是Context容器去解析的。tomcat默认的web.xml的配置如下所示,该配置中配置了两个WrapperContext,别离对应于两个Servlet配置。在web.xml中,咱们常常能够看到listener标签,次要是用于监听Context容器的申明周期事件。

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee                      https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"  version="5.0">  <request-character-encoding>UTF-8</request-character-encoding>  <response-character-encoding>UTF-8</response-character-encoding>    <servlet>        <servlet-name>default</servlet-name>        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>        <init-param>            <param-name>debug</param-name>            <param-value>0</param-value>        </init-param>        <init-param>            <param-name>listings</param-name>            <param-value>false</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet>        <servlet-name>jsp</servlet-name>        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>        <init-param>            <param-name>fork</param-name>            <param-value>false</param-value>        </init-param>        <init-param>            <param-name>xpoweredBy</param-name>            <param-value>false</param-value>        </init-param>        <load-on-startup>3</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>default</servlet-name>        <url-pattern>/*</url-pattern>    </servlet-mapping>    <!-- The mappings for the JSP servlet -->    <servlet-mapping>        <servlet-name>jsp</servlet-name>        <url-pattern>*.jsp</url-pattern>        <url-pattern>*.jspx</url-pattern>    </servlet-mapping>    <session-config>        <session-timeout>30</session-timeout>    </session-config>    <welcome-file-list>        <welcome-file>index.html</welcome-file>        <welcome-file>index.htm</welcome-file>        <welcome-file>index.jsp</welcome-file>    </welcome-file-list></web-app>

Wrapper容器

Wrapper容器是最小的容器,每个Wrapper都能够对应一个Servlet的实例。当申请转发到Wrapper容器之后,wrapper容器在调用Pipeline办法之后,会应用特定的类加载器去加载servlet类,对servlet进行实例化和初始化,而后将申请交给servelt的service办法进行解决。

咱们常见的Spring的DispatchServlet是线程平安的,所以Tomcat不须要保障Servlet的并发平安。对于非线程平安的servlet,则能够通过SingleThreadModel来保障多申请下servlet的失常运行。

Wrapper容器的次要作用就是载入servlet类并进行实例化,并调用service办法。当第一次申请某个servlet类的时候,Wrapper容器会载入servlet类。Tomcat提供了专门的类加载器用于加载servlet,对于这个类加载器我会在我的其它文章中介绍。

Wrapper容器的根本阀门StandardWrapperValve还会在调用servelt容器之前调用用户配置的过滤器链Filter。

我是御狐神,欢送大家关注我的微信公众号:wzm2zsd

本文最先公布至微信公众号,版权所有,禁止转载!