https://github.com/javahongxi
本文轉載自kaitao.hongxi.org
應用生命週期事件
11.1 介紹
應用事件設施給Web應用開發人員更好地控制ServletContext、HttpSession和ServletRequest的生命週期,可以更好地代碼分解,並在管理Web應用使用的資源上提高了效率。
11.2 事件監聽器
應用事件監聽器是實現一個或多個Servlet事件監聽器接口的類。它們是在部署Web應用時,實例化並註冊到Web容器中。它們由開發人員在WAR包中提供。
Servlet事件監聽器支持在ServletContext、HttpSession和ServletRequest狀態改變時進行事件通知。Servlet上下文監聽器是用來管理應用的資源或JVM級別持有的狀態。HTTP會話監聽器是用來管理從相同客戶端或用戶進入web應用的一系列請求關聯的狀態或資源。Servlet請求監聽器是用來管理整個Servlet請求生命週期的狀態。異步監聽器是用來管理異步事件,例如超時和完成異步處理。
可以有多個監聽器類監聽每一個事件類型,且開發人員可以爲每一個事件類型指定容器調用監聽器bean的順序。
11.2.1 事件類型和監聽器接口
事件類型和監聽器接口用於監控下表所示的:
表 11-1 Servlet上下文事件
事件類型 |
描述 |
監聽器接口 |
生命週期 |
Servlet上下文剛剛創建 並可用於服務它的第一個請求, 或者Servlet上下文即將關閉 |
javax.servlet. ServletContextListener |
更改屬性 |
在Servlet上下文的屬性已添加、刪除、或替換。 |
javax.servlet. ServletContextAttributeListener |
表 11-2 HTTP會話事件
事件類型 |
描述 |
監聽器接口 |
生命週期 |
會話已創建、銷燬或超時。 |
javax.servlet.http. HttpSessionListener |
更改屬性 |
已經在HttpSession上添加、移除、或替換屬性。 |
javax.servlet.http. HttpSessionAttributeListener |
會話遷移 |
HttpSession已被激活或鈍化。 |
javax.servlet.http. HttpSessionActivationListener |
對象綁定 |
對象已經從HttpSession綁定或解除綁定 |
javax.servlet.http. HttpSessionBindingListener |
表 11-3 Servlet請求事件
事件類型 |
描述 |
監聽器接口 |
生命週期 |
一個servlet請求已經開始由Web組件處理。 |
javax.servlet. ServletRequestListener |
更改屬性 |
已經在ServletRequest上添加、移除、或替換屬性。 |
javax.servlet. ServletRequestAttributeListener |
異步事件 |
超時、連接終止或完成異步處理 |
javax.servlet.AsyncListener |
11.2.2 監聽器使用的一個例子
爲了說明事件使用方案,考慮一個包含一些使用數據庫的Servlet的簡單Web應用。開發人員提供了一個Servlet上下文監聽器類用於管理數據庫連接。
1. 當應用啓動時,監聽器類得到通知。應用登錄到數據庫,並在servlet上下文中存儲連接。
2. 應用中的Servlet根據需要,在Web應用的活動期間訪問連接。
3. 當Web服務器關閉時,或應用從Web服務器移除時,監聽器類得到通知且關閉數據庫連接。
11.3 監聽器類配置
11.3.1 提供監聽器類
Web應用的開發人員提供實現了一個或多個在javax.servlet API中的監聽器接口的監聽器類。每一個監聽器類必須有一個無參構造器。監聽器類打包到WAR包中,或者在WEB-INF/classes歸檔項下,或者在WEB-INF/lib目錄的一個JAR內部。
11.3.2 部署聲明
監聽器類在Web應用部署描述符中使用listener元素聲明。它們根據類名列出的順序就是它們被調用的順序。與其他監聽器不同,AsyncListener類型的監聽器可能僅通過編程式註冊(使用一個ServletRequest)。
11.3.3 監聽器註冊
Web容器創建每一個監聽器類的一個實例,並在應用處理第一個請求之前爲事件通知註冊它。Web容器根據他們實現的接口註冊監聽器實例,且按照它們出現在部署描述符中的順序。在Web應用執行期間,監聽器按照它們註冊的順序被調用。
11.3.4 關閉時通知
在應用關閉時,監聽器以它們聲明時相反的順序得到通知,且通知會話監聽器在通知上下文監聽器之前。通知會話監聽器session失效必須在通知上下文監聽器關閉之前。
11.4 部署描述符示例
以下示例是註冊兩個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</listener-class>
</listener>
<listener>
<listener-class>com.acme.MyLoggingModule</listener-class>
</listener>
<servlet>
<display-name>RegistrationServlet</display-name>
...etc
</servlet>
</web-app>
11.5 監聽器實例和線程
容器需要在開始執行進入應用的第一個請求之前完成Web應用中的監聽器類的實例化。容器必須保持到每一個監聽器的引用直到爲Web應用最後一個請求提供服務。
ServletContext和HttpSession對象的屬性改變可能會同時發生。不要求容器同步到屬性監聽器類產生的通知。維護狀態的監聽器類負責數據的完整性且應明確處理這種情況。
11.6 監聽器異常
一個監聽器裏面的應用代碼在運行期間可能會拋出異常。一些監聽器通知發生在應用中的另一個組件調用樹過程中。這方面的一個例子是一個Servlet設置了會話屬性,該會話監聽器拋出未處理異常。容器必須允許未處理的異常由描述在10.9節“錯誤處理”的錯誤頁面機制處理。如果沒有爲這些異常指定錯誤頁面,容器必須確保返回一個狀態碼爲500的響應。這種情況下,不再有監聽器根據事件被調用。
有些異常不會發生在應用中的另一個組件調用棧過程中。這方面的一個例子SessionListener接收通知的會話已經超時並拋出未處理的異常,或者ServletContextListener在Servlet上下文初始化通知期間拋出未處理異常,或者ServletRequestListener在初始化或銷燬請求對象的通知期間拋出未處理異常。這種情況下,開發人員沒有機會處理這種異常。容器可以以HTTP狀態碼500來響應所有後續的到Web應用的請求,表示應用出錯了。
開發人員希望發生在監聽器產生一個異常且在通知方法裏面必須處理它們自己的異常之後的正常處理。
11.7 分佈式容器
在分佈式Web容器中,HttpSession實例被限到特定的JVM服務會話請求,且ServletContext對象被限定到Web容器所在的JVM。分佈式容器不需要傳播Servlet上下文事件或HttpSession事件到其他JVM。監聽器類實例被限定到每個JVM的每個部署描述符聲明一個。
11.8 會話事件
監聽器類提供給開發人員一種跟蹤Web應用內會話的方式。它通常是有用的,在跟蹤會話知道一個會話是否變爲失效,因爲容器超時會話,或因爲應用內的一個Web組件調用了invalidate方法。該區別可能會間接地決定使用監聽器和HttpSession API方法。