Servlet容器:
我们以大家最为熟悉的Tomcat为例来介绍Servlet容器时如何管理Servlet的。
Tomcat容器分为4个等级,真正管理Servlet的容器是Context容器,一个Context容器对应一个Web工程。
Servlet容器的启动过程:
从添加一个web应用说起,当添加一个web应用时,将会创建一个StandardContext容器,并且给这个Context容器设置必要的参数,url和path分别代表这个应用在Tomcat中的访问路径和这个应用实际的物理路径。最后将这个Context容器加到父容器Host中。
接下来会调用Tomcat的start方法启动Tomcat。Tomcat的启动逻辑基于观察者模式设计的,所有的容器都会继承Lifecycle接口,它管理着容器的整个生命周期,所有容器的修改和状态的改变都会由它去通知已经注册的观察者(Listener)。
当Context容器初始化状态设为init时,添加到Context容器的Listener将会被调用。
Web应用的初始化工作:
应用的初始化主要是解析web.xml文件,这个文件描述了一个web应用的关键信息,也是一个Web应用的入口。web.xml文件中的各个配置项将会被解析成相应的属性保存在WebXml对象中。
最后,将Servlet包装成StandardWrapper并作为子容器添加到Context中,其他所有的web.xml属性都被解析到Context中。
所以说Context容器才是真正运行Servlet的Servlet容器。一个Web应用对应一个Context容器,容器的配置属性由应用的web.xml指定。
Serlvet体系结构:
与Serlvet主动关联的是三个类,分别是ServletConfig,ServletRequest和ServletResponse。这三个类都是通过容器传递给Servlet的,其中ServletConfig在Servlet初始化时就传给Servlet了,而后两个是在请求到达时调用Servlet传递过来的。
我们很清楚ServletRequest和ServletResponse在Serlvet运行时的意义,而ServletCofig中的方法都是为了获取这个Servlet的一些配置属性,而这些配置属性可能在Servlet运行时被用到。
而SerlvetContext呢?Servlet的运行模式是一个典型的“握手型的交互式”运行模式。就是说两个模块为了交换数据通常都会准备一个交易场景,这个场景一直跟随这个交易过程直到这个交易完成为止。这个交易场景的初始化是根据这次交易对象指定的参数来定制的,这些指定参数通常就是一个配置类。所以对号入座,交易场景就由ServletContext来描述,而定制的参数集合就由ServletConfig来描述。而ServletRequest和ServletResponse就是要交互的具体对象,它们通常都作为运输工具来传递交互结果。
Servlet工作原理:
用户从浏览器向服务器发起一个请求通常会包含如下信息:http://hostname:port/contextpath/servletpath,hostname与port用来与服务器建立TCP连接,后面的URL才用来选择在服务器中那个子容器服务用户的请求。服务器是如何根据这个URL来到达正确的Servlet容器中的呢?
这项映射工作由专门的一个类来完成,这个类就是org.apache.tomcat.util.http.mapper,这个类保存了Tomcat的Container容器中的所有子容器的信息,org.apache.catalina.connector.Request类在进入Container容器之前,Mapper将会根据这次请求的hostnane和contextpath将host和context容器设置到Request的mappingData属性中,所以当Request进入Container容器之前,对于它要访问哪个子容器就已经确定了。
MapperListener类作为一个监听者加到整个Container容器的每个子容器中,这样只要任何一个容器中发生变化,MapperListener都将会被通知到,相应的保存容器关系的MapperListener的mapper属性也会被修改。
当Servlet从Servlet容器中移除时,也就表明该Servlet的生命周期结束了,这时Servlet的destroy方法将被调用,做一些扫尾工作。