JavaWeb Listener


1. 監聽器概述

1.1. 什么是監聽器

做過Swing或者AWT圖像界面Java程序開發的話,應該對ListenerEvent非常熟悉。Swing或者AWT中通過ListenerEvent來處理事件,如鼠標事件、鍵盤事件等。先實現一個Listener接口,然后通過addListener()方法把Listener綁定到某個控件上,單機按鈕時就會調用Listener的相應方法,並傳回一個Event對象。

Java Web程序也一樣,使用ListenerEvent完成相應事件的處理。使用Listener不需要關注該類事件是怎樣觸發的或者怎么調用相應的Listener,只要記住該類事件觸發時一定會調用相應的Listener。遵循Servlet規范的服務器完成了相應的工作。開發者只要在Listener里編寫相關代碼就OK了。

1.2. 八大監聽器

Java Web一共提供了八個監聽器供使用,分別用於監聽RequestSessionServletContext等的創建與銷毀、屬性變化。這八個監聽器分別如下:

  • ServletRequestListner

Method Summary

void

requestDestroyed(ServletRequestEvent sre) 
The request is about to go out of scope of the web application.

void

requestInitialized(ServletRequestEvent sre) 
The request is about to come into scope of the web application.

  • ServletRequestAttributeListener

Method Summary

void

attributeAdded(ServletRequestAttributeEvent srae) 
Notification that a new attribute was added to the servlet request.

void

attributeRemoved(ServletRequestAttributeEvent srae) 
Notification that an existing attribute has been removed from the servlet request.

void

attributeReplaced(ServletRequestAttributeEvent srae) 
Notification that an attribute was replaced on the servlet request.

  • HttpSessionListener

Method Summary

void

sessionCreated(HttpSessionEvent se) 
Notification that a session was created.

void

sessionDestroyed(HttpSessionEvent se) 
Notification that a session is about to be invalidated.

  • HttpSessionAttributeListener

Method Summary

void

attributeAdded(HttpSessionBindingEvent se) 
Notification that an attribute has been added to a session.

void

attributeRemoved(HttpSessionBindingEvent se) 
Notification that an attribute has been removed from a session.

void

attributeReplaced(HttpSessionBindingEvent se) 
Notification that an attribute has been replaced in a session.

  • ServletContextListener

Method Summary

void

contextDestroyed(ServletContextEvent sce) 
Notification that the servlet context is about to be shut down.

void

contextInitialized(ServletContextEvent sce) 
Notification that the web application initialization process is starting.

  • ServletContextAttributeListener

Method Summary

void

attributeAdded(ServletContextAttributeEvent scab) 
Notification that a new attribute was added to the servlet context.

void

attributeRemoved(ServletContextAttributeEvent scab) 
Notification that an existing attribute has been removed from the servlet context.

void

attributeReplaced(ServletContextAttributeEvent scab) 
Notification that an attribute on the servlet context has been replaced.

  • HttpSessionBindingListener

Method Summary

void

valueBound(HttpSessionBindingEvent event) 
Notifies the object that it is being bound to a session and identifies the session.

void

valueUnbound(HttpSessionBindingEvent event) 
Notifies the object that it is being unbound from a session and identifies the session.

  • HttpSessionActivationListener

Method Summary

void

sessionDidActivate(HttpSessionEvent se) 
Notification that the session has just been activated.

void

sessionWillPassivate(HttpSessionEvent se) 
Notification that the session is about to be passivated.

1.3. 自定義監聽器

如果要自定義一個監聽器的話,需要如下幾步:

  • 創建一個自定義監聽器類,並實現上述八個監聽器中的一個或多個。
  • 配置Web工程的web.xml文件,格式如下:
<listener>
      <listener-class>自定義監聽器的完整路徑</listener-class>
</listener>

2. 創建銷毀監聽器

2.1. ServletRequestListener

ServletRequestListener用於監聽Request的創建與銷毀。用戶每次請求Request都會執行requestInitialized()方法,Request處理完畢自動銷毀前執行requestDestroyed()方法。

