SRV.2.3    Servlet生命周期

servlet有着定义良好且明确的生命周期,它定义了servlet以怎样的方式加载和实例化、初始化、怎样处理客户端请求、以及怎样停止服务。生命周期表现在API中就是javax.servlet.Servlet接口的init、service和destroy三个方法。所有servlet必须直接或者通过GenericServlet/HttpServlet间接实现这些方法。

    SRV.2.3.1    加载和实例化

servlet容器负责加载和实例化servlet。加载和实例化可以发生在容器启动时,或者发生在容器判断出servlet需要处理请求时。

servlet引擎启动时,一些基础的必需型servlet必须被定位、找到,然后servlet容器通过正常的Java类加载机制来加载这些servlet。加载可能源于本地文件系统,也可能是远程文件系统,或者是网络服务。

servlet类加载完成后,容器对其进行实例化以备使用。

    SRV.2.3.2    初始化

servlet对象实例化之后,容器必须初始化servlet才能用于处理客户端请求。初始化的过程主要用于servlet读取持久化的配置信息,初始化比较耗时的资源如jdbc等,以及执行其他的一次性操作。容器通过调用Servlet接口的init方法来完成servlet实例的初始化,当然,调用init方法时需要传入一个全局唯一配置参数,该参数必须实现了ServletConfig接口。这个配置对象允许servlet从Web 应用程序的配置信息中访问一些名-值对形式的初始化参数。这个配置对象也允许servlet访问servlet运行时环境的一个实现了ServletContext接口的特定对象。关于ServletConfig接口的更多信息请看第三章SRV.3中“Servlet Context”一节。

    SRV.2.3.2.1    初始化出错的情况

初始化期间,servlet实例可能会抛出UnavailableException或ServletException。此时,该servlet就不允许提供服务并且servlet容易必须释放它。这时destroy方法是不会被调用的,因为这个servlet根本就没有初始化成功。

初始化失败后,容器可以尝试再次实例化并初始化一个新的实例。当然,如果UnavailableException指明了unavailability的最小不可用时间后,容器必须等过了这段时间后才能创建和初始化新的servlet实例。

    SRV.2.3.2.2    关于工具的思考

当一个工具类加载和自检web应用系统时,它的静态初始化方法是完全不同于servlet的init方法的。直到Servlet接口的init方法被调用后,开发人员才应该把当前servlet列为已激活的容器运行时环境。例如,当静态初始化方法被调用时,servlet并不应该尝试建立与数据库或EJB容器的连接,而应该等到Servlet接口的init方法被成功执行后才行。

    SRV.2.3.3    请求的处理

servlet正常初始化完成后,容器就可以用它来处理客户端请求了。客户端的请求用ServletRequest类型的实例对象来表示。servlet通过调用ServletResponse类型实例对象的对应方法来生成响应信息,并把响应信息作为Servlet接口中service方法的参数传递下去。

在http请求中,容器提供出来的代表客户端请求和响应信息的对象分别是HttpServletRequest和HttpServletResponse。

值得注意的是,被容器放在服务队列中的Servlet实例可能在它的整个生命周期中都不处理客户端请求。这个是很有可能的,例如整个声明周期中都没有请求过来,那它就不会被执行的。

    SRV.2.3.3.1   多线程的问题

servlet容器可能发送多个并发请求给servlet的service方法。为了处理这些请求,serlvet开发人员必须仔细设计service方法,让它可以同时妥善处理这些请求。

开发人员可以通过实现SingleThreadModel接口来强制要求servlet容器去保证每次只有一个请求传给service方法,当然了,这种方式并不建议使用。servlet容器可以通过添加请求排队机制或者维护一个servlet实例池来满足对并发请求的处理要求。如果当前servlet是分布式应用系统的一部分,容器可能会针对分布式环境下的每一个JVM维护一个serlvet实例池,以处理并发请求。

