java中servletContextListener、httpSessionListener和servletRequestListener使用整理


在java web應用中,listener監聽器似乎是不可缺少的。經常常使用來監聽servletContext、httpSession、servletRequest等域對象的創建、銷毀以及屬性的變化等等,能夠在這些事件動作前后進行一定的邏輯處理。


比較經常使用的應用場景是利用監聽器來初始化一些數據、統計在線人數、統計web應用瀏覽量等等。


這里所說的監聽器實際上是servlet規范中定義的一種特殊類,須要實現特定的接口。
而我臨時先說當中三個用來監聽域對象的,各自是servletContextListener、httpSessionListener、servletRequestListener。
這三個接口寫法上實際是幾乎相同的。都有兩個分別代表了該域對象創建時調用和銷毀時調用的方法。據我的理解,這三個對象最大的差別應該就是作用域不一樣。


servletContext在整個應用啟動到結束中生效。啟動系統時創建這個對象,整個過程中這個對象是唯一的。
httpSession則是在一個session會話中生效,在一個session被創建直到失效的過程中都起作用,只是一個啟動的應用中httpSession對象能夠有多個,比方同一台電腦兩個瀏覽器訪問。就會創建兩個httpSession對象。
而servletRequest是在一個request請求被創建和銷毀的過程中生效,每發起一次請求就會創建一個新的servletRequest對象,比方刷新瀏覽器頁面、點擊應用的內鏈等等。
這三個監聽器的寫法基本例如以下偽代碼所看到的:
首先創建一個監聽器類實現對應的接口及方法:

package packageName;
public class ListenerName implements *Listener {

    @Override
    public void 對象創建時被調用的方法(對應的事件 arg0) {

    }

    @Override
    public void 對象銷毀時被調用的方法(對應的事件 arg0) {

    }
}

然后在web.xml中注冊:

 <listener>
    <listener-class>packageName.ListenerName</listener-class>
  </listener>

到這里,基本上這個監聽器在啟動web服務器以后就能夠正常跑了,僅僅是有時候我們還會在注冊監聽器的時候配置一些其它的。
比方配置servletContextListener的時候,可能會加上context-param參數:

<context-param>
     <param-name>paramName</param-name>
     <param-value>paramValue</param-value>
</context-param>

配置httpSessionListener的時候,可能會加上session超時:

<session-config>
     <session-timeout>1</session-timeout>
</session-config>

我感覺經過這樣一整理后,就會發現起始監聽器寫起來還是非常easy的。於是便模擬簡單的實現了在線用戶統計和應用訪問量,基本代碼例如以下:
首先是實現了servletContext

package webTest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ListenerTest1 implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {

        System.out.println("contextDestroyed" + "," + new Date());
        Object count = arg0.getServletContext().getAttribute("count");
        File file = new File("count.txt");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            bufferedWriter.write(count.toString());
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("contextInitialized" + "," + new Date());
        File file = new File("count.txt");
        if (file.exists()) {
            try {
                FileInputStream fileInputStream = new FileInputStream(file);
                InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
                BufferedReader bReader = new BufferedReader(inputStreamReader);
                String count = bReader.readLine();
                System.out.println("歷史訪問次數:" + count);
                arg0.getServletContext().setAttribute("count", count);
                bReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

這里我把訪問次數存在一個txt文件里。以便於持久化保存。當項目啟動的時候。也就是創建servletContext對象的時候調用載入方法。從txt文件里讀取歷史訪問量,然后使用setAttribute方法把這個數據存入到內存中。
之后當應用被關閉,servletContext對象被銷毀的時候把內存中新的訪問量數據覆蓋寫入到txt文件。以便於下次啟動應用后繼續讀取之前的訪問量。
然后使用servletRequestListener來實現web瀏覽量的變化,當然了。這里僅僅是簡單的實現,假設是要實現那種同一個用戶刷新頁面不添加瀏覽量的功能,還須要做很多其它的處理。

package webTest;
import java.util.Date;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class ListenerTest3 implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent arg0) {
        System.out.println("requestDestroyed" + "," + new Date());
        System.out.println("當前訪問次數:" + arg0.getServletContext().getAttribute("count"));
    }

    @Override
    public void requestInitialized(ServletRequestEvent arg0) {
        System.out.println("requestInitialized" + "," + new Date());
        Object count = arg0.getServletContext().getAttribute("count");
        Integer cInteger = 0;
        if (count != null) {
            cInteger = Integer.valueOf(count.toString());
        }
        System.out.println("歷史訪問次數::" + count);
        cInteger++;
        arg0.getServletContext().setAttribute("count", cInteger);
    }

}

這里相同是兩個方法,在servletRequest對象被建立的時候調用初始化方法。從內存中讀取servletContext對象的count屬性,而后輸出歷史訪問量。


同一時候在此基礎上加一又一次設置servletContext對象的count屬性的內容。當servletRequest對象被銷毀的時候調用銷毀時的方法打印出當前瀏覽量。這樣就簡單的實現了web瀏覽的量的累加計數。
然后就是利用httpSessionListener來實如今線人數的統計:

package webTest;
import java.util.Date;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class ListenerTest2 implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
        System.out.println("sessionCreated" + "," + new Date());
        Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
        Integer count = 0;
        if (lineCount == null) {
            lineCount = "0";
        }
        count = Integer.valueOf(lineCount.toString());
        count++;
        System.out.println("新上線一人,歷史在線人數:" + lineCount + "個,當前在線人數有: " + count + " 個");
        arg0.getSession().getServletContext().setAttribute("lineCount", count);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {
        System.out.println("sessionDestroyed" + "," + new Date());
        Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
        Integer count = Integer.valueOf(lineCount.toString());
        count--;
        System.out.println("一人下線,歷史在線人數:" + lineCount + "個。當前在線人數: " + count + " 個");
        arg0.getSession().getServletContext().setAttribute("lineCount", count);
    }

}

這里的代碼都非常easy。我想應該沒有太多必要解釋,須要說明的是。我這里把lineCount存放在servletContext對象中並非唯一的方式,有興趣的朋友能夠嘗試其它的方式。比如使用類屬性。


這里的演示樣例也已打包上傳。須要的朋友能夠自行下載執行。


鏈接:http://pan.baidu.com/s/1bZ2vx0
password:ekb9

csdn下載:http://download.csdn.net/detail/tuzongxun/9761166


免責聲明!

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



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