乐趣区

关于java:学习Tomcat四之Engine和Host容器

在后面的文章中,咱们介绍了 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.9
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 

Context 容器

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

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

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

退出移动版