基于servlet的执行原理与生命周期(全面解析)

一、先从servlet容器说起:大家最为熟悉的servlet容器就是Tomcat ,Servlet 容器是如何管理 Servlet?

先看一下tomcat的容器模型:

从上图可以看出 Tomcat 的容器分为四个等级,真正管理Servlet 的容器是Context 容器,一个 Context 对应一个 Web 工程

Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类Wrapper(StandardWrapper)的容器,所以 Context 容器如何运行将直接影响 Servlet 的工作方式。

这里解释一下servlet的包装类:StandardWrapper,这里有个疑问,为什么要将 Servlet 包装成 StandardWrapper 而不直接是 Servlet 对象。因为StandardWrapper 是 Tomcat 容器中的一部分,它具有容器的特征,而 Servlet 为一个独立的 web 开发标准,不应该强耦合在 Tomcat 中。

除了将 Servlet 包装成 StandardWrapper 并作为子容器添加到 Context 中,其它的所有 web.xml 属性都被解析到 Context 中,所以说 Context 容器才是真正运行 Servlet 的 Servlet 容器。一个 Web 应用对应一个 Context 容器,容器的配置属性由应用的 web.xml 指定,这样我们就能理解 web.xml 到底起到什么作用了

二、下面简述一下servlet的工作工程:

Web服务器在与客户端交互时.Servlet的工作过程是:

1.在客户端对web服务器发出请求

2.web服务器接收到请求后将其发送给Servlet

3.Servlet容器为此产生一个实例对象并调用ServletAPI中相应的方法来对客户端HTTP请求进行处理,然后将处理的响应结果返回给WEB服务器.

4.web服务器将从Servlet实例对象中收到的响应结构发送回客户端.

三、servlet的生命周期:

如上图所示,Servlet的生命周期可以分为四个阶段,即装载类及创建实例阶段、初始化阶段、服务阶段和实例销毁阶段。下面针对每个阶段的编程任务及注意事项进行详细的说明。

1、创建servlet实例:

在默认情况下Servlet实例是在第一个请求到来的时候创建,以后复用。如果有的Servlet需要复杂的操作需要载初始化时完成,比如打开文件、初始化网络连接等,可以通知服务器在启动的时候创建该Servlet的实例。具体配置如下:

<servlet>
<servlet-name>TimeServlet</servlet-name>
<servlet-class>com.allanlxf.servlet.basic.TimeServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

创建servlet对象的相关类结构:

2、初始化

一旦Servlet实例被创建,Web服务器会自动调用init(ServletConfig config)方法来初始化该Servlet。其中方法参数config中包含了Servlet的配置信息,比如初始化参数,该对象由服务器创建。

I.如何配置Servlet的初始化参数?

在web.xml中该Servlet的定义标记中,比如:

<servlet>
<servlet-name>TimeServlet</servlet-name>
<servlet-class>com.allanlxf.servlet.basic.TimeServlet</servlet-class>
<init-param>
<param-name>user</param-name>
<param-value>username</param-value>
</init-param>
<init-param>
<param-name>blog</param-name>
<param-value>http://。。。</param-value>
</init-param>
</servlet>

配置了两个初始化参数user和blog它们的值分别为username和http://。。。, 这样以后要修改用户名和博客的地址不需要修改Servlet代码,只需修改配置文件即可。

II.如何读取Servlet的初始化参数?

ServletConfig中定义了如下的方法用来读取初始化参数的信息:

public String getInitParameter(String name)

参数:初始化参数的名称。

返回:初始化参数的值,如果没有配置,返回null。

III.init(ServletConfig)方法执行次数

在Servlet的生命周期中,该方法执行一次。

IV.init(ServletConfig)方法与线程

该方法执行在单线程的环境下,因此开发者不用考虑线程安全的问题。

V.init(ServletConfig)方法与异常

该方法在执行过程中可以抛出ServletException来通知Web服务器Servlet实例初始化失败。一旦ServletException抛出,Web服务器不会将客户端请求交给该Servlet实例来处理,而是报告初始化失败异常信息给客户端,该Servlet实例将被从内存中销毁。如果在来新的请求,Web服务器会创建新的Servlet实例,并执行新实例的初始化操作

3、服务

一旦Servlet实例成功创建及初始化,该Servlet实例就可以被服务器用来服务于客户端的请求并生成响应。在服务阶段Web服务器会调用该实例的service(ServletRequest request, ServletResponse response)方法,request对象和response对象有服务器创建并传给Servlet实例。request对象封装了客户端发往服务器端的信息,response对象封装了服务器发往客户端的信息。

I. service()方法的职责

service()方法为Servlet的核心方法,客户端的业务逻辑应该在该方法内执行,典型的服务方法的开发流程为:

解析客户端请求-〉执行业务逻辑-〉输出响应页面到客户端

II.service()方法与线程

为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性。

III.service()方法与异常

service()方法在执行的过程中可以抛出ServletException和IOException。其中ServletException可以在处理客户端请求的过程中抛出,比如请求的资源不可用、数据库不可用等。一旦该异常抛出,容器必须回收请求对象,并报告客户端该异常信息。IOException表示输入输出的错误,编程者不必关心该异常,直接由容器报告给客户端即可。

编程注意事项说明:

1) 当Server Thread线程执行Servlet实例的init()方法时,所有的Client Service Thread线程都不能执行该实例的service()方法,更没有线程能够执行该实例的destroy()方法,因此Servlet的init()方法是工作在单线程的环境下,开发者不必考虑任何线程安全的问题。

2) 当服务器接收到来自客户端的多个请求时,服务器会在单独的Client Service Thread线程中执行Servlet实例的service()方法服务于每个客户端。此时会有多个线程同时执行同一个Servlet实例的service()方法,因此必须考虑线程安全的问题。

3) 请大家注意,虽然service()方法运行在多线程的环境下,并不一定要同步该方法。而是要看这个方法在执行过程中访问的资源类型及对资源的访问方式。分析如下:

i. 如果service()方法没有访问Servlet的成员变量也没有访问全局的资源比如静态变量、文件、数据库连接等,而是只使用了当前线程自己的资源,比如非指向全局资源的临时变量、request和response对象等。该方法本身就是线程安全的,不必进行任何的同步控制。

ii. 如果service()方法访问了Servlet的成员变量,但是对该变量的操作是只读操作,该方法本身就是线程安全的,不必进行任何的同步控制。

iii. 如果service()方法访问了Servlet的成员变量,并且对该变量的操作既有读又有写,通常需要加上同步控制语句。

iv. 如果service()方法访问了全局的静态变量,如果同一时刻系统中也可能有其它线程访问该静态变量,如果既有读也有写的操作,通常需要加上同步控制语句。

v. 如果service()方法访问了全局的资源,比如文件、数据库连接等,通常需要加上同步控制语句。

4、销毁

当Web服务器认为Servlet实例没有存在的必要了,比如应用重新装载,或服务器关闭,以及Servlet很长时间都没有被访问过。服务器可以从内存中销毁(也叫卸载)该实例。Web服务器必须保证在卸载Servlet实例之前调用该实例的destroy()方法,以便回收Servlet申请的资源或进行其它的重要的处理。

Web服务器必须保证调用destroy()方法之前,让所有正在运行在该实例的service()方法中的线程退出或者等待这些线程一段时间。一旦destroy()方法已经执行,Web服务器将拒绝所有的新到来的对该Servlet实例的请求,destroy()方法退出,该Servlet实例即可以被垃圾回收。

四、servlet解析客户端http请求流程图:

1.web客户向Servlet容器发出HTTP请求;

2.Servlet容器解析web的HTTP请求.

3.Servlet容器创建一个HttpRequest对象,在这个对象中封装了http请求信息;

4.Servlet容器创建一个HttpResponse对象;

5.Servlet容器(如果访问的该servlet不是在服务器启动时创建的,则先创建servlet实例并调用init()方法初始化对象)调用HttpServlet的service()方法,把HttpRequest和HttpResponse对象为service方法的参数传给HttpServlet对象;

6.HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;

7.HttpServlet调用HttpResponse的有关方法,生成响应数据;

8.Servlet容器把HttpServlet的响应结果传给web客户.

以上这篇基于servlet的执行原理与生命周期(全面解析)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

您可能感兴趣的文章:

  • servlet配置方法及其生命周期详解
(0)

相关推荐

  • servlet配置方法及其生命周期详解

    servlet配置: 在web.xml中,首先向服务器注册一个servlet.在<servlet>标签下 给定一个servlet名字,这个servlet-name是我们自己用的,方便我们用它对servlet进行配置. 1 <servlet-name>AServlet</servlet-name>然后指定一个全类名,这个是给服务器使用,服务器用来创建全类名对象的实例 1 <servlet-class>com.servlet.AServlet</servl

  • 基于servlet的执行原理与生命周期(全面解析)

    一.先从servlet容器说起:大家最为熟悉的servlet容器就是Tomcat ,Servlet 容器是如何管理 Servlet? 先看一下tomcat的容器模型: 从上图可以看出 Tomcat 的容器分为四个等级,真正管理Servlet 的容器是Context 容器,一个 Context 对应一个 Web 工程 Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类Wrapper(StandardWrapper)的容器,所以 Context 容器如何运行

  • 基于Vue实例生命周期(全面解析)

    前面的话 Vue实例在创建时有一系列的初始化步骤,例如建立数据观察,编译模板,创建数据绑定等.在此过程中,我们可以通过一些定义好的生命周期钩子函数来运行业务逻辑.本文将详细介绍Vue实例的生命周期 图示 下图是Vue实例生命周期的图示 解释 接下来,根据提供的生命周期钩子,对Vue实例各个阶段的情况进行详细说明 [beforeCreate] 在实例开始初始化时同步调用.此时数据观测.事件等都尚未初始化 [created] 在实例创建之后调用.此时已完成数据观测.事件方法,但尚未开始DOM编译,即

  • MySql执行流程与生命周期详解

    目录 一.MySQL 客户端 二.MySQL 服务端 1. 查询缓存 2. SQL 解析器 3. 查询优化器 4. SQL 执行器 总结 我们经常会在一起讨论怎样优化 SQL.怎样优化数据库,那么请问你知道执行一条 SQL 的过程中都经过了哪些动作吗?如果不知道的话,又怎么去优化 SQL.优化数据库呢?为了更好地优化 MySQL 数据库,接下来我们就来讨论一下执行一条 SQL 都经过哪些步骤. 为了方便理解,在介绍 SQL 执行流程之前,我们先通过一张图,来详细阐述一下 SQL 执行流程. 由上

  • Flutter组件生命周期和App生命周期示例解析

    目录 引言 无状态组件(StatelessWidget) 有状态组件(StatefulWidget) StatefulWidget生命周期详细分析 1. createState 2. initState 3. didChangeDependencies 4. build 5. didUpdateWidget 6. deactivate 7. dispose 8. reassemble App生命周期 结束语 引言 在Flutter开发中,所有的组件和页面都继承自Widget,所以探索页面的生命周

  • C++临时性对象的生命周期详细解析

    有关临时对象的生命周期有三种情况: 1)一般情况:临时性对象的被摧毁,应该是对完整表达式(full-expression)求值过程中的最后一个步骤.该完整表达式造成临时对象的产生. 实例代码如下: 复制代码 代码如下: #include <iostream>using namespace std;class A{public:    A(int i): m_i(i)    {        cout << "A(): " << m_i <<

  • Spring中Bean的生命周期使用解析

    Bean的生命周期 解释 (1)BeanFactoryPostProcessor的postProcessorBeanFactory()方法:若某个IoC容器内添加了实现了BeanFactoryPostProcessor接口的实现类Bean,那么在该容器中实例化任何其他Bean之前可以回调该Bean中的postPrcessorBeanFactory()方法来对Bean的配置元数据进行更改,比如从XML配置文件中获取到的配置信息. (2)Bean的实例化:Bean的实例化是使用反射实现的. (3)B

  • Servlet生命周期与工作原理详解

    本文为大家分享了Servlet生命周期与工作原理,供大家参考,具体内容如下 Servlet生命周期分为三个阶段: 1.初始化阶段  调用init()方法 2.响应客户请求阶段 调用service()方法 3.终止阶段 调用destroy()方法 Servlet初始化阶段: 在下列时刻Servlet容器装载Servlet: 1.Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码: <lo

  • vue2与vue3中生命周期执行顺序的区别说明

    目录 vue2与vue3中生命周期执行顺序区别 生命周期比较 简单例子说明 三种情况下的生命周期执行顺序 1.单页面下生命周期顺序 2.父子.兄弟组件的生命周期顺序 3.不同页面跳转时各页面生命周期的执行顺序 vue2与vue3中生命周期执行顺序区别 生命周期比较 vue2中执行顺序 beforeCreate=>created=>beforeMount =>mounted=>beforeUpdate =>updated=>beforeDestroy=>destro

  • 深入解析AngularJS框架中$scope的作用与生命周期

    $scope 的使用贯穿整个 Angular App 应用,它与数据模型相关联,同时也是表达式执行的上下文.有了 $scope 就在视图和控制器之间建立了一个通道,基于作用域视图在修改数据时会立刻更新 $scope,同样的 $scope 发生改变时也会立刻重新渲染视图. 有了 $scope 这样一个桥梁,应用的业务代码可以都在 controller 中,而数据都存放在controller 的 $scope 中. $scope是一个把view(一个DOM元素)连结到controller上的对象.在

  • 详解ASP.NET页面生命周期

    ASP.NET页面运行时候,页面将经历一个生命周期,在生命周期中将执行一系列的处理步骤.包括初始化.实例化控件.还原和维护状态.运行时间处理程序代码以及进行呈现.熟悉页面生命周期非常重要,这样我们才能在生命周期的合适阶段编写代码.如果我们能在写代码的时候想着我们现在是在做生命周期的哪一步那将是非常好的. 几个代表性的问题 在开始的时候我们先思考几个问题,看看我们在描述完页面生命周期的时候,能不能回答上这几个问题 1.为什么在服务器端能通过this.textbox1.Text获取到用户提交过来的数

随机推荐