Servlet 5 監聽

監聽

    監聽: 對某一些操作進行監視,那麼就稱爲監聽

    在web 中的監聽主要的功能是永遠對ServletContext、Session、Request進行監聽的一種操作



1、對application 進行監聽

      Application是Servlet 進行監聽接口的對象,表示的是整個上下午的環境

      如果要想實現對application 監聽則可以使用如下兩個接口

      ServletContextListener 是對整個上下文環境的監控

      ServletContextAttributeListener  對屬性的監聽

  1. package org.gz.servlet.listener;  
  2. import javax.servlet.*;  
  3.   
  4. public class ServletContextListener implements ServleContextListener {  
  5.     public void contextInitialized(ServletContextEvent event) {  
  6.         System.out.println("========容器初始化--->" + event.getServletContext().getContextPath());  
  7.     }  
  8.     public void contextDestroyed(ServletContextEvent event) {  
  9.         System.out.println("=====容器銷燬 ----->"+ event.getServletContext().getContextPath());  
  10.     }  
  11. }  
    此時的監聽操作只是做了一個簡單的輸出

過濾器: <filter> 、<filter-mapping>

但是現在的監聽器就省事了,直接編寫<listener>

    如果現在一個web.xml文件之中包含簡單Servlet 、過濾器、監聽器,則建議的縮寫配置的順序

     <filter>

     <filter-mapping>

     <listener>

     <servlet>

     <servlet-mapping>

     監聽器的配置

  1. <listener>  
  2.         <listener-class>  
  3.             org.gz.servlet.listener.ServletContextListenerdemo  
  4.         </listener-class>  
  5.     </listener  
         只要是容器的啓動和關閉都要觸發這些操作

         還可以實現 ServletContextAttributeListener 接口,此接口可以直接對屬性監聽

  1. package org.gz.servlet.listener.attribute;  
  2. import javax.servlet.*;  
  3.   
  4. public class ServletContextAttributeListenerdemo implements ServletContextAttributeListener {  
  5.     public void attributeAdded(ServletContextAttributeEvent scab) {  
  6.         System.out.println("增加屬性名稱--》" + scab.getName() + " ,屬性內容————》" + scab.getValue());  
  7.     }  
  8.     public void attributeRemoved(ServletContextAttributeEvent scab) {  
  9.         System.out.println("刪除屬性名稱--》" + scab.getName() + " ,屬性內容————》" + scab.getValue());  
  10.     }  
  11.     public void attributeReplaced(ServletContextAttributeEvent scab) {  
  12.         System.out.println("替換屬性名稱--》" + scab.getName() + " ,屬性內容————》" + scab.getValue());  
  13.     }  
  14. }  
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2.   
  3. <html>  
  4. <head> <title>歡迎光臨</title>  
  5. </head>  
  6. <body>  
  7. <%  
  8.     this.getServletContext().setAttribute("info","www.baidu.com");  
  9. %>  
  10. </body>  
  11. </html>  
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2.   
  3. <html>  
  4. <head> <title>歡迎光臨</title>  
  5. </head>  
  6. <body>  
  7. <%  
  8.     this.getServletContext().removeAttribute("info");  
  9. %>  
  10. </body>  
  11. </html>  

      監聽器就是實現接口,覆寫方法, 實際上這個與SWING中的操作都是非常類似的


2、對session 監聽

