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. 利用wget 和 curl 监控网站是否正常

    监控网站URL是否正常最常见的方法莫过于wget和curl命令了,这两个命令都是非常强大,参数也非常多,下面列举几个常用的参数. wget  常用命令参数:--spider              ...

  2. tab key usage

    QA:gvim编辑ascii文本时由于tabkey的default setting 不合适编写Verilog代码(比如一个tab 代表多少空格) ANS: 1.tab 的自动补齐有两种usage自动补 ...

  3. linux系统装载ELF过程

    参考:程序员的自我修养 fork -->execve() //----kenerl space--------------- sys_execve() /*arch\i386\kernel\pr ...

  4. LeetCode(205)Isomorphic Strings

    题目 Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the ch ...

  5. RSS列表

    博客园 http://feed.cnblogs.com/blog/sitehome/rss

  6. HDU 5371 Manacher Hotaru's problem

    求出一个连续子序列,这个子序列由三部分ABC构成,其中AB是回文串,A和C相同,也就是BC也是回文串. 求这样一个最长的子序列. Manacher算法是在所有两个相邻数字之间插入一个特殊的数字,比如- ...

  7. 基于AOP的优惠券发送异常哨兵监控

    本文来自网易云社区 作者:王贝 最近总是发现支付发红包优惠券发完的情况,但是发现的比较迟缓,于是乎,想加一个哨兵监控,统计了一下,组内不少需求都有发送优惠券的行为,也是经常遇到发送异常的情况,所以,想 ...

  8. Python的深浅copy

    27.简述Python的深浅拷贝以及应用场景? 深浅拷贝的原理 深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:copy.deepcopy 字面理 ...

  9. css图像处理与动画

    先讨论几个css 问题 1,css 清除浮动的方法 2,css 居中 3,多行省略号 4,小布局技巧 2D 动画功能属性兼容性:transform.transition.animation trans ...

  10. xml ,html,xhtml

    html,xhtml和xml的定义: 1.html即是超文本标记语言(Hyper Text Markup Language),是最早写网页的语言,但是由于时间早,规范不是很好,大小写混写且编码不规范: ...