对于没有实现SingleThreadModel接口的servlet,如果service已被定义为同步方法,那对应的servlet容器就不能再使用实例池机制,而只能添加请求排队机制了。强烈建议开发人员不要为service方法实现同步锁,因为这个同步锁会造成很大的性能影响。

    SRV.2.3.3.2    请求处理期间的异常

在处理请求期间,servlet是很可能抛出ServletException或UnavailableException的。ServletException标志着处理请求期间发生了一些错误,此时servlet容器应该采取合适的措施清理掉这些请求。

UnavailableException标志着当前servlet临时或永久性的不能处理请求了。

如果UnavailableException明确指示出servlet永久性的出现故障,那么容器必须从服务列表中通过调用servlet的destroy方法去移除并释放servlet实例。然后凡是被容器拒绝的请求都必须返回给客户端一个404响应信息。

如果只是临时性的出现故障,容器可以不再把客户端请求传递给当前servlet,直到该servlet服务恢复正常为止。此时凡是被容器拒绝的请求都必须返回给客户端一个服务不可用(503)响应信息。

当然了,servlet容器完全可以不区分永久性和临时性故障,一视同仁的把所有UnavailableExceptions当作永久性故障,并随后从服务列表中移除出现故障的servlet。

    SRV.2.3.3.3    线程安全性

请求和响应对象的实现方式并不是确保线程安全的。这意味着这些对象应该仅被用在请求处理线程的局部范围内。

请求和响应对象的引用绝不应该传递给当前正在执行的其他线程,以免对其他线程的执行结果造成干扰和不确定性。

如果应用创建的线程使用了由容器管理的对象,例如请求或响应对象,这些对象必须确保仅在servlet的服务周期内访问并且这样的线程在servlet的service方法内必须自己独立的生命周期,不然的话访问service方法执行结束后的这些对象很可能产生莫名其妙的各种问题。一定要做到请求和响应对象的线程安全性。如果这些对象不可避免的要在多线程下访问,那必须确保访问的方法已被同步或者对的封装添加线程安全控制,例如,同步一下访问这些请求属性的方法调用,或者在一个线程内使用本地局部变量去响应客户端请求。

    SRV.2.3.4    服务结束

某些时间内容器并不需要一直保持着servlet处于服务列表内。一个servlet实例的服务时间并不是固定的,可能只保持一小段时间,或者一直到容器的生命周期终结,或者居于两者之间。

当容器判定一个servlet应该被移除时,它会调用Servlet接口的destroy方法告知servlet释放它使用的任何资源并保存数据。例如,容器很可能在清理内存资源时销毁不必要的servlet,或者是在容器停止服务时。

在servlet容器调用destroy方法前,它必须确保所有正在执行的线程顺利完成所有操作,或者直接等到他们超过时间限制为止。总之,只有所有servlet都执行完了或者已经超过时间限制了,servlet容器才能调用destroy方法销毁servlet。

一旦servlet实例的destroy方法被调用了,容器就不会再传递任何请求给当前servlet实例。如果容器又要启用这个servlet,它也只能等到新的servlet实例启动完成后才传递请求过来。

destroy方法执行完成后,servlet容器必须释放servlet实例,然后垃圾回收机制才会适时回收servlet占用的资源和空间。

文档信息

