Servlet容器的启动过程

【http://book.51cto.com/art/201408/448854.htm】
 
Tomcat的启动逻辑是基于观察者模式设计的,所有的容器都会继承Lifecycle接口,它管理着容器的整个生命周期,所有容器的修改和状态的改变都会由它去通知已经注册的观察者(Listener)。Tomcat启动的时序图如图9-2表示。
 
 

图9-2描述了在Tomcat的启动过程中主要类之间的时序关系,下面我们将会重点关注添加examples应用所对应的StandardContext容器的启动过程。

当Context容器初始化状态设为init时,添加到Contex容器的Listener将会被调用。ContextConfig继承了LifecycleListener接口,它是在调用Tamcat.addWebapp时被加入到StandardContext容器中的。

ContextConfig类会负责整个Web应用的配置文件的解析工作。

ContextConfig的init方法将会主要完成以下工作。

        创建用于解析XML配置文件的contextDigester对象。

        读取默认的context.xml配置文件,如果存在则解析它。

        读取默认的Host配置文件,如果存在则解析它。

        读取默认的Context自身的配置文件,如果存在则解析它。

        设置Context的DocBase。

ContextConfig的init方法完成后,Context容器就会执行startInternal方法,这个方法的启动逻辑比较复杂,主要包括如下几部分。

        创建读取资源文件的对象。

        创建ClassLoader对象。

        设置应用的工作目录。

        启动相关的辅助类,如logger、realm、resources等。

        修改启动状态,通知感兴趣的观察者(Web 应用的配置)。

        子容器的初始化。

        获取ServletContext并设置必要的参数。

        初始化“load on startup”的Servlet。

WEB应用的初始化工作是在ContextConfig的configureStart方法中实现的,应用的初始化工作主要是解析web.xml文件,这个文件是一个WEB应用的入口。

        Tomcat首先会找globalWebXml,这个文件的搜索路径是engine的工作目录下的org/apache/catalina/startup/NO-DEFAULT_XML或conf/web.xml。

        接着会找hostWebXml,这个文件可能会在System.getProperty("catalina.base")/conf/${EngineName}/${HostName}/web.xml.default中。

        接着寻找应用的配置文件examples/WEB-INF/web.xml,web.xml文件中的各个配置项将会被解析成相应的属性保存在WebXml对象中。

        接下来会讲WebXml对象中的属性设置到context容器中,这里包括创建servlet对象,filter,listerner等,这些在WebXml的configureContext方法中。

 

上面的代码将servlet容器包装成context容器中的StandardWrapper。StandardWrapper是tomcat容器中的一部分,它具有容器的特征,而Servlet作为一个独立的web开发标准,不应该强制耦合在tomcat中。

        除了将Servlet包装成StandardWrapper并作为子容器添加到Context中外,其他所有的web.xml属性都被解析到Context中。

        前面完成了servlet的解析工作,并且被包装成了StandardWrapper添加到Context容器中,但是它仍然不能为我们工作,它还没有被实例化。

 
 
创建Servlet对象

如果Servlet的load-on-startup配置项大于0,那么在Context容器启动时就会被实例化。

        前面提到的在解析配置文件时会读取默认的globalWebXml,在conf下的web.xml文件中定义了一些默认的配置项,其中定义了两个Servlet,分别是org.apache.catalina.servlets.DefaultServlet和org.apache.jsper.servlet.JspServelt,它们的load-on-startup分别是1和3,也就是当tomcat启动时这两个servlet就会被启动。

        创建Servlet实例的方式是从Wrapper.loadServlet开始的,loadServlet方法要完成的就是获取servletClass,然后把它交给InstanceManager去创建一个基于servletClass.class的对象。如果这个Servlet配置了jsp-file,那么这个servletClass就是在conf/web.xml中定义的org.apache.jasper.servlet.JspServlet。

 
 
初始化Servlet对象

初始化Servlet在StandardWrapper的initServlet方法中,这个方法很简单,就是调用Servlet的init()方法,同时把包装了StandardWrapper对象的StandardWrapperFacade作为ServletConfig传给Servlet。

如果该Servlet关联的是一个JSP文件,那么前面初始化的就是JspServlet,接下来会模拟一次简单请求,请求调用这个JSP文件,以便编译这个JSP文件为类,并初始化这个类。

这样Servlet对象的初始化就完成了。

容器默认Servlet

每个servlet容器都有一个默认的servlet,一般都叫做default。

例如:tomcat中的 DefaultServlet 和 JspServlet (上面的部分)

原文地址:https://www.cnblogs.com/lsx1993/p/4632085.html