servlet的session管理(轉)

     根據設計,HTTP是一種無狀態的協議。它意味着Web應用並不瞭解有關同一用戶之前請求的信息。維持會話狀態信息的方法之一是使用Servlet或者JSP容器提供的會話跟蹤功能。Servlet API規範定義了一個簡單的HttpSession接口,經過它咱們能夠方便地實現會話跟蹤。 java

     HttpSession接口提供了存儲和返回標準會話屬性的方法。標準會話屬性如會話標識符、應用數據等,都以「名字-值」對的形式保存。簡而言之,HttpSession接口提供了一種把對象保存到內存、在同一用戶的後繼請求中提取這些對象的標準辦法。在會話中保存數據的方法是setAttribute(String s, Object o),從會話提取原來所保存對象的方法是getAttribute(String s) web

 

每當新用戶請求一個使用了HttpSession對象的JSP頁面,JSP容器除了發回應答頁面以外,它還要向瀏覽器發送一個特殊的數字。這個特殊的數字稱爲「會話標識符」,它是一個惟一的用戶標識符。此後,HttpSession對象就駐留在內存之中,等待同一用戶返回時再次調用它的方法。 瀏覽器

     在客戶端,瀏覽器保存會話標識符,並在每個後繼請求中把這個會話標識符發送給服務器。會話標識符告訴JSP容器當前請求不是用戶發出的第一個請求,服務器之前已經爲該用戶建立了HttpSession對象。此時,JSP容器再也不爲用戶建立新的HttpSession對象,而是尋找具備相同會話標識符的HttpSession對象,而後創建該HttpSession對象和當前請求的關聯。 服務器

     會話標識符以Cookie的形式在服務器和瀏覽器之間傳送。若是客戶端不支持cookie,運用url改寫機制來保證會話標識符傳回服務器。 cookie

2、  Session事件偵聽 session

HttpSessionBindingEvent\
      
定義\
      public class HttpSessionBindingEvent extends EventObject
      
這個事件是在監聽到HttpSession發生綁定和取消綁定的狀況時連通HttpSessionBindingListener的。這多是一個session被終止或被認定無效的結果。
      
事件源是HttpSession.putValueHttpSession.removeValue
      
構造函數
      public HttpSessionBindingEvent(HttpSession session, String name);
      
經過引發這個事件的Session和發生綁定或取消綁定的對象名構造一個新的HttpSessionBindingEvent
      
方法
      1
getName
      public String getName();
      
返回發生綁定和取消綁定的對象的名字。
      2
getSession
      public HttpSession getSession();
      
返回發生綁定和取消綁定的session的名字。
HttpSessionBindingListener
接口
      
定義\
      public interface HttpSessionBindingListener
      
這個對象被加入到HTTPsession中,執行這個接口會通告有沒有什麼對象被綁定到這個HTTP session中或被從這個HTTP session中取消綁定。
      
方法
      1
valueBound
      public void valueBound(HttpSessionBindingEvent event);
      
當一個對象被綁定到session中,調用此方法。HttpSession.putValue方法被調用時,Servlet引擎應該調用此方法。
      2
valueUnbound
      public void valueUnbound(HttpSessionBindingEvent event);
      
當一個對象被從session中取消綁定,調用此方法。HttpSession.removeValue方法被調用時,Servlet引擎應該調用此方法。

app

Session的事件處理機制與swing事件處理機制不一樣。Swing採用註冊機制,而session沒有;當任一session發生綁定或其餘事件時,都會觸發HttpSessionBindingEvent ,若是servlet容器中存在HttpSessionBindingListener的實現類,則會將事件做爲參數傳送給session偵聽器的實現類。在HttpSessionBindingEvent 中能夠經過getsession獲得發生綁定和取消綁定的session的名字,而偵聽器能夠據此作更多處理。 函數

 

所以,對session的事件偵聽,只需實現HttpSessionBindingListener便可。 網站

 

servlet2.3增長了 this

HttpSessionEventThis is the class representing event notifications for changes to sessions within a web application

HttpSessionActivationListenerObjects that are bound to a session may listen to container events notifying them that sessions will be passivated and that session will be activated.

HttpSessionAttributeListenerThis listener interface can be implemented in order to get notifications of changes to the attribute lists of sessions within this web application.

分別執行不一樣的任務,處理基本相同。