Servlet 2.4 规范之第三篇:Servlet生命周期的更多相关文章

  1. 转:OSGi 入门篇:生命周期层

    OSGi 入门篇:生命周期层 前言 生命周期层在OSGi框架中属于模块层上面的一层,它的运作是建立在模块层的功能之上的.生命周期层一个主要的功能就是让你能够从外部管理应用或者建立能够自我管理的应用(或 ...

  2. iOS开发UI篇—UITabBarController生命周期(使用storyoard搭建)

    iOS开发UI篇—UITabBarController生命周期(使用storyoard搭建)   一.UITabBarController在storyoard中得搭建 1.新建一个项目,把storyb ...

  3. J2EE的13个规范之(三) Servlet简单介绍

    Servlet是一种server端脚本,它是一个特殊的Java类,继承自HttpServlet.开发中主要用于处理和响应client的请求. Servlet在容器中执行,事实上例的和销毁创建由容器进行 ...

  4. Servlet 2.4 规范之第七篇:过滤器

    过滤器是一套java组件,用于在请求—>资源—>应答的这一过程中即时转换处理负载和头信息. 本章讲述了Servlet 2.4 API中一些类和方法,这些类和方法提供了一套轻量级框架用于过滤 ...

  5. Servlet 2.4 规范之第六篇:响应

    响应对象封装了服务端返回给客户端的所有信息.在HTTP协议中,这些信息通过HTTP头和消息体传送. SRV.5.1    缓冲 出于效率考量,servlet容器可以缓冲输出数据,但这并非强制要求.常见 ...

  6. Servlet 2.4 规范之第五篇:请求

    request对象封装了来自客户端的所有请求信息.在HTTP协议中,客户端发给服务端的所有信息都是通过request对象的请求头和请求体来传送的.           SRV.4.1    HTTP协 ...

  7. Servlet 2.4 规范之第四篇:Servlet上下文

    SRV.3.1    ServletContext接口说明 ServletContext接口定义了运行servlet的web应用中和servlet相关的视图信息.容器提供者负责提供ServletCon ...

  8. Servlet(三):生命周期、常用方法、常见错误

    Servlet的生命周期:从第一次调用,到服务器关闭.如果在web.xml 中配置了load-on-startup则是从服务器开启到服务器关闭. 注意: * init方法是对Servlet进行初始化的 ...

  9. servlet篇 之 生命周期

    二:Servlet的生命周期 背景知识: servlet是单例,在web项目运行期间,一个servlet只会创建一个对象[tomcat帮我们实例 化][尽量不要在servlet中定义成员变量].因为w ...

随机推荐

  1. 初涉网络流[EK&dinic]

    主要还是板子 Edmonds-Karp 从S开始bfs,直到找到一条到达T的路径后将该路径增广,并重复这一过程. 在处理过程中,为了应对“找到的一条路径把其他路径堵塞”的情况,采用了建反向弧的方式来实 ...

  2. 【启发式拆分】bzoj4059: [Cerc2012]Non-boring sequences

    这个做法名字是从武爷爷那里看到的…… Description 我们害怕把这道题题面搞得太无聊了,所以我们决定让这题超短.一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,即每个子 ...

  3. mysql关联查询

    mysql数据库的统计------生成统计信息 1.distinct:在一组之中将各个唯一的值找出来,如找出所有的品牌种类 mysql>select distinct brand_kind fr ...

  4. Linux异常体系之stubs_offset

    转自 http://www.xuebuyuan.com/2208550.html 在ARM V4及V4T以后的大部分处理器中,中断向量表的位置可以有两个位置:一个是0x00000000,另一个是0xf ...

  5. i2c_drivers个人分析

    \arch\arm\mach-mx6\board-mx6q_sabresd.c static struct i2c_board_info i2c_board_info_rtc[] __initdata ...

  6. 【HIHOCODER 1599】逃离迷宫4

    描述 小Hi被坏女巫抓进一座由无限多个格子组成的矩阵迷宫. 小Hi一开始处于迷宫(x, y)的位置,迷宫的出口在(a, b).小Hi发现迷宫被女巫施加了魔法,假设当前他处在(x, y)的位置,那么他只 ...

  7. re--findall 【转】

    原文链接 python re 模块 findall 函数用法简述 代码示例: >>> import re >>> s = "adfad asdfasdf ...

  8. [转载]关于typedef的用法总结

    不管实在C还是C++代码中,typedef这个词都不少见,当然出现频率较高的还是在C代码中.typedef与#define有些相似,但更多 的是不同,特别是在一些复杂的用法上,就完全不同了,看了网上一 ...

  9. ios开发讲解之anchorPoint和position详解

    引言 相信初接触到CALayer的人都会遇到以下几个问题:  为什么修改anchorPoint会移动layer的位置? CALayer的position点是哪一点呢? anchorPoint与posi ...

  10. 使用Jquery与vuejs操作dom比较

    jquery实现添加功能 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...