1. 程式人生 > >Servlet監聽器詳解及舉例

Servlet監聽器詳解及舉例

監聽器就是一個實現特定介面的普通java程式,這個程式專門用於監聽另一個java物件的方法呼叫或屬性改變,當被監聽物件發生上述事件後,監聽器某個方法將立即被執行。

監聽器原理

監聽原理
1、存在事件源
2、提供監聽器
3、為事件源註冊監聽器
4、操作事件源,產生事件物件,將事件物件傳遞給監聽器,並且執行監聽器相應監聽方法

監聽器典型案例:監聽window視窗的事件監聽器
例如:swing開發首先製造Frame**窗體**,窗體本身也是一個顯示空間,對窗體提供監聽器,監聽窗體方法呼叫或者屬性改變:
* 關閉窗體時,呼叫windowListener 的windowclosing() , 傳遞windowEvent引數,表示窗體關閉事件物件
* 事件物件操作事件源,獲得事件源狀態

自定義監聽器

以上內容可以用下圖解釋:

這裡寫圖片描述

通過person.addPersonListener(new PersonListener(){})使事件源與監聽器間產生聯絡。

事件源(在事件源方法中建立事件物件):

監聽器(引數是事件物件)

事件物件(通過事件物件可以獲得事件源)

測試方法

對上的匿名類補充:匿名內部類的作用是建立一個實現介面的匿名類物件,含義是建立一個繼承自PersonListener的匿名類的物件),通過new表示式返回的引用被自動向上轉型為對PersonListener的引用

Servlet監聽器

不需要配置,但是監聽器仍需要進行註冊
在Servlet規範中定義了多種型別的監聽器,它們用於監聽的事件源

分別為 ServletContext, HttpSessionServletRequest 這三個域物件。

Servlet監聽器分為三大類
1、資料域物件建立和銷燬監聽器
2、資料域物件和屬性變更監聽器
3、繫結到 HttpSession 域中的某個物件的狀態的事件監聽器

(一)資料域物件建立銷燬監聽器 — 監聽三個與物件 (三個監聽器)

1、ServletContextListener : 用來監聽ServletContext物件的建立和銷燬
監聽建立
監聽銷燬
* ServletContext物件代表全域性唯一物件,每個web工程會產生一個ServletContext,伺服器啟動建立,伺服器關閉銷燬

編寫監聽器
步驟一:編寫類實現特定監聽器介面
步驟二:註冊監聽器,不是通過事件源,而是在web.xml 進行配置
監聽器和Servlet、Filter不同,不需要url配置,監聽器執行不是由使用者訪問的,監聽器 是由事件源自動呼叫的

servletContext域物件何時建立和銷燬

  • 建立:伺服器啟動針對每一個web應用建立servletcontext
  • 銷燬:伺服器關閉前先關閉代表每一個web應用的servletContext

ServletContextListener主流應用:
第一個:在伺服器啟動時,對一些物件進行初始化,並且將物件儲存ServletContext資料範圍內(因為在監聽器內可以獲得事件源物件) — 全域性資料

  • 例如:建立資料庫連線池

第二個:對框架進行初始化 例如:Spring框架初始化通過ServletContextListener (因為監聽器程式碼在伺服器啟動時執行)

  • Spring框架(配置檔案隨伺服器啟動載入) org.springframework.web.context.ContextLoaderListener

第三個:實現任務排程,啟動定時程式 (Timer、TimerTask) 使一個程式,定時執行

比如說每天晚上十二點給過生日的人進行生日祝福,中國移動對賬戶進行同步,會在伺服器使用較少的時間,例如凌晨之類,啟動一段程式,進行同步

java.util.Timer 一種執行緒設施,用於安排以後在後臺執行緒中執行的任務。可安排任務執行一次,或者定期重複執行。
Timer提供了啟動定時任務方法 schedule
* schedule(TimerTask task, Date firstTime, long period) 用來在指定一個時間啟動定時器,定期迴圈執行
* schedule(TimerTask task, long delay, long period) 用來在當前時間delay多少毫秒後啟動定時器
停止定時器,timer.cancel取消任務

2、HttpSession 資料物件建立和銷燬監聽器 —– HttpSessionListener

