Tomcat有两个核心组件:连接器和容器,其中连接器负责外部交流,容器负责内部处理。具体来说就 是,连接器处理Socket通信和应用层协议的解析,得到Servlet请求;而容器则负责处理Servlet请求。
Tomcat为什么要设计成多层架构?
Tomcat设计了多层容器是为了灵活性的考虑,灵活性具体体现在一个Tomcat实例(Server)可以有多个
Service,每个Service通过多个连接器监听不同的端口,而一个Service又可以支持多个虚拟主机。一个URL
网址可以用不同的主机名、不同的端口和不同的路径来访问特定的Servlet实例。
假如有用户访问一个URL,比如图中的http://user.shopping.com:8080/order/buy,Tomcat如何将这个URL定位到一个Servlet呢?
1、首先,根据协议和端口号选定Service和Engine。
2、然后,根据域名选定Host。
3、之后,根据URL路径找到Context组件。
4、最后,根据URL路径找到Wrapper(Servlet)。
连接器中的Adapter会调用容器的Service方法来执行Servlet,最先拿到请求的是Engine容器,Engine容器对请求做一些处理后,会把请求传给自己子容器Host继续处理,依次类推,最后这个请求会传给Wrapper容器,Wrapper会调用最终的Servlet来处理。
那么这个调用过程具体是怎么实现的呢?
答案是使用Pipeline-Valve管道。
Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处
理,每个处理者负责做自己相应的处理,处理完之后将再调用下一个处理者继续处理。
整个调用过程由连接器中的Adapter触发的,它会调用Engine的第一个Valve:
// Calling the container
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
Wrapper容器的最后一个Valve会创建一个Filter链,并调用doFilter()方法,最终会调到Servlet的service方
法。
业务的controller是从哪部分进去的?
Wrapper -> Filter -> DispatcherServlet -> Controller
Tomcat内的Context组件跟Servlet规范中的ServletContext接口有什么区别?跟Spring中的ApplicationContext又有什么关系?
1、Servlet规范中ServletContext表示web应用的上下文环境,而web应用对应tomcat的概念是Context,
所以从设计上,ServletContext自然会成为tomcat的Context具体实现的一个成员变量。
2、tomcat内部实现也是这样完成的,ServletContext对应tomcat实现是org.apache.catalina.core.Applica
tionContext,Context容器对应tomcat实现是org.apache.catalina.core.StandardContext。ApplicationCo
ntext是StandardContext的一个成员变量。
3、Spring的ApplicationContext之前已经介绍过,tomcat启动过程中ContextLoaderListener会监听到容
器初始化事件,它的contextInitialized方法中,Spring会初始化全局的Spring根容器ApplicationContext,
初始化完毕后,Spring将其存储到ServletContext中。
总而言之,Servlet规范中ServletContext是tomcat的Context实现的一个成员变量,而Spring的Applicatio
nContext是Servlet规范中ServletContext的一个属性。