如何用Session實現在線統計的功能,其實只要對Servlet規范詳細了解一下,明白其基本原理,編寫一個類似的功能并不是一件很復雜的事情。這個例子是基于2.3以上的規范編寫的,最主要功能就是提供在線用戶列表顯示(既然用戶列表都可以顯示了,那人數統計自然也不在話下了)。
在給出代碼之前,先簡單說一下監聽器的常識。
HttpSessionListener:這是2.3以上規范所提供的一個新功能,也就是可以定義監聽器監聽HttpSession對象的創建和銷毀。每當有新的用 戶訪問網站,應用服務器會創建一個HttpSession對象,每當Session超時,應用服務器則會銷毀這個對象。
HttpSessionBindingListener:每當往Session中存入一個對象(setAttribute)或從Session中刪除一個對象的時候,如果這個對象實現了此監聽器接口,應用服務器將會自動調用接口相應的方法。
需要注意的一點就是,在sessionDestroyed方法和valueUnbound方法中,你可以得到HttpSession對象的實例,但是其getAttribute方法不再可用,也就是在這兩個方法中,你不能再次得到存入session中的對象。
基于以上這些粗淺的認識,再簡單介紹一下提供的測試例子的情況:
測試例子總共包含如下文件:
OnlineUserListener.java:它實現了HttpSessionListener接口
OnlineUsers.java:它包含了所有正在訪問網站的用戶信息,為了方便起見,它也實現了HttpSessionBindingListener接口(實際中你最好把他們分開吧)
User.java:這是用戶的信息
test.jsp:為了方便,把登錄,退出,顯示在線用戶列表等功能都做在同一個jsp文件里了。
下面是具體的代碼:
/**?
*?OnlineUserListener.java?
*?Created?on?2004-11-19?
*/?
package?com.ccctc.view.web;?

import?javax.servlet.http.HttpSessionEvent;?
import?javax.servlet.http.HttpSessionListener;?

/**?
*?@author?litf?
*?
*/?
public?class?OnlineUserListener?
?implements?HttpSessionListener?{?

?/**?
??*?瀏覽器第一次訪問的時候,調用本方法?
??*?@see?javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent)?
??*/?
?public?void?sessionCreated(HttpSessionEvent?event)?{?
??User?u?=?new?User();?
??u.setName("guest");?
??u.setId(event.getSession().getId());?
??event.getSession().setAttribute("currentUser",u);?
??OnlineUsers.getInstance().addUser(u);?
?}?

?/**?
??*?Session超時的時候,調用本方法?
??*?@see?javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent)?
??*/?
?public?void?sessionDestroyed(HttpSessionEvent?event)?{?
??OnlineUsers.getInstance().removeUser(event.getSession().getId());?
?}?

}?


/**?
*?OnlineUsers.java?
*?Created?on?2004-11-19?
*/?
package?com.ccctc.view.web;?

import?java.util.Collection;?
import?java.util.HashMap;?
import?java.util.Map;?

import?javax.servlet.http.HttpSession;?
import?javax.servlet.http.HttpSessionBindingEvent;?
import?javax.servlet.http.HttpSessionBindingListener;?

/**?
*?@author?litf?
*?在線用戶統計?
*/?
public?class?OnlineUsers?implements?HttpSessionBindingListener{?

?private?Map?users?=?new?HashMap();?
??
?private?static?OnlineUsers?onlineUsers?=?new?OnlineUsers();?
??
?public?static?OnlineUsers?getInstance(){?
??return?onlineUsers;?
?}?
??
?/**?
??*?@return?
??*/?
?public?Collection?getUsers()?{?
??return?users.values();?
?}?
??
?public?void?addUser(User?user)?{?
??users.put(user.getId(),user);?
?}?
??
?public?void?removeUser(String?userId){?
??users.remove(userId);?
?}?
??
?/**?
??*?對象實例(即OnlineUserListener的實例)作為一個屬性被設置到session的?
??*?時候,會調用本方法,這種情況一般發生在點擊登錄按鈕以后的處理過程中?
??*?設置?
??*?@see?javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent)?
??*/?
?public?void?valueBound(HttpSessionBindingEvent?event)?{?
??//現在暫時不需要額外處理,你可以在這里記錄日志等?
?}?

?/**?
??*?當Session超時,或本實例被從session中移除的時候被調用,這種情況一般?
??*?發生在注銷方法的處理過程中?
??*?@see?javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.servlet.http.HttpSessionBindingEvent)?
??*/?
?public?void?valueUnbound(HttpSessionBindingEvent?event)?{?
??try?{?
???HttpSession?session?=?event.getSession();?
???User?u?=?(User)session.getAttribute("currentUser");?
???u.setName("guest");?
??}?catch?(RuntimeException?e)?{?
???//e.printStackTrace();?
??}?
?}?

??
}?


