Servlet规范之应用生命周期事件
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet规范之应用生命周期事件相关的知识,希望对你有一定的参考价值。
Application Lifecycle Events
文章是对 JSR-000340 JavaTM Servlet 3.1 Final Release的Java™ Servlet规范的翻译,尚未校准
文章目录
介绍
应用事件设施为Web应用开发者提供了对 ServletContext
和 HttpSession
以及 ServletRequest
生命周期的更好的控制,允许更好的代码因子,并提高管理Web应用所使用资源的效率。
Event Listeners
应用程序事件监听器是实现一个或多个Servlet事件监听器接口的类。在部署Web应用程序时,它们被实例化并在Web容器中注册。它们是由WAR中的开发者提供的。
Servlet事件监听器支持对 ServletContext
、HttpSession
和 ServletRequest
对象的状态变化进行事件通知。Servlet上下文监听器被用来管理资源或应用程序在JVM层面上的状态。HTTP会话监听器用于管理与同一客户或用户向Web应用程序发出的一系列请求相关的状态或资源。Servlet请求监听器用于管理Servlet请求的整个生命周期的状态。异步监听器用于管理异步事件,如超时和异步处理的完成。
可能有多个监听器类来监听每个事件类型,开发者可以指定容器为每个事件类型调用监听器Bean的顺序。
Event Types and Listener Interfaces
事件类型和用于监测它们的监听器接口显示在以下表格中。
TABLE 11-1 Servlet Context Events
Event Type | Description | Listener Interface |
---|---|---|
Lifecycle | 上下文刚刚被创建,可以为其第一个请求提供服务,或者Servlet上下文即将被关闭。 | javax.servlet.ServletContextListener |
Changes to attributes | 在servlet上下文上的属性已被添加、删除或替换。 | javax.servlet.ServletContextAttributeListener |
TABLE 11-2 HTTP Session Events
Event Type | Description | Listener Interface |
---|---|---|
Lifecycle | 一个HttpSession已经被创建、失效或超时。 | javax.servlet.http.HttpSessionListener |
Changes to attributes | 在一个HttpSession上,属性被添加、删除或替换。 | javax.servlet.httpHttpSessionAttributeListener |
Changes to id | HttpSession的id已经被改变。 | javax.servlet.httpHttpSessionIdListener |
Session migration | HttpSession已经被激活或钝化。 | javax.servlet.httpHttpSessionActivationListener |
Object binding | 对象已被绑定到HttpSession或从HttpSession解绑。 | javax.servlet.httpHttpSessionBindingListener |
TABLE 11-3 Servlet Request Events
Event Type | Description | Listener Interface |
---|---|---|
Lifecycle | 一个servlet请求已经开始被Web组件处理。 | javax.servlet.ServletRequestListener |
Changes to attributes | 在ServletRequest上添加、删除或替换了属性。 | javax.servlet.ServletRequestAttributeListener |
Async events | 超时、连接终止或异步处理的完成。 | javax.servlet.AsyncListener |
For details of the API, refer to the API reference.
An Example of Listener Use
为了说明事件的使用方案,考虑一个简单的Web应用程序,其中包含一些使用数据库的Servlet。开发者提供了一个用于管理数据库连接的servlet上下文监听器类。
- 当应用程序启动时,监听器类被通知。应用程序登录到数据库,并在servlet上下文中存储连接。
- 应用程序中的Servlet在Web应用程序的活动中根据需要访问该连接。
- 当Web服务器关闭时,或者应用程序从Web服务器上删除时,监听器类被通知,数据库连接被关闭。
Listener Class Configuration
提供监听器类
Web应用程序的开发者提供了监听器类,实现了javax.servlet
API中的一个或多个监听器接口。每个监听器类必须有一个公共构造函数,不需要任何参数。监听器类被打包到WAR中,可以在WEB-INF/classes
归档条目下,也可以在WEB-INF/lib
目录下的JAR中。
部署声明
监听器类在Web应用程序部署描述符中使用listener
元素进行声明。它们按类的名称列出,并按其被调用的顺序排列。与其他监听器不同,AsyncListener
类型的监听器只能以编程方式注册(使用ServletRequest
)。
监听器注册
Web 容器为每个监听器类创建一个实例,并在处理应用程序的第一个请求之前将其注册为事件通知。Web容器根据它们实现的接口和它们在部署描述符中出现的顺序来注册监听器实例。在Web应用执行过程中,给定事件的监听器大多按照它们的注册顺序被调用,但也有一些例外。例如,HttpSessionListener.destory
是以相反的顺序调用的。详见第8.2.3节,“从web.xml、web-fragment.xml和注解中组装描述符”。
关闭时通知
在应用程序关闭时,监听器将按照与它们的声明相反的顺序被通知,对会话监听器的通知在对上下文监听器的通知之前。会话监听器必须在上下文监听器收到应用程序关闭的通知之前被通知会话无效的情况。
部署描述符示例
下面的例子是注册两个Servlet上下文生命周期监听器和一个HttpSession
监听器的部署语法。
假设com.acme.MyConnectionManager
和com.acme.MyLoggingModule
都实现了javax.servlet.ServletContextListener
,并且com.acme.MyLoggingModule
额外实现了javax.servlet.http.HttpSessionListener
。另外,开发者希望com.acme.MyConnectionManager
在com.acme.MyLoggingModule
之前得到servlet上下文生命周期事件的通知。下面是这个应用程序的部署描述符。
<web-app>
<display-name>MyListeningApplication</display-name>
<listener>
<listener-class>com.acme.MyConnectionManager</listenerclass>
</listener>
<listener>
<listener-class>com.acme.MyLoggingModule</listener-class>
</listener>
<servlet>
<display-name>RegistrationServlet</display-name>
...etc
</servlet>
</web-app>
监听器实例和线程
容器需要在开始执行进入应用程序的第一个请求之前,完成Web应用程序中的监听器类的实例化。容器必须保持对每个监听器实例的引用,直到Web应用程序的最后一个请求得到服务。
ServletContext
和HttpSession
对象的属性变化可能同时发生。容器不需要将产生的通知同步到属性监听器类。维护状态的监听器类对数据的完整性负责,应该明确地处理这种情况。
监听器异常
监听器内的应用程序代码可能会在操作过程中抛出一个异常。一些监听器的通知发生在应用程序中另一个组件的调用树下。这方面的一个例子是设置会话属性的 servlet,其中会话监听器会抛出一个未处理的异常。容器必须允许未处理的异常由第 10.9 节 "错误处理 "中描述的错误页机制来处理。如果没有为这些异常指定错误页,那么容器必须确保以状态 500 发送一个响应。在这种情况下,该事件下没有更多的监听器被调用。
有些异常不会发生在应用程序中另一个组件的调用栈下。这方面的一个例子是,SessionListener
收到会话超时的通知并抛出一个未处理的异常,或者 ServletContextListener
在通知Servlet上下文初始化时抛出一个未处理的异常,或者 ServletRequestListener
在通知初始化或销毁请求对象时抛出一个未处理的异常。在这种情况下,开发者没有机会来处理这个异常。容器可能会用HTTP状态代码500来响应所有对Web应用程序的后续请求,以表示应用程序错误。
开发人员希望在监听器产生异常后进行正常的处理,必须在通知方法中处理他们自己的异常。
分布式容器
在分布式Web容器中,HttpSession
实例的范围是服务会话请求的特定JVM,而ServletContext
对象的范围是Web容器的JVM。分布式容器不需要将servlet context事件或HttpSession
事件传播给其他JVM。监听器类实例的范围是每个JVM的部署描述符声明一个。
会话事件
监听器类为开发者提供了一种在Web应用程序中跟踪会话的方法。在跟踪会话时,了解会话是否因为容器超时而变得无效,还是因为应用程序中的Web组件调用了 invalidate
方法,通常是很有用的。可以使用监听器和 HttpSession
API方法间接地确定这种区别。
以上是关于Servlet规范之应用生命周期事件的主要内容,如果未能解决你的问题,请参考以下文章
JavaWeb-Servlet笔记--- Servlet规范;Servlet接口实现类;Servlet对象生命周期;HttpServletResponse/HttpServletRequest;请求对