一、 Servlet的會話管理機制
根據(jù)設(shè)計,HTTP是一種無狀態(tài)的協(xié)議。它意味著Web應(yīng)用并不了解有關(guān)同一用戶以前請求的信息。維持會話狀態(tài)信息的方法之一是使用Servlet或者JSP容器提供的會話跟蹤功能。Servlet API規(guī)范定義了一個簡單的HttpSession接口,通過它我們可以方便地實現(xiàn)會話跟蹤。
HttpSession接口提供了存儲和返回標(biāo)準(zhǔn)會話屬性的方法。標(biāo)準(zhǔn)會話屬性如會話標(biāo)識符、應(yīng)用數(shù)據(jù)等,都以“名字-值”對的形式保存。簡而言之,HttpSession接口提供了一種把對象保存到內(nèi)存、在同一用戶的后繼請求中提取這些對象的標(biāo)準(zhǔn)辦法。在會話中保存數(shù)據(jù)的方法是setAttribute(String s, Object o),從會話提取原來所保存對象的方法是getAttribute(String s)。
每當(dāng)新用戶請求一個使用了HttpSession對象的JSP頁面,JSP容器除了發(fā)回應(yīng)答頁面之外,它還要向瀏覽器發(fā)送一個特殊的數(shù)字。這個特殊的數(shù)字稱為“會話標(biāo)識符”,它是一個唯一的用戶標(biāo)識符。此后,HttpSession對象就駐留在內(nèi)存之中,等待同一用戶返回時再次調(diào)用它的方法。
在客戶端,瀏覽器保存會話標(biāo)識符,并在每一個后繼請求中把這個會話標(biāo)識符發(fā)送給服務(wù)器。會話標(biāo)識符告訴JSP容器當(dāng)前請求不是用戶發(fā)出的第一個請求,服務(wù)器以前已經(jīng)為該用戶創(chuàng)建了HttpSession對象。此時,JSP容器不再為用戶創(chuàng)建新的HttpSession對象,而是尋找具有相同會話標(biāo)識符的HttpSession對象,然后建立該HttpSession對象和當(dāng)前請求的關(guān)聯(lián)。
會話標(biāo)識符以Cookie的形式在服務(wù)器和瀏覽器之間傳送。如果客戶端不支持cookie,運用url改寫機制來保證會話標(biāo)識符傳回服務(wù)器。
二、 Session事件偵聽
HttpSessionBindingEvent類\
定義\
public class HttpSessionBindingEvent extends EventObject
這個事件是在監(jiān)聽到HttpSession發(fā)生綁定和取消綁定的情況時連通HttpSessionBindingListener的。這可能是一個session被終止或被認(rèn)定無效的結(jié)果。
事件源是HttpSession.putValue或HttpSession.removeValue。
構(gòu)造函數(shù)
public HttpSessionBindingEvent(HttpSession session, String name);
通過引起這個事件的Session和發(fā)生綁定或取消綁定的對象名構(gòu)造一個新的HttpSessionBindingEvent。
方法
1、getName
public String getName();
返回發(fā)生綁定和取消綁定的對象的名字。
2、getSession
public HttpSession getSession();
返回發(fā)生綁定和取消綁定的session的名字。
HttpSessionBindingListener接口
定義\
public interface HttpSessionBindingListener
這個對象被加入到HTTP的session中,執(zhí)行這個接口會通告有沒有什么對象被綁定到這個HTTP session中或被從這個HTTP session中取消綁定。
方法
1、valueBound
public void valueBound(HttpSessionBindingEvent event);
當(dāng)一個對象被綁定到session中,調(diào)用此方法。HttpSession.putValue方法被調(diào)用時,Servlet引擎應(yīng)該調(diào)用此方法。
2、valueUnbound
public void valueUnbound(HttpSessionBindingEvent event);
當(dāng)一個對象被從session中取消綁定,調(diào)用此方法。HttpSession.removeValue方法被調(diào)用時,Servlet引擎應(yīng)該調(diào)用此方法。
Session的事件處理機制與swing事件處理機制不同。Swing采用注冊機制,而session沒有;當(dāng)任一session發(fā)生綁定或其他事件時,都會觸發(fā)HttpSessionBindingEvent ,如果servlet容器中存在HttpSessionBindingListener的實現(xiàn)類,則會將事件作為參數(shù)傳送給session偵聽器的實現(xiàn)類。在HttpSessionBindingEvent 中可以通過getsession得到發(fā)生綁定和取消綁定的session的名字,而偵聽器可以據(jù)此做更多處理。
因此,對session的事件偵聽,只需實現(xiàn)HttpSessionBindingListener即可。
從servlet2.3增加了
HttpSessionEvent(This is the class representing event notifications for changes to sessions within a web application)
HttpSessionActivationListener(Objects
that are bound to a session may listen to container events notifying
them that sessions will be passivated and that session will be
activated.)
HttpSessionAttributeListener(This
listener interface can be implemented in order to get notifications of
changes to the attribute lists of sessions within this web application.)
分別執(zhí)行不同的任務(wù),處理基本相同。
三、 例子(zz)
捕獲Session事件的意義:
1、 記錄網(wǎng)站的客戶登錄日志(登錄,退出信息等)
2、 統(tǒng)計在線人數(shù)
3、 等等還有很多,呵呵,自己想吧……總之挺重要的。
Session代表客戶的會話過程,客戶登錄時,往Session中傳入一個對象,即可跟蹤客戶的會話。在Servlet中,傳入Session的對象如果是一個實現(xiàn)HttpSessionBindingListener接口的對象(方便起見,此對象稱為監(jiān)聽器),則在傳入的時候(即調(diào)用HttpSession對象的setAttribute方法的時候)和移去的時候(即調(diào)用HttpSession對象的removeAttribute方法的時候或Session Time out的時候)Session對象會自動調(diào)用監(jiān)聽器的valueBound和valueUnbound方法(這是HttpSessionBindingListener接口中的方法)。由此可知,登錄日志也就不難實現(xiàn)了。
另外一個問題是,如何統(tǒng)計在線人數(shù),這個問題跟實現(xiàn)登錄日志稍微有點不同,統(tǒng)計在線人數(shù)(及其信息),就是統(tǒng)計現(xiàn)在有多少個Session實例存在,我們可以增加一個計數(shù)器(如果想存儲更多的信息,可以用一個對象來做計數(shù)器,隨后給出的實例中,簡單起見,用一個整數(shù)變量作為計數(shù)器),通過在valueBound方法中給計數(shù)器加1,valueUnbound方法中計數(shù)器減1,即可實現(xiàn)在線人數(shù)的統(tǒng)計。當(dāng)然,這里面要利用到ServletContext的全局特性。(有關(guān)ServletContext的敘述請參考Servlet規(guī)范),新建一個監(jiān)聽器,并將其實例存入ServletContext的屬性中,以保證此監(jiān)聽器實例的唯一性,當(dāng)客戶登錄時,先判斷ServletContext的這個屬性是否為空,如果不為空,證明已經(jīng)創(chuàng)建,直接將此屬性取出放入Session中,計數(shù)器加1;如果為空則創(chuàng)建一個新的監(jiān)聽器,并存入ServletContext的屬性中。
舉例說明:
實現(xiàn)一個監(jiān)聽器:
// SessionListener.java
import java.io.*;
import java.util.*;
import javax.servlet.http.*;
//監(jiān)聽登錄的整個過程
public class SessionListener implements HttpSessionBindingListener
{
public String privateInfo=""; //生成監(jiān)聽器的初始化參數(shù)字符串
private String logString=""; //日志記錄字符串
private int count=0; //登錄人數(shù)計數(shù)器
public SessionListener(String info){
this.privateInfo=info;
}
|