/**?
*?User.java?
*?Created?on?2004-11-19?
*/?
package?com.ccctc.view.web;?

/**?
*?@author?litf?
*?
*/?
public?class?User{?
?private?String?address;?
?private?String?id;?
?private?String?name;?

?/**?
??*?@see?java.lang.Object#equals(java.lang.Object)?
??*/?
?public?boolean?equals(Object?obj)?{?
??if?(obj?==?null?||?!(obj?instanceof?User))?{?
???return?false;?
??}?
??if(this.id?!=null?&&?this.id.equals(((User)obj).getId())){?
???return?true;?
??}?
??return?false;?
?}?

?/**?
??*?@return?
??*/?
?public?String?getAddress()?{?
??return?address;?
?}?

?/**?
??*?@return?
??*/?
?public?String?getId()?{?
??return?id;?
?}?

?/**?
??*?@return?
??*/?
?public?String?getName()?{?
??return?name;?
?}?

?/**?
??*?@param?string?
??*/?
?public?void?setAddress(String?string)?{?
??address?=?string;?
?}?

?/**?
??*?@param?string?
??*/?
?public?void?setId(String?string)?{?
??id?=?string;?
?}?

?/**?
??*?@param?string?
??*/?
?public?void?setName(String?string)?{?
??name?=?string;?
?}?
??
?/**?
??*?@see?java.lang.Object#toString()?
??*/?
?public?String?toString()?{?
??return?"name:"+name?+?",id:"?+?id?+?",address:"+address;?
?}?

}?
test.jsp
<%@?page?import="com.ccctc.view.web.*"?%>?

<%?
User?u?=?(User)session.getAttribute("currentUser");?
String?name?=?request.getParameter("user");?

if(u?!=?null){?
?String?remote?=?request.getRemoteAddr();?
?u.setAddress(remote);?
??
}?

//User?Login?
if(name?!=?null){?
?if(u?!=?null){?
??session.setAttribute("_listener",OnlineUsers.getInstance());?
??u.setName(name);?
???
?}?
}?

//User?Logout?
String?logout?=?request.getParameter("logout");?
if(logout?!=?null){?
?session.removeAttribute("_listener");?
}?
%>?

current?users:<p>?

<%?
java.util.Collection?l?=?OnlineUsers.getInstance().getUsers();?
for(java.util.Iterator?it?=?l.iterator();?it.hasNext();)?
{?
?User?tu?=?(User)it.next();?
?if(u.equals(tu))?
?{?
%>?

<font?color=red><%=tu.getName()%>:<%=tu.getAddress()%>?</font>???

<%?
?}else{?
%>?

<%=tu.getName()%>:<%=tu.getAddress()%>???

<%?
?}?
}?
%>?
<form?action="/cctc/login.jsp">?
User?:?<input?name="user"?type="text">?<br>?
<input?type="submit"?name="Submit">?
</form>?
<p>?
<a?href="/cctc/login.jsp?logout=true">Logout</a>?<p>?
<a?href="/cctc/login.jsp">refresh</a>?
web.xml文件中增加:
<listener>?
??<listener-class>com.ccctc.view.web.OnlineUserListener</listener-class>?
?</listener>
在給出代碼之前,先簡單說一下監聽器的常識。
HttpSessionListener:這是2.3以上規范所提供的一個新功能,也就是可以定義監聽器監聽HttpSession對象的創建和銷毀。每當有新的用 戶訪問網站,應用服務器會創建一個HttpSession對象,每當Session超時,應用服務器則會銷毀這個對象。
HttpSessionBindingListener:每當往Session中存入一個對象(setAttribute)或從Session中刪除一個對象的時候,如果這個對象實現了此監聽器接口,應用服務器將會自動調用接口相應的方法。
需要注意的一點就是,在sessionDestroyed方法和valueUnbound方法中,你可以得到HttpSession對象的實例,但是其getAttribute方法不再可用,也就是在這兩個方法中,你不能再次得到存入session中的對象。
基于以上這些粗淺的認識,再簡單介紹一下提供的測試例子的情況:
測試例子總共包含如下文件:
OnlineUserListener.java:它實現了HttpSessionListener接口
OnlineUsers.java:它包含了所有正在訪問網站的用戶信息,為了方便起見,它也實現了HttpSessionBindingListener接口(實際中你最好把他們分開吧)
User.java:這是用戶的信息
test.jsp:為了方便,把登錄,退出,顯示在線用戶列表等功能都做在同一個jsp文件里了。
下面是具體的代碼:





























































































































































































test.jsp


























































web.xml文件中增加:


