在Servlet技術中已經定義了一些事件,並且我們可以針對這些事件來編寫相關的事件監聽器,從而對事件作出相應處理。Servlet事件主要有3類:Servlet上下文事件、會話事件與請求事件。下面具體講解這3類事件的監聽器實現。
1.對Servlet上下文進行監聽
可以監聽ServletContext對象的建立和刪除以及屬性的添加、刪除和修改等操作。該監聽器需要使用到如下兩個介面類:
● ServletContextAttributeListener:監聽對ServletContext屬性的操作,如增加、刪除、修改操作。
● ServletContextListener:監聽ServletContext,當建立ServletContext時,激發contextInitialized (ServletContextEvent sce)方法;當銷毀ServletContext時,激發contextDestroyed(ServletContext- Event sce)方法。
2.監聽Http會話
可以監聽Http會話活動情況、Http會話中屬性設定情況,也可以監聽Http會話的active、paasivate情況等。該監聽器需要使用到如下多個介面類:
● HttpSessionListener:監聽HttpSession的操作。當建立一個Session時,激發session Created (SessionEvent se)方法;當銷毀一個Session時,激發sessionDestroyed (HttpSessionEvent se) 方法。
● HttpSessionActivationListener:用於監聽Http會話active、passivate情況。
● HttpSessionAttributeListener:監聽HttpSession中屬性的操作。當在Session增加一個屬性時,激發attributeAdded(HttpSessionBindingEvent se) 方法;當在Session刪除一個屬性時,激發attributeRemoved(HttpSessionBindingEvent se)方法;在Session屬性被重新設定時,激發attributeReplaced(HttpSessionBindingEvent
se) 方法。
3.對用戶端請求進行監聽
對用戶端的請求進行監聽是在Servlet 2.4規範中新添加的一項技術,使用的介面類如下:
● ServletRequestListener介面類。
● ServletRequestAttrubuteListener介面類。
Servlet上下文監聽器執行個體
下面編寫一個執行個體,使它能夠對ServletContext以及屬性進行監聽。由以上介紹可知,該類需要實現ServletContextAttributeListener和ServletContextListener介面類,其詳細代碼如下:
package servlet;import java.io.FileOutputStream;import java.io.PrintWriter;import javax.servlet.ServletContext;import javax.servlet.ServletContextAttributeEvent;import javax.servlet.ServletContextAttributeListener;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;public class MyServletContextListener implements ServletContextListener,ServletContextAttributeListener{ private ServletContext context = null; //定義一個ServletContext物件變數,賦為null public void contextInitialized(ServletContextEvent s) { //TODO 該方法實現了ServletContextListener介面定義的方法,對ServletContext進行初始化 this.context = s.getServletContext(); //初始化一個ServletContext對象 print("ServletContext初始化......"); //列印出該方法的操作資訊 } public void contextDestroyed(ServletContextEvent s) { //TODO 該方法實現了ServletContextListener介面類定義方法,用於釋放ServletContext對象 this.context = null; print("ServletContext被釋放......"); } public void attributeAdded(ServletContextAttributeEvent sa) { //TODO 當上下文添加屬性時,將調用該方法。這裡只是將添加的屬性資訊列印出來 print("增加ServletContext對象的一個屬性:attributeAdded('"+sa.getName()+"',' "+sa.getValue()+"')"); } public void attributeRemoved(ServletContextAttributeEvent sa) { //TODO 當把ServletContext中的某個屬性刪除時,調用該方法 print("刪除ServletContext對象的某一個屬性:attributeRemoved(' "+sa.getName()+"','")"); } public void attributeReplaced(ServletContextAttributeEvent sa) { //TODO 當上下文進行屬性值更新時,將調用該方法 print("更改ServletContext對象的某一個屬性:attributeReplaced(' "+sa.getName()+"','"+sa.getValue()+"')"); } private void print(String message){ //調用該方法在txt檔案中列印出message字串資訊 PrintWriter out = null; try{ out = new PrintWriter(new FileOutputStream("D:\\output.txt",true)); out.println(new java.util.Date().toLocaleString()+" ContextListener: "+message); out.close(); } catch(Exception e) { e.printStackTrace(); } }}
程式說明:該監聽器類實現了ServletContextAttributeListener和ServletContextListener兩個介面類中的5個方法:
● contextInitialized(ServletContextEvent s)方法用來初始化ServletContext對象。
● contextDestroyed(ServletContextEvent s)方法在上下文中刪除某個屬性時調用。
● attributeAdded(ServletContextAttributeEvent sa)方法在上下文中添加一個新的屬性時調用。
● attributeReplaced(ServletContextAttributeEvent sa)方法在更新屬性時調用。
● attributeRemoved(ServletContextAttributeEvent sa)方法在上下文中刪除某個屬性時會被調用。
在使用這個監聽器之前還需要在Web模組中的web.xml設定檔中進行聲明,代碼如下:
<listener><listener-class>servlet.MyServletContextListener</listener-class></listener>
接下來就編寫JSP程式來操作ServletContext的屬性,看看監聽器程式作出什麼反應,該JSP的一段代碼如下:
<%out.println(“Test ServletContextListener”);application.setAttribute(“userid”,”zzb”); //添加一個屬性application.setAttribute(“userid”,”zzb2”); //替換掉已經添加的屬性application.removeAttribute(“userid”); //刪除該屬性%>
代碼說明:當第一次添加屬性userid時,監聽器調用contextInitialized(ServletContextEvent s)初始化監聽方法和attributeAdded(ServletContextAttributeEvent sa)添加屬性監聽方法。
可以查看D根目錄下的output.txt檔案內容,如下:
2006-7-12 14:07:50 ContextListener: ServletContext初始化......
2006-7-12 14:13:55 ContextListener: 增加ServletContext對象的一個屬性:attributeAdded('userid','zzb')
2006-7-12 14:13:55 ContextListener: 更改ServletContext對象的某一個屬性:attributeReplaced ('userid','zzb2')
2006-7-12 14:13:55 ContextListener: 刪除ServletContext對象的某一個屬性:attributeRemoved ('userid')
該log檔案記錄了監聽器所做的動作。
12.2.2 Http會話監聽器執行個體
通過上一個監聽器執行個體,讀者應該對監聽器的實現過程有所瞭解,本小節將要介紹基於Http會話的監聽器。首先建立監聽器類MySessionListener.java,其原始碼如下:
package servlet;import java.io.FileOutputStream;import java.io.PrintWriter;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.http.HttpSessionActivationListener;import javax.servlet.http.HttpSessionAttributeListener;import javax.servlet.http.HttpSessionBindingEvent;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;public class MySessionListener implements HttpSessionActivationListener,HttpSessionAttributeListener, HttpSessionListener,ServletContextListener{ ServletContext context = null; int users = 0; public void sessionWillPassivate(HttpSessionEvent arg0) { //監聽Http會話的passivate情況 print("sessionWillPassivate("+arg0.getSession().getId()+")"); } public void sessionDidActivate(HttpSessionEvent arg0) { //監聽Http會話的active情況 print("sessionDidActivate("+arg0.getSession().getId()+")"); } public void attributeAdded(HttpSessionBindingEvent arg0) { //監聽Http會話中的屬性添加 print("attributeAdded('"+arg0.getSession().getId()+"','"+arg0.getName()+"','"+arg0.getValue()+"')"); } public void attributeRemoved(HttpSessionBindingEvent arg0) { //監聽Http會話中的屬性刪除 print("attributeRemoved('"+arg0.getSession().getId()+"','"+arg0.getName()+"','"+arg0.getValue()+"')"); } public void attributeReplaced(HttpSessionBindingEvent arg0) { //監聽Http會話中的屬性更改操作 print("attributeReplaced('"+arg0.getSession().getId()+"','"+arg0.getName()+"','"+arg0.getValue()+"')"); } public void sessionCreated(HttpSessionEvent arg0) { //Http會話的建立監聽 users++; //建立一個會話,把users變數加1 print("sessionCreated('"+arg0.getSession().getId()+"'),目前擁有"+users+"個使用者"); context.setAttribute("users",new Integer(users)); //把會話數設定到ServletContext的屬性users中 } public void sessionDestroyed(HttpSessionEvent arg0) { //Http會話的釋放監聽 users--; //釋放一個會話,把users變數減1 print("sessionDestroyed('"+arg0.getSession().getId()+"'),目前擁有"+users+"個使用者"); context.setAttribute("users",new Integer(users)); //把會話數設定到ServletContext的屬性users中 } public void contextInitialized(ServletContextEvent arg0) { //該方法實現了ServletContextListener介面定義的方法,對ServletContext進行初始化 this.context = arg0.getServletContext(); //初始化ServletContext對象 print("ServletContext初始化......"); //列印出該方法的操作資訊 } public void contextDestroyed(ServletContextEvent arg0) { //監聽Servlet上下文被釋放 this.context = null; //釋放ServletContext對象 print("ServletContext被釋放......"); //列印出該方法的操作資訊 } private void print(String message){ //調用該方法在txt檔案中列印出message字串資訊 PrintWriter out = null; try{ out = new PrintWriter(new FileOutputStream("d:\\output.txt",true)); out.println(new java.util.Date().toLocaleString()+" SessionListener: "+message); out.close(); } catch(Exception e) { e.printStackTrace(); } }}
程式說明:
(1)該程式實現了HttpSessionListener介面類中的兩個方法:
● sessionCreated(HttpSessionEvent arg0)方法進行Http會話建立的監聽,如果Http會話被建立將調用該方法。
● sessionDestroyed(HttpSessionEvent arg0)方法對Http會話銷毀進行監聽,如果某個Http會話被釋放將調用該方法。
(2)實現HttpSessionActivationListener介面類中的如下兩個方法:
● sessionDidActivate(HttpSessionEvent arg0)方法對Http會話處於active情況進行監聽。
● sessionWillPassivate(HttpSessionEvent arg0)方法對Http會話處於passivate情況進行監聽。
(3)實現HttpSessionAttributeListener介面類中的如下3種方法:
● attributeAdded(HttpSessionBindingEvent arg0)方法對Http會話中屬性添加進行監聽。
● attributeReplaced(HttpSessionBindingEvent arg0)方法對Http會話中屬性修改進行監聽。
● attributeRemoved(HttpSessionBindingEvent arg0)方法對Http會話中屬性刪除進行監聽。
(4)另外,該程式中還實現了ServletContextListener介面類,該類的實現方法已經在12.2.1小節中有所介紹。
同樣需要在web.xml設定檔進行該監聽器的聲明,配置方法如12.2.1小節介紹。該監聽器實現了線上會話人數的統計,當一個會話建立時,users變數將加1;當銷毀一個會話對象的時候,users變數將減1。
下面建立測試的JSP頁面程式,代碼如下:
<%out.println("Test SessionListener");session.setAttribute("username","zzb1"); //在Http會話中設定一個使用者username屬性session.setAttribute("username","zzb2"); //修改之上添加的username屬性session.removeAttribute("username"); //刪除建立的username屬性session.invalidate(); //passivate Http會話%>
執行效果可以查看output.txt文檔內容,如下:
2006-7-12 15:24:47 SessionListener: ServletContext初始化......
2006-7-12 15:25:47 SessionListener: sessionCreated('720C4654847ECE025DF6A8AF09117212'),目前擁有1個使用者
2006-7-12 15:25:47 SessionListener:
attributeAdded('720C4654847ECE025DF6A8AF09117212','username','zzb1')
2006-7-12 15:25:47 SessionListener:
attributeReplaced('720C4654847ECE025DF6A8AF09117212','username','zzb1')
2006-7-12 15:25:47 SessionListener:
attributeRemoved('720C4654847ECE025DF6A8AF09117212','username','zzb2')
2006-7-12 15:25:47 SessionListener: sessionDestroyed('720C4654847ECE025DF6A8AF09117212'),目前擁有0個使用者
12.2.3 用戶端請求監聽器執行個體
對用戶端請求進行監聽的技術是在Servlet 2.4版本之後才出現的。一旦監聽程式能夠獲得用戶端請求,就可以對所有用戶端請求進行統一處理。例如,一個Web程式如果在本機訪問,就可以不登入,如果是遠端存取,即需要登入。這是通過監聽用戶端請求,從請求中擷取到用戶端地址,並通過地址來作出相應的處理。
實現用戶端請求監聽的程式碼如下: