在后面的文章中,咱们介绍了Tomcat的连接器Connector,连接器会监听指定的端口,并把承受到的音讯转为HttpServletRequest和HttpServletResponse,交个Servlet容器解决。Tomcat的Servlet容器分为四种:Engin容器/Host容器/Context容器/Wrapper容器,这四个容器之间是父子关系,Engine容器蕴含Host容器,Host容器蕴含Context,Context蕴含Wrapper容器。本文会介绍Tomcat容器中的Engin容器和Host容器,在下一篇文章中会介绍Context容器和Wrapper容器。

Container的作用

Tomcat中的Container用于解决连接器解决好的Request和Response。Tomcat中的四种容器都继承自Container接口,其中Engin容器全局只有一个,是Container对外提供解决Request和Response的入口。Host容器是Engin容器的子容器,一个Engin容器能够蕴含多个Host容器,每个Host容器代表一个虚拟主机(下文会具体介绍)。Engin容器在收到申请之后,会依照虚拟主机的配置将申请映射到对应的Host容器之上。

Container的构造

如下图所示,Tomcat中的四种Container都有雷同的构造,蕴含以下几局部要害组件:申请解决阀门链PipeLine、根底阀门BaseValve和日志组件等。

  1. PipeLine:用于流式加工解决申请中的信息,每个PipeLine中能够蕴含多个阀门Valve,每个Valve都有同样的办法invoke(Request request,Response response)
    <Engine name="Catalina" defaultHost="localhost">        <Host name="localhost"  appBase="webapps"            unpackWARs="true" autoDeploy="true">            <!-- 默认 Valve -->            <Valve className="org.apache.catalina.valves.AccessLogValve"                directory="logs"                prefix="localhost_access_log"                suffix=".txt"                <!-- maxDays="5" -->                pattern="%h %l %u %t &quot;%r&quot; %s %b" />            <!-- 自定义 valve -->            <Valve className="org.apache.catalina.valves.WswAccessValve"/>        </Host>    </Engine>
  1. BaseValve:根底阀门,和Piple中的阀门的接口雷同办法:invoke(Request request,Response response),然而作用和Piple中的阀门不同,次要用于将申请传递到下一个容器或者对应的Servlet组件。
  2. 日志记录器和生命周期治理等组其它组件,不具体介绍。

Engine容器

如上图所示,每个Tomcat仅仅有一个Engin容器,Tomcat中的连接器承受并解析音讯之后,会把音讯的转给Engin容器,用户能够给Engin容器的PipeLine增加各种自定义的Valve,Engin容器会将一一调用PipeLine中的Valve。Engin容器的BaseValve是StandardEngineValve,这个Valve会读取Request中的Host信息,而后把申请路由给对应的Host容器。

final class StandardEngineValve extends ValveBase {    public StandardEngineValve() {        super(true);    }    @Override    public final void invoke(Request request, Response response)        throws IOException, ServletException {        // Ignore some code here.        // Select the Host to be used for this Request        Host host = request.getHost();                // Ignore some code here.        // Ask this Host to process this request        host.getPipeline().getFirst().invoke(request, response);    }}

Host容器

Host容器是Engine容器的子容器,每个Host容器都是一个虚拟主机,对应于不同的域名。http协定从1.1开始,反对在申请头外面增加Host字段用来示意申请的域名。DNS域名解析的时候,能够将不同的域名解析到同一个ip或者主机。Engine容器的BaseValve会读取Request中的Host,而后调用对应Host容器的PipeLine去解决音讯。

什么是虚拟主机

如果咱们须要在一个tomcat外面同时反对三个域名:

  • http://www.ramki.com
  • http://www.krishnan.com
  • http://www.blog.ramki.com

咱们须要在server.xml文件外面的Engine标签上面增加多个Host标签,如下所示,其中name示意域名,appbase示意虚拟主机的目录。当咱们在浏览器输出http://www.ramki.com之后,相应域名将申请到tomcat。tomcat通过读取并搜寻server.xml,找到www.ramki.com对应的虚拟主机Host,而后就应用查找到的Host来解决申请。

<Host name="www.ramki.com" appbase="ramki_webapps" /><Host name="www.krishnan.com" appbase="krishnan_webapps" /> <Host name="www.blog.ramki.com" appbase="blog_webapps" /> 

在浏览器申请的时候,申请头信息如下,这儿咱们重点关注Host header。

GET /appA/servletA/some-url 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.9Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8 

Context容器

Tomcat中一个Host容器能够蕴含多个Context容器,通常状况下一个Context容器标识一个利用,对应于wabapp目录上面的一个工程,在我的下一篇博客中会具体介绍Context容器。

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

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