在上一篇文章中,我们介绍了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用于处理connector处理的Request和Response。Tomcat中的四个容器都继承自Container接口。其中,Engin容器全局只有一个,是Container提供的处理Request和Response的入口。Host容器是Engin容器的子容器。一个Engin容器可以包含多个Host容器,每个Host容器代表一个虚拟主机(下面详细介绍)。Engin容器收到请求后,会根据虚拟主机的配置,将请求映射到对应的Host容器中。Container的结构如下图所示。Tomcat中的四种Container结构相同,包括以下关键组件:请求处理阀链PipeLine、基础阀BaseValve、日志组件。PipeLine:用于流处理处理请求信息,每个PipeLine可以包含多个ValveValve,每个Valve都有相同的方法invoke(Requestrequest,Responseresponse)。pattern="%h%l%u%t"%r"%s%b"/>BaseValve:基础阀门,与Piple中valve的接口相同的方法:invoke(Requestrequest,Responseresponse),但功能与Piple中的valve不同,主要用于将请求传递给下一个容器或对应的Servlet组件。其他组件logger、生命周期管理等就不详细介绍了,Engine容器如上图所示,每个Tomcat只有一个Engin容器,Tomcat中的connector收到消息并解析后,会将消息传递给Engine容器。用户可以在Engin容器的PipeLine中添加各种自定义Valve,Engin容器会一一调用PipeLine中的Valve。Engine容器的BaseValve是StandardEngineValve。这个Valve会读取Request中的Host信息,然后将请求路由到对应的Host容器中。最终类StandardEngineValve扩展ValveBase{publicStandardEngineValve(){super(true);}@Overridepublicfinalvoidinvoke(Requestrequest,Responseresponse)throwsIOException,ServletException{//忽略这里的一些代码。//选择要用于此请求的主机Hosthost=request.getHost();//这里忽略一些代码。//让这个Host处理这个请求host.getPipeline().getFirst().invoke(request,response);}}Host容器Host容器是Engine容器的子容器,每个Host容器都是对应不同域名的虚拟主机。从1.1开始,http协议支持在请求头中增加一个Host字段来表示请求的域名。DNS域名解析时,不同的域名可以解析到同一个ip或host。Engine容器的BaseValve会读取Request中的Host,然后调用对应Host容器的PipeLine来处理消息。什么是虚拟主机如果我们需要在一个tomcat中同时支持三个域名:http://www.ramki.comhttp://www.krishnan.comhttp://www.blog.ramki.com我们需要在server.xml文件中的Engine标签下添加多个Host标签,如下图,其中name代表域名,appbase代表虚拟主机的目录。当我们在浏览器中输入http://www.ramki.com时,就会向tomcat请求对应的域名。Tomcat通过读取和查找server.xml找到www.ramki.com对应的虚拟主机Host,然后使用找到的Host来处理请求。浏览器请求时,请求头信息如下,这里重点关注Host头。GET/appA/servletA/some-urlHTTP/1.1主机:www.ramki.com代理连接:keep-alive用户代理:Mozilla/5.0(WindowsNT6.2)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11Accept:text/html,application/xhtml+xml,application/xml;q=0.9Accept-Encoding:gzip,deflate,sdchAccept-Language:en-US,en;q=0.8上下文容器TomcatA宿主容器可以包含多个上下文容器。通常,一个Context容器标识一个应用,对应于wabapp目录下的一个项目。我将在下一篇博客中详细介绍Context容器。我是狐神,欢迎大家关注我的微信公众号:wzm2zsd本文首发于微信公众号,版权所有,禁止转载!