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