監聽Session物件建立
監聽Session物件銷燬

Session何時建立:request.getSession()
Session何時銷燬:關閉伺服器,Session過期,session.invalidate
*Session過期時間通過web.xml配置(tomcat配置檔案中),預設時間30分鐘

配置:

HttpSession監聽器

現有如下JSP頁面:

1.jsp

2.jsp

訪問1.jsp時會執行監聽器原因:因為如果觀察jsp的原始碼,封閉式英語培訓jsp會被預處理成.java程式碼(在tomcat中work資料夾下,參見http://blog.csdn.net/megustas_jjc/article/details/53462025),我們開啟這個.java程式碼的原始碼:

這裡寫圖片描述

其中的getSession的實現實際就是request.getSession()

3、HttpServletRequest物件的建立和銷燬監聽器 —- ServletRequestListener

—-監聽request物件建立
監聽request物件銷燬

Request何時建立:請求發起時建立
Request何時銷燬:響應結束時銷燬

例如:每次重新整理介面都會建立銷燬一次

注意(建立銷燬次數由請求次數決定):
使用forward —- request建立銷燬幾次 —– 一次
使用sendRedirect —- request建立銷燬兩次 (兩次請求)

(二)ServletContext/HttpSession/ServletRequest中儲存資料 建立、修改、移除監聽器

ServletContextAttributeListener 監聽ServletContext中屬性變化
HttpSessionAttributeListener 監聽HttpSession中屬性變化
ServletRequestAttributeListener 監聽ServletRequest中屬性變化

attributeAdded 監聽屬性新增 —- 當資料範圍物件沒有該屬性,第一次新增時呼叫執行
attributeRemoved 監聽屬性移除 —- 從一個數據範圍物件刪除一個已經存在屬性執行
attributeReplaced 監聽屬性替換 —– 當一個數據範圍已經存在一個屬性,向資料範圍新增相同名稱屬性觸發替換方法

例如,此處我們用HttpSessionAttributeListener舉例(ServletContextListener與ServletRequestListener同理):

JSP頁面

監聽器

註冊

注意:獲得返回值通過session.getAttribute(se.getName())

(三)被繫結Session物件,自我狀態感知監聽器

儲存在 Session 域中的物件可以有多種狀態:繫結到 Session 中;從 Session 域中解除繫結;隨 Session 物件持久化到一個儲存裝置中(鈍化);隨 Session 物件從一個儲存裝置中恢復(活化

被存放Session的Java物件,感知自我四種狀態變化
1、被繫結
2、被解除繫結
3、被鈍化 —– 資料從記憶體序列化硬碟
4、被活化 —- 資料從硬碟重新載入回記憶體

HttpSessionBindingListener實現介面的java物件,感知自己被繫結到Session或者從Session中解除繫結
HttpSessionActivationListener實現介面的java物件,感知從記憶體被鈍化硬碟上,雅思託福的區別從硬碟活化到記憶體中
實現這兩個介面的類不需要 web.xml 檔案中進行註冊,都是由Session自主完成的,例如在儲存物件的時候會自動呼叫繫結

HttpSessionBindingListener
* 繫結物件方法 —-
* 解除繫結方法 —–、當Session物件銷燬時,當中所有繫結物件解除繫結

JSP頁面:

HttpSessionActivationListener
* 感知物件被活化
* 感知物件被鈍化
使用場景:Session儲存資料,很長一段時間沒用,但是不能銷燬Session物件,不想佔用伺服器記憶體資源 —– 鈍化(將伺服器記憶體中資料序列化硬碟上)

JSP介面

讀取資料

注意

鈍化和活化應該由tomcat伺服器 自動進行 —- 配置tomcat

配置context有幾個位置?
1、tomcat/conf/context.xml 對所有虛擬主機 所有web工程生效
2、tomcat/conf/Catalina/localhost/context.xml 對當前虛擬主機所有web工程生效
3、當前工程/META-INF/context.xml 對當前工程有效

鈍化後 it315目錄在哪裡?在“tomcat/work/Catalina/localhost/專案名”目錄中

java物件如果想實現序列化,需要實現Serializable介面(因此上述Bean2實現Serializable介面,才可以被鈍化,並之後進行活化並讀取)