(一)Servlet 工作原理解析-第一讲 Servlet 容器

阿凯不错

提供最棒的技术分享,关注get新技能

阅读文本大概需要 10 分钟。

初学 Java Web 开发,请远离各种框架,从 Servlet 开始。 那么Servlet 到底是什么呢?

先说概念:事实上,Servlet 就是一个 Java 接口interface

那 Servlet 是干嘛的?很简单,接口的作用是什么?

一样的 定义规范...

Servlet 接口定义的是一套处理网络请求的规范,所有实现 Servlet 的类,都需要实现它那五个方法,其中最主要的是两个生命周期方法 init() 和 destroy() ,还有一个处理请求的 service() ,也就是说,所有实现 Servlet 接口的类,或者说,所有想要处理网络请求的类,都需要回答这三个问题:

- 你初始化时要做什么

- 你接受到请求时要做什么

- 你销毁时要做什么

这是Java给的一种规范!

Servlet 是一个规范,那实现了 Servlet 的类,就能直接处理请求了吗?

不能,Servlet 并不会直接和客户端打交道 !我们写的 Servlet 程序都需要部署到一个容器中,不然你的 Servlet 压根不会起作用。比如我们最常用的 Tomcat。

Tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据 url 等信息,确定要将请求交给哪个Servlet 去处理,然后调用那个 Servlet 的 service() 方法,service 方法返回一个 response 对象,tomcat再把这个 response 返回给客户端。

要介绍 Servlet 必须要先把 Servlet 容器说清楚

Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力。

虽然它们是彼此依存的,但是又相互独立发展,从技术角度来说是为了解耦,通过标准化接口来相互协作。Servlet 要求必须运行在 Web 服务器当中,与 Web 服务器之间属于分工和互补关系。

确切的说,在实际运行的时候 Servlet 与 Web 服务器会融为一体,如同一个程序一样,运行在同一个Java虚拟机(JVM)当中。因为JavaServlet 是运行在虚拟机之上的,也就解决了跨平台问题。如果没有 Servlet 的出现,也就没有互联网的今天。

我们这里以大家最为熟悉Tomcat 为例来介绍 Servlet容器如何管理 Servlet 。

Tomcat 容器模型

从上图可以看出 Tomcat 的容器分为四个等级,真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程,在 Tomcat 的配置文件(server.xml) 中可以很容易发现这一点,如下:

下面详细介绍一下 Tomcat 解析 Context 容器的过程,包括如何构建 Servlet 的过程。既然接口是连接 Servlet 与 Servlet 容器的关键,那我们就从它们的接口说起。

1.Servlet 容器的启动过程

创建一个Tomcat的一个实例对象,新增了一个WEB应用 (Tomcat的addWebap方法 ),并调用start方法就可以启动 tomcat。

一个 Web 应用对应一个 Context 容器,也就是 Servlet 运行时的 Servlet 容器。

添加一个 Web 应用时将会创建一个StandardContext容器,并且给这个 Context 容器设置必要的参数,url 和 path 分别代表这个应用在 Tomcat 中的访问路径和这个应用实际的物理路径,这两个参数与 Tomcat 配置中的两个参数是一致的。

其中最重要的一个配置是ContextConfigContextConfig 类 负责整个WEB应用的配置文件的解析工作,后面将会详细介绍。

最后将这个 Context 容器加到父容器 Host 中。接下去将会调用 Tomcat 的 start 方法启动 Tomcat。

2.Web应用的初始化工作

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

Tomcat 首先会找 globalWebXml,以及应用的配置文件web.xml文件中的各个配置项将会被解析成相应的属性保存在WebXml 对象中。接下来会将 WebXml 对象中的属性设置到 context 容器中,这里包括创建 Servlet 对象,filter,listerner等。

将 Servlet 容器包装成 context 容器中的 StandardWrapper

StandardWrapper 是 Tomcat 容器中的一部分,它具有容器的特征,而 Servlet 作为一个独立的 web 开发标准,不应该强制耦合在Tomcat中。

3.创建Servlet对象

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

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

创建 Servlet 实例的方式是从Wrapper.loadServlet开始的,loadServlet 方法要完成的就是获取 servletClass,然后把它交给 InstanceManager 去创建一个基于 servletClass.class 的对象。

4.初始化Servlet对象

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

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

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

如果算上监听器的话,整个过程是这样的:

启动web项目后,web容器首先回去找 web.xml文件,读取这个文件。

容器会创建一个 ServletContext ( servlet 上下文),整个 web 项目的所有部分都将共享这个上下文。

容器将 转换为键值对,并交给 servletContext

容器创建 中的类实例,创建监听器。

容器加载 filter,创建过滤器, 要注意对应的filter-mapping一定要放在filter的后面。

容器加载 servlet,加载顺序按照 Load-on-startup 来执行

因此它的完整加载顺序就是 :

ServletContext->context-param->listener->filter->servlet

web 容器接收消息后不知道怎么处理,转交给我们编写的Servlet 处理

那么web容器怎么和Servlet 交流呢?于是就出现了Servlet 接口,接口是定义一种规范的良好表达形式。 只要我们编写符合 Servlet 规范的Java 类,那么就能被Web容器识别并被容器管理。

以上。

后期更多猛料放出,关注 阿凯不错 公众号,获取实时动态:

大家还有什么需求,也可以后台留言给我,公众号上还有其他学习资源哦....

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180523G1GSSJ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券