3、例子(zz

    捕獲Session事件的意義: 

1 記錄網站的客戶登陸日誌(登陸,退出信息等) 

2 統計在線人數 

3 等等還有不少,呵呵,本身想吧……總之挺重要的。 

  Session表明客戶的會話過程,客戶登陸時,往Session中傳入一個對象,便可跟蹤客戶的會話。在Servlet中,傳入Session的對象若是是一個實現HttpSessionBindingListener接口的對象(方便起見,此對象稱爲監聽器),則在傳入的時候(即調用HttpSession對象的setAttribute方法的時候)和移去的時候(即調用HttpSession對象的removeAttribute方法的時候或Session Time out的時候)Session對象會自動調用監聽器的valueBoundvalueUnbound方法(這是HttpSessionBindingListener接口中的方法)。由此可知,登陸日誌也就不難實現了。 

  另一個問題是,如何統計在線人數,這個問題跟實現登陸日誌稍微有點不一樣,統計在線人數(及其信息),就是統計如今有多少個Session實例存在,咱們能夠增長一個計數器(若是想存儲更多的信息,能夠用一個對象來作計數器,隨後給出的實例中,簡單起見,用一個整數變量做爲計數器),經過在valueBound方法中給計數器加1valueUnbound方法中計數器減1,便可實如今線人數的統計。固然,這裏面要利用到ServletContext的全局特性。(有關ServletContext的敘述請參考Servlet規範),新建一個監聽器,並將其實例存入ServletContext的屬性中,以保證此監聽器實例的惟一性,當客戶登陸時,先判斷ServletContext的這個屬性是否爲空,若是不爲空,證實已經建立,直接將此屬性取出放入Session中,計數器加1;若是爲空則建立一個新的監聽器,並存入ServletContext的屬性中。 

  舉例說明: 

  實現一個監聽器: 


// SessionListener.java

 

import java.io.*;

import java.util.*;

import javax.servlet.http.*;

 

//監聽登陸的整個過程

public class SessionListener implements HttpSessionBindingListener

{

 

public String privateInfo=""; //生成監聽器的初始化參數字符串

private String logString=""; //日誌記錄字符串

private int count=0; //登陸人數計數器

 

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(); //若是文件不存在,建立此文件

if(file.length()>1048576) //若是文件大於1M,從新建立一個文件

continue;

FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true);

//以append方式打開建立文件

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(); //若是文件不存在,建立此文件

if(file.length()>1048576) //若是文件大於1M,從新建立一個文件

continue;

FileOutputStream foo=new FileOutputStream("yeeyoo.log"+i,true);

//以append方式打開建立文件

foo.write(logString.getBytes(),0,logString.length()); //寫入日誌字符串

foo.close();

break;//退出

}

}catch(FileNotFoundException e){}

catch(IOException e){}

}

 

}



登陸日誌的實現: 

下面再來看看咱們的登陸Servlet中使用這個監聽器的部分源代碼: 


……

HttpSession session = req.getSession (true);

……

//////////////////////////////////////////////////////////////////

SessionListener sessionListener=

   new SessionListener("IP:"+req.getRemoteAddr());

//對於每個會話過程均啓動一個監聽器

session.setAttribute("listener",sessionListener);

//將監聽器植入HttpSession,這將激發監聽器調用valueBound方法,

//從而記錄日誌文件。

//////////////////////////////////////////////////////////////////



當系統退出登陸時,只需簡單地調用session.removeAttribute(「listener」); 

便可自動調用監聽器的valueUnbound方法。或者,當Session Time Out的時候也會調用此方法。 

登陸人數的統計: 


ServletContext session1=getServletConfig().getServletContext();

//取得ServletContext對象實例

if((SessionListener)session1.getAttribute("listener1")==null)

{

SessionListener sessionListener1=new SessionListener("count");

//只設置一次,不一樣於上面日誌文件的記錄每次會話均設置。

//即當第一個客戶鏈接到服務器時啓動一個全局變量,

//此後全部的客戶將使用相同的上下文。

session1.setAttribute("listener1",sessionListener1);

//將監聽器對象設置成ServletContext的屬性,具備全局範圍有效性,

//即全部的客戶都可以取得它的實例。

}

session.setAttribute("listener1",(SessionListener)session1.

getAttribute("listener1"));

//取出此全局對象,而且將此對象綁定到某個會話中,

//此舉將促使監聽器調用valueBound,計數器加一。



在此後的程序中隨時能夠用如下代碼取得當前的登陸人數: 


((SessionListener)session.getAttribute("listener1")).getCount()



getCount()是監聽器的一個方法,即取得當前計數器的值也就是登陸人數了。

相關文章
相關標籤/搜索