在監聽器中,針對於session的監聽操作提供了三個接口:

      HttpSessionListener

      HttpSessionAttributeListener

      HttpSessionBindingListener

      Session 屬於HTTP協議的範疇,所以這些接口肯定在javax.servlet.http 包中定義的。

      在Servlet中如果要想取得session 依靠HttpServletRequest 接口中的getSession()方法

  1. package org.gz.servlet.sesssionlistener;  
  2. import javax.servlet.http.*;  
  3. //  org.gz.servlet.sesssionlistener.HttpSessionListenerDemo  
  4. public class HttpSessionListenerDemo implements HttpSessionListener {  
  5.     public void sessionCreated(HttpSessionEvent se) {  
  6.         System.out.println("session創建,SESSION ID= " + se.getSession().getId());  
  7.     }  
  8.     public void sessionDestroyed(HttpSessionEvent se) {  
  9.                 System.out.println("session銷燬,SESSION ID= " + se.getSession().getId());  
  10.     }  
  11. }  
  12. /* 
  13.     <listener> 
  14.         <listener-class> 
  15.             org.gz.servlet.sesssionlistener.HttpSessionListenerDemo 
  16.         </listener-class> 
  17.     </listener> 
  18.  
  19.  
  20. */  
    在講解內置對象的時候一直強調,當客戶端第一次連接到服務器上的時候服務器將會自動爲用戶創建一個新的session , 同時會分配一個新的 session id。

    現在session 已經被創建,在第一次訪問的時候觸發了事件,可是還有一點,什麼時候銷燬呢?

     如果現在想要讓一個session 銷燬的化,有兩種方法,但是這兩種方法並不是直接關閉服務器就可以實現的:

            session註銷: invalidate()

           超時時間到了, 在tomcat中一般的超時時間是30 分鐘。

  1. //D:\java rj\web\tomcat-6.0.18\conf\web.xml  
  2.   
  3.    <session-config>  
  4.         <session-timeout>30</session-timeout>  
  5.     </session-config>  
       當然: 也可以根據自己的情況修改,例如:將本想買中的超時時間修改爲1 分鐘
  1. //  E:\webdemo\WEB-INF\web.xml  
  2.      
  3. <session-config>  
  4.         <session-timeout>1</session-timeout>  
  5.     </session-config>  
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2.   
  3. <html>  
  4. <head> <title>歡迎光臨</title>  
  5. </head>  
  6. <body>  
  7. <%  
  8.     // 手工註銷  
  9.     session.invalidate();  
  10. %>  
  11. </body>  
  12. </html>  

     之前一直強調,當調用invalidate() 方法的時候就意味着 session 的內容將被清空

      不過一般的銷燬時間都是設置在30 分鐘或更長的時間,如果時間保存長也就意味着佔用空間的時間就長


  1. package org.gz.servlet.attributelistener;  
  2. import javax.servlet.http.*;  
  3. //   org.gz.servlet.attributelistener.HttpSessionAttributeListenerdemo   
  4. public class HttpSessionAttributeListenerdemo implements HttpSessionAttributeListener {  
  5.         public void attributeAdded(HttpSessionBindingEvent se) {  
  6.             System.out.println(se.getSession().getId() + " ,增加屬性--->名稱: " +  
  7.                 se.getName() + ", 屬性內容: " + se.getValue() );  
  8.         }  
  9.         public void attributeRemoved(HttpSessionBindingEvent se) {  
  10.             System.out.println(se.getSession().getId() + " ,刪除屬性--->名稱: " +  
  11.                 se.getName() + ", 屬性內容: " + se.getValue() );  
  12.         }  
  13.         public void attributeReplaced(HttpSessionBindingEvent se) {  
  14.             System.out.println(se.getSession().getId() + " ,替換屬性--->名稱: " +  
  15.                 se.getName() + ", 屬性內容: " + se.getValue() );  
  16.         }  
  17. }  
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2.   
  3. <html>  
  4. <head> <title>歡迎光臨</title>  
  5. </head>  
  6. <body>  
  7. <%  
  8.     // 手工註銷  
  9.     session.removeAttribute("info");  
  10. %>  
  11. </body>  
  12. </html>  
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2.   
  3. <html>  
  4. <head> <title>歡迎光臨</title>  
  5. </head>  
  6. <body>  
  7. <%  
  8.     // 手工註銷  
  9.     session.setAttribute("info","www.baidu.com");  
  10. %>  
  11. </body>  
  12. </html>  
    
  1. package org.gz.servlet.bindinglistener;  
  2. import javax.servlet.http.*;  
  3. //  org.gz.servlet.bindinglistener.HttpSessionBindingListenerdemo  
  4. public class HttpSessionBindingListenerdemo implements HttpSessionBindingListener {  
  5.     private String name;  
  6.     public HttpSessionBindingListenerdemo (String name) {  
  7.         this.name = name;  
  8.     }  
  9.       
  10.     public void valueBound(HttpSessionBindingEvent event) {  
  11.         System.out.println("在session中保存HttpSessionBindingListenerdemo 對象(name =  "  
  12.             + this.getName() + " ) , session id = " + event.getSession().getId());  
  13.     }  
  14.     public void valueUnbound(HttpSessionBindingEvent event) {  
  15.         System.out.println("在session中移除HttpSessionBindingListenerdemo 對象(name =  "  
  16.             + this.getName() + " ) , session id = " + event.getSession().getId());  
  17.     }  
  18.     public String getName() {  
  19.         return this.name;  
  20.     }  
  21.     public void setName(String name){  
  22.         this.name = name;  
  23.     }  
  24. }  
  25. /* 
  26.     此處根本就不需要任何配置文件的支持 
  27. */  
  1. <%@ page contentType="text/html" pageEncoding="GBK"%>  
  2. <%@ page import="org.gz.servlet.bindinglistener.*"%>  
  3. <html>  
  4. <head> <title>歡迎光臨</title>  
  5. </head>  
  6. <body>  
  7. <%  
  8.     //由於此處需要手工綁定,所以纔不需要做任何額外的配置  移除 session.removeAttribute("info");  
  9.     HttpSessionBindingListenerdemo binding = new HttpSessionBindingListenerdemo("gz");  
  10.     session.setAttribute("info",binding);  //直接保存 HttpSessionBindingListenerdemo 對象  
  11. %>  
  12. </body>  
  13. </html>  

