《深入分析Java Web技术内幕》—第9章Servlet 工作原理解析

写在前面:这是一本讲的很细的书,我这里只是部分的节选,把一些源码给删去了,格式上自行做了点修改便于观看。
原文链接:https://www.ibm.com/developerworks/cn/java/j-lo-servlet/

9.1从Servlet说起
Servlet:
java web技术的核心基础;
Servlet容器种类:Jetty、Tomcat


Tomcat:

Servlet 容器的启动过程

Tomcat7 也开始支持嵌入式功能,增加了一个启动类 org.apache.catalina.startup.Tomcat。创建一个实例对象并调用 start 方法就可以很容易启动 Tomcat,我们还可以通过这个对象来增加和修改 Tomcat 的配置参数,如可以动态增加 Context、Servlet 等。下面我们就利用这个 Tomcat 类来管理新增的一个 Context 容器,我们就选择 Tomcat7 自带的 examples Web 工程,并看看它是如何加到这个 Context 容器中的。

Servlet 运行时的 Servlet 容器,添加一个 Web 应用时将会 创建一个 StandardContext 容器并且给这个 Context 容器设置必要的参数,url 和 path 分别代表这个应用在 Tomcat 中的访问路径和这个应用实际的物理路径。其中最重要的一个配置是 ContextConfig,这个类将会 负责整个 Web 应用配置的解析工作最后将这个 Context 容器加到父容器 Host 中。

接下去将会调用 Tomcat 的 start 方法启动 Tomcat。

添加 examples 应用所对应的 StandardContext 容器的启动过程:
当 Context 容器初始化状态设为 init 时,添加在 Context 容器的 Listener 将会被调用。ContextConfig 继承了 LifecycleListener 接口,它是在调用Tomcat.addWebapp时被加入到 StandardContext 容器中。

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 文件

1、首先Tomcat会找 globalWebXml ;这个文件的搜索路径是在 engine 的工作目录下寻找以下两个文件中的任一个 org/apache/catalin/startup/NO_DEFAULT_XML 或 conf/web.xml。
2、接着会找 hostWebXml ;这个文件可能会在 System.getProperty("catalina.base")/conf/${EngineName}/${HostName}/web.xml.default中
3、接着寻找应用的 配置文件 examples/WEB-INF/web.xml。
web.xml 文件中的各个配置项将会被解析成相应的属性保存在WebXml 对象中。
4、如果当前应用支持 Servlet3.0,解析还将完成额外 9 项工作,这个额外的 9 项工作主要是为 Servlet3.0 新增的特性,包括 jar 包中的 META-INF/web-fragment.xml 的解析以及对 annotations 的支持。
5、接下去将会将 WebXml 对象中的属性设置到 Context 容器中,这里包括创建 Servlet 对象、filter、listener 等等。这段代码在 WebXml 的 configureContext 方法中。
Servlet 包装成 StandardWrapper 并作为子容器添加到 Context 中,其它的所有 web.xml 属性都被解析到 Context 中, Context 容器才是真正运行 Servlet 的 Servlet 容器。

总结:找到各个XML文件,保存到WebXml对象,再设置到Context容器中;
一个 Web 应用对应一个 Context 容器,容器的配置属性由应用的 web.xml 指定。


9.2 创建 Servlet 实例
创建 Servlet 对象
如果 Servlet 的 load-on-startup 配置项大于 0,那么在 Context 容器启动的时候就会被实例化,前面提到在解析配置文件时会读取默认的 globalWebXml,在 conf 下的 web.xml 文件中定义了一些默认的配置项,其定义了两个 Servlet,分别是:org.apache.catalina.servlets.DefaultServlet 和 org.apache.jasper.servlet.JspServlet 它们的 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 文件为 class,并初始化这个 class。


9.3 Servlet 体系结构


与 Servlet 主动关联的是三个类,分别是 ServletConfig、ServletRequest 和 ServletResponse。
这三个类都是通过容器传递给 Servlet 的,其中 ServletConfig 是在 Servlet 初始化时就传给 Servlet 了,而后两个是在请求达到时调用 Servlet 时传递过来的。
我们很清楚 ServletRequest 和 ServletResponse 在 Servlet 运行的意义
ServletConfig :方法都是为了获取这个 Servlet 的一些配置属性,而这些配置属性可能在 Servlet 运行时被用到。 

Servlet 的运行模式是一个典型的“握手型的交互式”运行模式。所谓“ 握手型的交互式”就是两个模块为了交换数据通常都会准备一个交易场景,这个场景一直跟随个这个交易过程直到这个交易完成为止。这个交易场景的初始化是根据这次交易对象指定的参数来定制的,这些指定参数通常就会是一个配置类。

交易场景就由 ServletContext 来描述,而定制的参数集合就由 ServletConfig 来描述。而 ServletRequest 和 ServletResponse 就是要交互的具体对象了,它们通常都是作为运输工具来传递交互结果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值