需要注意的是如果一個頁面內含有多個圖片等元素,則請求一次頁面可能會觸發多次Request事件。

2.2. HttpSessionListener

HttpSessionListener用於監聽Session的創建與銷毀。創建Session時執行sessionCreated()方法,銷毀SessionSession超時時執行sessionDestroyed()方法。該Listener可用於收集在線者信息。

2.3. ServletContextListener

ServletContextListener用於監聽ServletContext的創建與銷毀。服務器啟動或者部署Web應用程序時執行contextInitialized()方法,服務器關閉或關閉Web應用程序時執行contextDestroyed()方法。該Listener可用於啟動時獲取web.xml文件中配置的初始化參數。

2.4. 監聽RequestSessionServletContext

編寫一個監聽器,分別實現ServletRequestListenerHttpSessionListenerServletContextListener,並重寫上述三個接口提供的方法。

  • 編寫一個自定義監聽器。
public class ListenerTest implements ServletRequestListener, HttpSessionListener, ServletContextListener {
    /**
     * requestInitialized()用於監聽Request對象的創建.
     *  * 該方法在Request對象創建后被調用.
     */
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("客戶端向服務器端發送了一次請求......");
    }
    /**
     * requestDestroyed()用於監聽Request對象的銷毀.
     *  * 該方法在Request對象銷毀前被調用.
     */
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("客戶端的請求結束了......");
    }
    /**
     * sessionCreated()用於監聽Session對象的創建.
     *  * 該方法在Session對象創建后被調用.
     */
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("新創建了一個session......");
    }
    /**
     * sessionDestroyed()用於監聽Session對象的銷毀.
     *  * 該方法在Session對象銷毀前被調用.
 */
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("銷毀了一個session......");
    }
    /**
     * contextInitialized()用於監聽ServletContext對象的創建.
     *  * 該方法在ServletContext對象創建后被調用.
     */
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Web應用即將啟動......");
    }
    /**
     * contextDestroyed()用於監聽ServletContext對象的銷毀.
     *  * 該方法在ServletContext對象銷毀前被調用.
     */
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("Web應用即將關閉......");
    }
}
  • web.xml文件中配置自定義監聽器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <listener>
      <listener-class>app.java.listener.ListenerTest</listener-class>
  </listener>
</web-app>

3. 屬性操作監聽器

3.1. ServletRequestAttributeListener

ServletRequestAttributeListener用於監聽Request對象添加、更新和移除屬性。Request添加屬性時執行requestAdded()方法,Request對象更新屬性時執行requestReplaced()方法,Request對象移除屬性時執行requestRemoved()方法。

3.2. HttpSessionAttributeListener

HttpSessionAttributeListener用於監聽Session對象添加、更新和移除屬性。Session添加屬性時執行sessionAdded()方法,Session對象更新屬性時執行sessionReplaced()方法,Session對象移除屬性時執行sessionRemoved()方法。

3.3. ServletContextAttributeListener

ServletContextAttributeListener用於監聽ServletContext對象添加、更新和移除屬性。ServletContext添加屬性時執行contextAdded()方法,ServletContext對象更新屬性時執行contextReplaced()方法,Session對象移除屬性時執行contextRemoved()方法。

3.4. 監聽ServletRequestAttributeListenerHttpSessionAttributeListenerServletContextAttributeListener

編寫一個監聽器,分別實現ServletRequestAttributeListenerHttpSessionAttributeListenerServletContextAttributeListener,並重寫上述三個接口提供的方法。

  • 編寫一個自定義監聽器。
public class AttributeListenerTest implements ServletRequestAttributeListener, HttpSessionAttributeListener, ServletContextAttributeListener {
    /**
     * attributeAdded(ServletRequestAttributeEvent srae)用於監聽Request對象添加屬性.
     *  * 該方法在Request對象添加屬性后被調用.
     */
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("成功向Request對象添加了一個屬性......");
    }
    /**
     * attributeRemoved(ServletRequestAttributeEvent srae)用於監聽Request對象刪除屬性.
     *  * 該方法在Request對象刪除屬性前被調用.
     */
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("成功向Request對象刪除了一個屬性......");
    }
    /**
     * attributeReplaced(ServletRequestAttributeEvent srae)用於監聽Request對象更新屬性.
     *  * 該方法在Request對象更新屬性前被調用.
     */
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        System.out.println("成功向Request對象更新了一個屬性......");
    }
    /**
     * attributeAdded(HttpSessionBindingEvent se)用於監聽Session對象添加屬性.
     *  * 該方法在Session對象添加屬性后被調用.
     */
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("成功向Session對象添加了一個屬性......");
    }
    /**
     * attributeRemoved(HttpSessionBindingEvent se)用於監聽Session對象刪除屬性.
     *  * 該方法在Session對象刪除屬性前被調用.
     */
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("成功向Session對象刪除了一個屬性......");
    }
    /**
     * attributeReplaced(HttpSessionBindingEvent se)用於監聽Session對象更新屬性.
     *  * 該方法在Session對象更新屬性前被調用.
     */
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("成功向Session對象更新了一個屬性......");
    }
    /**
     * attributeAdded(ServletContextAttributeEvent scab)用於監聽ServletContex對象添加屬性.
     *  * 該方法在ServletContex對象添加屬性后被調用.
     */
    public void attributeAdded(ServletContextAttributeEvent scab) {
        System.out.println("成功向ServletContex對象添加了一個屬性......");
    }
    /**
     * attributeRemoved(ServletContextAttributeEvent scab)用於監聽ServletContex對象刪除屬性.
     *  * 該方法在ServletContex對象刪除屬性前被調用.
     */
    public void attributeRemoved(ServletContextAttributeEvent scab) {
        System.out.println("成功向ServletContex對象刪除了一個屬性......");
    }
    /**
     * attributeReplaced(ServletContextAttributeEvent scab)用於監聽ServletContex對象更新屬性.
     *  * 該方法在ServletContex對象更新屬性前被調用.
     */
    public void attributeReplaced(ServletContextAttributeEvent scab) {
        System.out.println("成功向ServletContex對象更新了一個屬性......");
    }
}
  • web.xml文件中配置自定義監聽器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <listener>
    <listener-class>app.java.listener.AttributeListenerTest</listener-class>
  </listener>
</web-app>

4. Session綁定監聽器

4.1. JavaBean感知監聽

HttpSessionBindingListener用於當JavaBean對象被放到Session里時執行valueBound()方法,當JavaBean對象從Session移除時執行valueUnBound()方法。JavaBean必須實現該Listener接口。

  • 創建一個JavaBean,實現HttpSessionBindingListener接口。

 

public class User implements HttpSessionBindingListener {
    private String name;
    private int age;
    private String job;
    public User(String name, int age, String job) {
        this.name = name;
        this.age = age;
        this.job = job;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", job=" + job + "]";
    }
    /**
     * valueBound()將該JavaBean對象放置到Session時被調用.
     */
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("該JavaBean被添加到session中......");
    }
    /**
     * valueUnbound()將該JavaBean對象從Session移除時被調用.
     */
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("該JavaBean從session中被移除......");
    }
}
  • 創建一個Servlet用於將JavaBean對象放置到Session和從Session移除。
public class BeanServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.setAttribute("user", new User("zhangwuji", 18, "jiaozhu"));
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.removeAttribute("user");
    }
}

使用HttpSessionBindingListener監聽器時,不需要配置web.xml文件。

5. Session鈍化與活化

5.1. Session序列化

所謂Session序列化就是指當Tomcat服務器關閉時Session會被保存到本地硬盤中,當Tomcat服務器啟動時Session會從本地硬盤讀取到內存中的過程。

  • 創建一個Servlet用於向Session中存放數據內容。
public class SetSessionServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.setAttribute("name", "zhangwuji");
        System.out.println("成功向session存儲了數據......");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 創建一個Servlet用於從Session中讀取存放的數據內容。