3、對request監聽

在Servlet 2.4 之後增加了對request 操作的監聽,主要使用 ServletRequestListener、 ServletRequestAttributeListener 兩個接口

  1. package org.gz.servlet.reqestlistener;  
  2. import javax.servlet.*;  
  3.   
  4. public class ServletRequestListenerdemo implements ServletRequestListener {  
  5.       
  6.     public void requestInitialized(ServletRequestEvent sre) {  
  7.         System.out.println("request 初始化 http://" +   
  8.             sre.getServletRequest().getRemoteAddr() +  
  9.             sre.getServletContext().getContextPath());  
  10.     }  
  11.     public void requestDestroyed(ServletRequestEvent sre) {  
  12.         System.out.println("request 銷燬 http://" +   
  13.             sre.getServletRequest().getRemoteAddr() +  
  14.             sre.getServletContext().getContextPath());  
  15.     }   
  16. }  
  1. package org.gz.servlet.reqestattributelistener;  
  2. import javax.servlet.*;  
  3. public class ServletRequestAttributeListenerdemo implements ServletRequestAttributeListener {  
  4.     public void attributeAdded(ServletRequestAttributeEvent srae) {  
  5.         System.out.println("增加request屬性-->屬性名稱: " + srae.getName() + ",屬性內容:   " + srae.getValue());  
  6.     }  
  7.     public void attributeRemoved(ServletRequestAttributeEvent srae) {  
  8.         System.out.println("刪除request屬性-->屬性名稱: " + srae.getName() + ",屬性內容:   " + srae.getValue());  
  9.     }  
  10.     public void attributeReplaced(ServletRequestAttributeEvent srae) {  
  11.         System.out.println("替換request屬性-->屬性名稱: " + srae.getName() + ",屬性內容:   " + srae.getValue());  
  12.       
  13.     }  
  14. }  
  15.   
  16. /* 
  17.  
  18. <%@ page contentType="text/html" pageEncoding="GBK"%> 
  19. <%@ page import="org.gz.servlet.bindinglistener.*"%> 
  20. <html> 
  21. <head> <title>歡迎光臨</title> 
  22. </head> 
  23. <body> 
  24. <% 
  25.     request.setAttribute("info","www.baidu.com"); 
  26.     //request.setAttribute("info","www.baidu.com");  //將出現替換 
  27.     request.removeAttribute("info"); 
  28. %> 
  29. </body> 
  30. </html> 
  31.  
  32.     <listener> 
  33.         <listener-class> 
  34.             org.gz.servlet.reqestattributelistener.ServletRequestAttributeListenerdemo 
  35.         </listener-class> 
  36.     </listener> 
  37.  
  38. */  

       從實際來講,對request 範圍的監聽操作並不是很常見的,用的最多的還是ServletContext、HttpSession監聽

4、監聽器的實例

     經常會在各個站點上看見一些在線人員的列表操作,實際上次操作就可以通過監聽完成

  

         在整個的操作中,需要使用以下幾個接口 :

         所有的人員列表應該用集合保存,但是這個集合所有的用戶都可以看見,而且以後也要操作,

那麼證明在整個監聽中必然需要有一個 application 對象保存

        用戶登錄成功,增加屬性,肯定要在屬性監聽接口中使用

       當用戶離開之後,


  1. package org.gz.servlet.context;  
  2. import java.util.*;  
  3. import javax.servlet.*;  
  4. import javax.servlet.http.*;  
  5.   
  6. //  org.gz.servlet.context.OnlineUserList  
  7. public class OnlineUserList implements ServletContextListener,HttpSessionAttributeListener,HttpSessionListener {  
  8.     private ServletContext app = null;  
  9.       
  10.     //ServletContextListener  
  11.     public void contextInitialized(ServletContextEvent sce) {  
  12.         this.app = sce.getServletContext();  //初始化  
  13.         this.app.setAttribute("online",new TreeSet());  //設置內容,準備集合  TreeSet 按照 Comparable  二分法排序  
  14.     }  
  15.   
  16.     public void contextDestroyed(ServletContextEvent sce) { }  
  17.     // HttpSessionAttributeList   
  18.     public void attributeAdded(HttpSessionBindingEvent se) {  
  19.         Set all = (Set) this.app.getAttribute("online");    // 取出屬性集合  
  20.         all.add(se.getValue());    // 保存屬性名字  
  21.         this.app.setAttribute("online",all);  // 重新設置回去  
  22.     }  
  23.     public void attributeRemoved(HttpSessionBindingEvent se) {  
  24.         Set all = (Set) this.app.getAttribute("online");  
  25.         all.remove(se.getSession().getAttribute("userid"));     //用戶離開刪除  
  26.         this.app.setAttribute("online",all);  
  27.     }  
  28.     public void attributeReplaced(HttpSessionBindingEvent se) { }  
  29.   
  30.     //  HttpSessionListener  
  31.     public void sessionCreated(HttpSessionEvent se) { }   
  32.     public void sessionDestroyed(HttpSessionEvent se) {  
  33.         Set all = (Set) this.app.getAttribute("online");  
  34.         all.remove(se.getSession().getAttribute("userid"));     //用戶離開刪除  沒有getValue()這個方法  
  35.         this.app.setAttribute("online",all);  //操作完了之後重新放回集合之中  
  36.     }  
  37. }  
  38. /* 
  39.  
  40. <%@ page contentType="text/html" pageEncoding="GBK"%> 
  41.  
  42. <html> 
  43. <head> <title>歡迎光臨</title> 
  44. </head> 
  45. <% 
  46.     request.setCharacterEncoding("GBK"); 
  47. %> 
  48. <body> 
  49. <form action="online_listener.jsp" method="post"> 
  50.     用戶ID: <input type="text" name="userid"> 
  51.     <input type="submit" value="登錄"> 
  52. </form> 
  53. <% 
  54.     String userid = request.getParameter("userid"); 
  55.     if(!(userid == null || "".equals(userid)))  { //userid 不爲空 
  56.         session.setAttribute("userid",userid); 
  57.         response.sendRedirect("online_list.jsp"); 
  58.     } 
  59. %> 
  60. </body> 
  61. </html> 
  62.  
  63.  
  64. <%@ page contentType="text/html" pageEncoding="GBK"%> 
  65. <%@ page import="java.util.*"%> 
  66. <html> 
  67. <head> <title>歡迎光臨</title> 
  68. </head> 
  69. <body> 
  70. <% 
  71.     Set all = (Set)this.getServletContext().getAttribute("online"); 
  72.     Iterator iter = all.iterator(); 
  73.     while(iter.hasNext()) { 
  74. %> 
  75.         <h3><%=iter.next()%></h3> 
  76. <% 
  77.     } 
  78. %> 
  79. </body> 
  80. </html> 
  81.  
  82.  
  83.  
  84.  
  85. */  
  86.   
  87.   
  88.   
  89. /* 
  90.     <listener> 
  91.         <listener-class> 
  92.             org.gz.servlet.context.OnlineUserList 
  93.         </listener-class> 
  94.     </listener> 
  95.     <session-config> 
  96.         <session-timeout>1</session-timeout> 
  97.     </session-config> 
  98.  
  99.  
  100. E:\webdemo\WEB-INF\classes>javac -d . *.java 
  101. 注意:OnlineUserList.java 使用了未經檢查或不安全的操作。 
  102. 注意:要了解詳細信息,請使用 -Xlint:unchecked 重新編譯。 (編譯出現這樣的情況是由於List集合沒有加泛型) 
  103.  
  104. */  

使用監聽器可以對application 、session、request 的屬性範圍進行監聽

在web 中可以配置每一個session 的超時時間


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章