新聞中心
一、 Servlet的會話管理機制

創(chuàng)新互聯(lián)是工信部頒發(fā)資質(zhì)IDC服務(wù)器商,為用戶提供優(yōu)質(zhì)的四川電信機房托管服務(wù)
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ù)器。
二、 Servlet 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)
捕獲Servlet 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; }
public int getCount(){ return count; }
public void valueBound(HttpSessionBindingEvent event) { count++; if (privateInfo.equals("count")) { return; } try{ Calendar calendar=new GregorianCalendar(); System.out.println("LOGIN:"+privateInfo+" TIME:"+calendar.getTime()); logString="\nLOGIN:"+privateInfo+" TIME:"+calendar.getTime()+"\n"; for(int i=1;i<1000;i++){ File file=new File("yeeyoo.log"+i); if(!(file.exists())) file.createNewFile(); //如果文件不存在,創(chuàng)建此文件 if(file.length()>1048576) //如果文件大于1M,重新創(chuàng)建一個文件 continue; FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true); //以append方式打開創(chuàng)建文件 foo.write(logString.getBytes(),0,logString.length()); //寫入日志字符串 foo.close(); break;//退出 } }catch(FileNotFoundException e){} catch(IOException e){} }
public void valueUnbound(HttpSessionBindingEvent event) { count--; if (privateInfo.equals("count")) { return; } try{ Calendar calendar=new GregorianCalendar(); System.out.println("LOGOUT:"+privateInfo+" TIME:"+calendar.getTime()); logString="\nLOGOUT:"+privateInfo+" TIME:"+calendar.getTime()+"\n"; for(int i=1;i<1000;i++){ File file=new File("yeeyoo.log"+i); if(!(file.exists())) file.createNewFile(); //如果文件不存在,創(chuàng)建此文件 if(file.length()>1048576) //如果文件大于1M,重新創(chuàng)建一個文件 continue; FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true); //以append方式打開創(chuàng)建文件 foo.write(logString.getBytes(),0,logString.length()); //寫入日志字符串 foo.close(); break;//退出 } }catch(FileNotFoundException e){} catch(IOException e){} }
} |
登錄日志的實現(xiàn):
下面再來看看我們的登錄Servlet中使用這個監(jiān)聽器的部分源代碼:
…… HttpSession session = req.getSession (true); …… ////////////////////////////////////////////////////////////////// SessionListener sessionListener= new SessionListener("IP:"+req.getRemoteAddr()); //對于每一個會話過程均啟動一個監(jiān)聽器 session.setAttribute("listener",sessionListener); //將監(jiān)聽器植入HttpSession,這將激發(fā)監(jiān)聽器調(diào)用valueBound方法, //從而記錄日志文件。 ////////////////////////////////////////////////////////////////// |
當(dāng)系統(tǒng)退出登錄時,只需簡單地調(diào)用session.removeAttribute(“l(fā)istener”);
即可自動調(diào)用監(jiān)聽器的valueUnbound方法?;蛘撸?dāng)Session Time Out的時候也會調(diào)用此方法。
登錄人數(shù)的統(tǒng)計:
ServletContext session1=getServletConfig().getServletContext(); //取得ServletContext對象實例 if((SessionListener)session1.getAttribute("listener1")==null) { SessionListener sessionListener1=new SessionListener("count"); //只設(shè)置一次,不同于上面日志文件的記錄每次會話均設(shè)置。 //即當(dāng)***個客戶連接到服務(wù)器時啟動一個全局變量, //此后所有的客戶將使用相同的上下文。 session1.setAttribute("listener1",sessionListener1); //將監(jiān)聽器對象設(shè)置成ServletContext的屬性,具有全局范圍有效性, //即所有的客戶均可以取得它的實例。 } session.setAttribute("listener1",(SessionListener)session1. getAttribute("listener1")); //取出此全局對象,并且將此對象綁定到某個會話中, //此舉將促使監(jiān)聽器調(diào)用valueBound,計數(shù)器加一。 |
在此后的程序中隨時可以用以下代碼取得當(dāng)前的登錄人數(shù):
((SessionListener)session.getAttribute("listener1")).getCount() |
Servlet Session中的getCount()是監(jiān)聽器的一個方法,即取得當(dāng)前計數(shù)器的值也就是登錄人數(shù)了。
【編輯推薦】
- 淺析Java Servlet構(gòu)建系統(tǒng)
- HTTP Servlet應(yīng)用編程接口介紹
- 再談如何理解JSP和Servlet的概念
- Servlet和JavaServer Page使用介紹
- ServletResponse是什么
當(dāng)前題目:ServletSession機制詳解
轉(zhuǎn)載來于:http://www.dlmjj.cn/article/dpcoohh.html


咨詢
建站咨詢