public class GetSessionServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        String name = (String) session.getAttribute("name");
        System.out.println("session中存儲的數據內容為: "+name+"......");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 發布Web工程到Tomcat服務器,並啟動Tomcat服務器。訪問向Session存儲數據的Servlet
  • 關閉Tomcat服務器,查看${CATALINA_HOME}\work\Catalina\localhost\Web工程名目錄。
  • 重新啟動Tomcat服務器,訪問從Session讀取存儲數據的Servlet

Tomcat服務器被重新啟動讀取Session內容之后,序列化到本地硬盤中的Session文件會自動銷毀。

如果想要關閉Session的序列化,可以修改Tomcat安裝目錄中conf目錄的context.xml文件。具體內容如下:

<Manager pathname=""/>

5.2. Session鈍化與活化

Session長時間不被使用時(沒有超時),將Session里的內容保存到本地硬盤中,這個過程叫做鈍化。當Session重新被使用時,將保存到本地硬盤中的Session里的內容重新讀取,這個過程叫做活化。

  • 創建一個Servlet用於向Session中存放數據內容。
public class SetSessionServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.setAttribute("name", "zhangwuji");
        System.out.println("成功向session存儲了數據......");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 創建一個Servlet用於從Session中讀取存放的數據內容。
public class GetSessionServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        String name = (String) session.getAttribute("name");
        System.out.println("session中存儲的數據內容為: "+name+"......");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
  • 修改Tomcat安裝目錄/conf目錄/ Catalina目錄/ localhost目錄中,創建一個名為Web工程名的xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- maxIdleSwap:指定多長時間后Session會被鈍化.(單位為分鍾) -->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1" >
        <!-- 
            directory:指定鈍化文件的保存目錄.
            鈍化文件保存路徑:${CATALINA_HOME}\work\Catalina\localhost\Web工程名\${sessionid}.session
        -->
        <Store className="org.apache.catalina.session.FileStore" directory="mysession" />
    </Manager>
</Context>

鈍化文件在重新被使用時,不會自動銷毀。

6. 監聽器案例

6.1. 統計在線人數

利用Java Web的監聽器技術,實現在線人數統計的案例,具體實現步驟如下:

  • 創建一個監聽器,實現ServletContextListener接口,用於初始化在線人數為0
public class OnLineCountServletContextListener implements
        ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        // 通過 事件對象,獲得事件源ServletContext
        ServletContext servletContext = sce.getServletContext();
        // 只會執行一次
        servletContext.setAttribute("onlinecount", 0);
    }
    public void contextDestroyed(ServletContextEvent sce) {}
}
  • 創建一個監聽器,實現HttpSessionListener接口,用於統計在線人數。
public class OnLineCountHttpSessionListener implements HttpSessionListener {
    public void sessionCreated(HttpSessionEvent se) {
        // 獲得ServletContext
        ServletContext servletContext = se.getSession().getServletContext();
        // 獲得原來在線人數
        int onlinecount = (Integer) servletContext.getAttribute("onlinecount");
        System.out.println(se.getSession().getId() + "在線了...");
        servletContext.setAttribute("onlinecount", onlinecount + 1);
    }
    public void sessionDestroyed(HttpSessionEvent se) {
        // 獲得ServletContext
        ServletContext servletContext = se.getSession().getServletContext();
        // 獲得原來在線人數
        int onlinecount = (Integer) servletContext.getAttribute("onlinecount");
        System.out.println(se.getSession().getId() + "離線了...");
        servletContext.setAttribute("onlinecount", onlinecount - 1);
    }
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <listener>
    <listener-class>app.java.demo.OnLineCountServletContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>app.java.demo.OnLineCountHttpSessionListener</listener-class>
  </listener>
</web-app>
  • 創建一個JSP頁面用於顯示在線人數。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>在線人數統計案例</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
    <h1>在線人數:${applicationScope.onlinecount }</h1>
  </body>
</html>
  • 發布Web工程到Tomcat服務器,並啟動Tomcat服務器。訪問對應的JSP頁面查看結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM