1. 程式人生 > >Java Web(五) 監聽器Listener

Java Web(五) 監聽器Listener

用戶 on() std 部署 ppi tin nco err create

監聽器概述

在上一篇裏介紹了過濾器Filter,而Listener是Servlet的另一個高級特性。Listener用於監聽Java Web程序中的事件,例如創建,修改,刪除Session,request,context等,並觸發相應的事件。Listener主要用於對Session,request,context等進行監控,目前共有8種Listener,分別完成對不同事件的監聽。

使用Listener不需要關註事件是怎樣觸發的或者怎麽調用相應的Listener,只要記住該類事件觸發時一定會調用相應的Listener。你只需要在Lisener裏編寫相關的代碼就可以。

Servlet3.0以前需要在web.xml中配置,之後直接用@WebListener()註解即可。

<listener>
  <listener-class>listener.TestListener</listener-class>
</listener>

監聽對象的創建與銷毀

HttpSessionListener,ServletContextListener,ServletRequestListener分別用來監控Session,context,request的創建於銷毀。觸發時機為:

  • HttpSessionListener:創建Session時執行sessionCreatedf方法,超時或者執行session.invalidate()時執行sessionDestroy方法。該Listener可用於收集在線者信息。
  • ServletContextListener:服務器啟動或者熱部署war包時執行contextInitialized方法。服務器關閉時執行contextDestroyed方法。該Listener可用於啟動時獲取web.xml裏配置的初始化參數。
  • ServletRequest:用戶每次請求時都會執行requestInitialized方法。request處理完畢自動銷毀前執行requestDestroyed方法。

實例:因為java可以繼承多個接口,所以用一個類繼承這三個接口即可。

package listener; 

/**
 * Created by kindleheart happily.
 */
import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class TestListener implements ServletContextListener, HttpSessionListener, ServletRequestListener {
    public TestListener() {
    }

    //加載context上下文時被調用
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext servletContext = sce.getServletContext();
        System.out.println("即將啟動" + servletContext.getContextPath());
    }
    //銷毀context上下文時被調用
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext servletContext = sce.getServletContext();
        System.out.println("即將關閉" + servletContext.getContextPath());
    }
    //創建Session時被調用
    public void sessionCreated(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("新創建一個Session,ID為:" + session.getId());
    }
    //銷毀Session時被調用
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("銷毀一個Session,ID為:" + session.getId());
    }
    //創建request時被調用
    public void requestInitialized(ServletRequestEvent sre) {
        //存儲創建request時的時間
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        request.setAttribute("dateCrated", System.currentTimeMillis());
    }
    //銷毀request時被調用
    public void requestDestroyed(ServletRequestEvent sre) {
        //計算該請求所需時間
        HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
        long time = System.currentTimeMillis() - (Long)request.getAttribute("dateCrated");
        System.out.println("請求處理結束,用時" + time + "毫秒");
    }

}

監聽對象屬性的變化

HttpSessionAttributeListener,ServletContextAttributeListener,ServletRequestAttributeListener分別用來監控Session,context,request的屬性變化。在向監聽對象添加,更新,移除屬性時,會分別執行xxxAdded(),xxxReplaced(),xxxRemoved()方法,xxx分別代表Session,context,request。

/**
 * Created by kindleheart happily.
 */
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;

@WebListener
public class SessionAttributeListenerTest implements HttpSessionAttributeListener {
    public SessionAttributeListenerTest() { }

    public void attributeAdded(HttpSessionBindingEvent sbe) {
        HttpSession session = sbe.getSession();
        String name= sbe.getName();    //新添加的屬性名
        System.out.println("新建Session屬性:" + name + ",值為:" + sbe.getValue());
    }

    public void attributeRemoved(HttpSessionBindingEvent sbe) {
        HttpSession session = sbe.getSession();
        String name= sbe.getName();    //即將刪除的屬性名
        System.out.println("刪除Session屬性:" + name + ",值為:" + sbe.getValue());
    }

    public void attributeReplaced(HttpSessionBindingEvent sbe) {
        HttpSession session = sbe.getSession();
        String name= sbe.getName();    //發生修改的屬性名
        Object oldValue = sbe.getValue();   //原來的屬性值
        System.out.println("修改Session屬性:" + name + ",舊值為:" + oldValue +"新值為:" + session.getAttribute(name));
    }
}

監聽Session內的對象

除了上面6種Listener,另外還有兩種Listener用於監控Session內的對象,分別是HttpSessionBindingListener與HttpSessionActivationListener。他們觸發的時機為:

  • HttpSessionBindingListener:當監聽對象與Session綁定時執行valueBound方法,解綁時執行valueUnbound方法。
  • HttpSessionActivationListener:服務器關閉時,會將Session裏的內容保存到硬盤上,這個過程稱為鈍化,執行sessionWillPassivate方法。服務器重新啟動時,會將Session內容從硬盤上重新加載,會執行sessonDidActivate方法。

案例:把User對象與Session綁定時,就會執行相應的方法。

package model;
/**
 * Created by kindleheart happily.
 */

import javax.servlet.http.*;

public class User implements HttpSessionBindingListener, HttpSessionActivationListener {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    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;
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println(this + "已經成功從硬盤加載。SessionId:" + session.getId());
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println(this + "即將保存到硬盤。SessionId:" + session.getId());
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        String name = event.getName();
        System.out.println(this + "被綁定到Session" + session.getId() + "的" + name + "屬性上");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        HttpSession session = event.getSession();
        String name = event.getName();
        System.out.println(this + "被從Session" + session.getId() + "的" + name + "屬性上移除");
    }
}

應用:統計在線人數

用戶第一次訪問服務器時,服務器會創建一個Session,用戶結束訪問時會銷毀這個Session,那麽可以使用HttpSessionListener來統計在線人數。

package util;
/**
 * Created by kindleheart happily.
 */

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener()
public class OnlineNumListener implements HttpSessionListener {
    private static int userNum = 0;

    public OnlineNumListener() {
    }

    public static int getUserNum() {
        return userNum;
    }

    public void sessionCreated(HttpSessionEvent se) {
        userNum++;
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        userNum--;
    }
}

 在主頁顯示在線人數:

<%@ page import="util.OnlineNumListener" %>
<%@page pageEncoding="utf-8" contentType="text/html; utf-8" language="java" isELIgnored="false" %>
<html>
<body>
<h2>我是主頁</h2>
<%
    int num = OnlineNumListener.getUserNum();
%>
<h3>在線人數為:</h3>><%=num%>
</body>
</html>

Java Web(五) 監聽器Listener