Servlet与Tomcat的关系

  1. Servlet 工作原理解析:https://www.ibm.com/developerworks/cn/java/j-lo-servlet/
  2. JSP九大内置对象的作用和用法总结?http://blog.csdn.net/sona_shi555/article/details/7797068
  3. Servlet简介与Servlet和HttpServlet运行的流程:https://www.cnblogs.com/libingbin/p/5960456.html

servlet是什么?

Servlet是用Java编写的Server端程序,它与协议和平台无关。
Servlet运行于Java-enabled Web Server中。
Java Servlet可以动态地扩展Server的能力,并采用请求-响应模式提供Web服务。
最早支持Servlet技术的是JavaSoft的Java Web Server。
此后,一些其它的基于Java的Web Server开始支持标准的Servlet API。
Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。

Servlet 与 Servlet 容器的关系

image.png

要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力。虽然它们是彼此依存的,但是又相互独立发展,这一切都是为了适应工业化生产的结果。从技术角度来说是为了解耦,通过标准化接口来相互协作。既然接口是连接 Servlet 与 Servlet 容器的关键,那我们就从它们的接口说起。
(1)Context 容器
Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类 Wrapper,所以 Context 容器如何运行将直接影响 Servlet 的工作方式。

真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程,在 Tomcat 的配置文件中可以很容易发现这一点,如下:

<Context path="/projectOne " docBase="D:\projects\projectOne"
reloadable="true" />

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

清单 1:给 Tomcat 增加一个 Web 工程:
Tomcat tomcat = getTomcatInstance(); 
File appDir = new File(getBuildDirectory(), "webapps/examples"); 
tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); 
tomcat.start(); 
ByteChunk res = getUrl("http://localhost:" + getPort() + 
              "/examples/servlets/servlet/HelloWorldExample"); 
assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0);

清单 1的代码是创建一个 Tomcat 实例并新增一个 Web 应用,然后启动 Tomcat 并调用其中的一个 HelloWorldExample Servlet,看有没有正确返回预期的数据。

清单 2:Tomcat 的 addWebapp 方法的代码如下:
public Context addWebapp(Host host, String url, String path) { 
       silence(url); 
       Context ctx = new StandardContext(); 
       ctx.setPath( url ); 
       ctx.setDocBase(path); 
       if (defaultRealm == null) { 
           initSimpleAuth(); 
       } 
       ctx.setRealm(defaultRealm); 
       ctx.addLifecycleListener(new DefaultWebXmlListener()); 
       ContextConfig ctxCfg = new ContextConfig(); 
       ctx.addLifecycleListener(ctxCfg); 
       ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"); 
       if (host == null) { 
           getHost().addChild(ctx); 
       } else { 
           host.addChild(ctx); 
       } 
       return ctx; 
}

添加一个 Web 应用时将会创建一个 StandardContext 容器,并且给这个 Context 容器设置必要的参数(
url 代表这个应用在 Tomcat 中的访问路径;
path 代表这个应用实际的物理路径)
其中最重要的一个配置是 ContextConfig,【ContextConfig监听器】继承了 【LifecycleListener 监听器接口】,它是在调用清单 2 时被加入到 StandardContext 容器中。
当 Context 容器初始化状态设为 init 时,添加在 Context 容器的 Listener 将会被调用。【ContextConfig监听器】将会负责整个 Web 应用配置文件的解析工作。
最后将这个 Context 容器加到父容器 Host 中。

(3)【ContextConfig监听器】的解析工作有哪些?
ContextConfig 的 init 方法将会主要完成以下工作:
1.创建用于解析 xml 配置文件的 contextDigester 对象
1.读取默认 context.xml 配置文件,如果存在解析它
1.读取默认 Host 配置文件,如果存在解析它
1.读取默认 Context 自身的配置文件,如果存在解析它
1.设置 Context 的 DocBase
ContextConfig 的 init 方法完成后,Context 容器的会执行 startInternal 方法,这个方法启动逻辑比较复杂,主要包括如下几个部分:
1.创建读取资源文件的对象
1.创建 ClassLoader 对象
1.设置应用的工作目录
1.启动相关的辅助类如:logger、realm、resources 等
1.修改启动状态,通知感兴趣的观察者(Web 应用的配置)
1.子容器的初始化
1.获取 ServletContext 并设置必要的参数
1.初始化“load on startup”的 Servlet

(4)Web 应用的初始化工作?
应用的初始化主要是要解析 web.xml 文件,这个文件描述了一个 Web 应用的关键信息,也是一个 Web 应用的入口。
【web.xml 文件】中的各个配置项将会被解析成相应的属性保存在 【WebXml 对象】中。
接下去将会将 WebXml 对象中的属性设置到 Context 容器中,这里包括创建 Servlet 对象、filter、listener 等等,这些代码在 WebXml 的 configureContext 方法中。

(5)servlet 与 wrapper 的关系?
Servlet 被 【解析】 和 【包装】 成 【Context 容器中的 StandardWrapper】。
这里有个疑问,为什么要将 Servlet 包装成 StandardWrapper 而不直接是 Servlet 对象。
这里 StandardWrapper 是 Tomcat 容器中的一部分,它具有容器的特征,而 Servlet 为了一个独立的 web 开发标准,不应该强耦合在 Tomcat 中。


image.png

Servlet 体系结构

image.png

与 Servlet 主动关联的是三个顶层类,分别是 【ServletConfig】、【ServletRequest】 和 【ServletResponse】。这三个类都是通过容器传递给 Servlet 的。
(1)Servlet 的运行模式是一个典型的“握手型的交互式”运行模式。所谓“握手型的交互式”就是两个模块为了交换数据通常都会准备一个【交易场景】,这个场景一直跟随着这个交易过程直到这个交易完成为止。这个交易场景的初始化是根据这次【交易对象指定的参数来】定制的,这些指定参数通常就会是一个【配置类】。
(1)ServletConfig 接口的作用:获取这个 Servlet 的一些【配置类】属性。
(2)【ServletContext顶层类】的作用:是一个描述【交易场景】的【参数集合】即【配置类】。

Tomcat 创建的 Request 和 Response 类

image.png

1.Tomcat 一接受到请求首先将会创建 【org.apache.coyote.Request】 和 【org.apache.coyote.Response】,这两个类是 Tomcat 内部使用的描述一次请求和相应的信息类它们是一个轻量级的类,它们作用就是在服务器接收到请求后,经过简单解析将这个请求快速的分配给后续线程去处理,所以它们的对象很小,很容易被 JVM 回收。
2.接下去当交给一个用户线程去处理这个请求时又创建 【org.apache.catalina.connector.Request】 和 【org.apache.catalina.connector.Response】 对象。这两个对象一直穿越整个 Servlet 容器,直到要传给 Servlet。
3.传给 Servlet 的是 Request 和 Response 的【门面类】 【RequestFacade】 和 【ResponseFacade】,这里使用【门面模式】的目的——【封装容器中的数据】。

Servlet 如何工作?

当用户从浏览器向服务器发起一个请求,通常会包含如下信息:【http://hostname: port /contextpath/servletpath】。
hostname 和 port 是用来与服务器建立 TCP 连接。
而后面的【/contextpath/servletpath】即【 URL 】才是用来选择服务器中的哪个子容器来服务用户的请求。
Tomcat7.0 中有个映射类【org.apache.tomcat.util.http.mapper】,这个类保存了 Tomcat 的 Container 容器中的所有子容器的信息,
mapper 将会根据这次请求的 hostnane 和 contextpath 将 host 和 context 容器设置到 Request 的 mappingData 属性中。

Session

(1)Session的三种工作方式
1.基于 URL Path Parameter,默认就支持;
1.基于 Cookie,如果你没有修改 Context 容器和 cookies 标识的话,默认也是支持的;
1.基于 SSL,默认不支持,只有 connector.getAttribute(“SSLEnabled”) 为 TRUE 时才支持。
(2)SSL(Secure Sockets Layer 安全套接层)协议,及其继任者TLS(Transport Layer Security传输层安全)协议,是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密,用于保障网络数据传输安全,利用数据加密技术,确保数据在网络传输过程中不会被截取及窃听。SSL协议已成为全球化标准,所有主要的浏览器和WEB服务器程序都支持SSL协议,可通过安装SSL证书激活SSL协议。
SSL 证书就是遵守 SSL协议的服务器数字证书,由受信任的证书颁发机构(CA机构),验证服务器身份后颁发,部署在服务器上,具有网站身份验证和加密传输双重功能。
如果是第三种情况的话将会根据 javax.servlet.request.ssl_session 属性值设置 Session ID。
(3)有了 Session ID 服务器端就可以创建 HttpSession 对象了,第一次触发是通过 request. getSession() 方法,如果当前的 Session ID 还没有对应的 HttpSession 对象那么就创建一个新的,并将这个对象加到 org.apache.catalina. Manager 的 sessions 容器中保存,Manager 类将管理所有 Session 的生命周期,Session 过期将被回收,服务器关闭,Session 将被序列化到磁盘等。只要这个 HttpSession 对象存在,用户就可以根据 Session ID 来获取到这个对象,也就达到了状态的保持。
(4)Session 的致命弱点是不容易在多台服务器之间共享。

Servlet 中的 Listener

(1)整个 Tomcat 服务器中 Listener 使用的非常广泛,它是基于【观察者模式】设计的。
Listener 的设计对开发 Servlet 应用程序提供了一种快捷的手段,能够方便的从另一个【纵向维度控制程序和数据】。
(2)目前 Servlet 中提供了 6 种两类事件的观察者接口,它们分别是:
4 个 EventListeners 类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。
这些 Listener 的实现类可以配置在 web.xml 中的 标签中。当然也可以在应用程序中动态添加 Listener,需要注意的是 ServletContextListener 在容器启动之后就不能再添加新的,因为它所监听的事件已经不会再出现。掌握这些 Listener 的使用,能够让我们的程序设计的更加灵活。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容