最近又有網(wǎng)友問(wèn)到,如何用Session實(shí)現在線(xiàn)統計的功能,其實(shí)只要對Servlet規范詳細了解一下,明白其基本原理,編寫(xiě)一個(gè)類(lèi)似的功能并不是一件很復雜的事情。我以前的一篇文章,最初也是發(fā)表在JavaResearch上的(http://www.javaresearch.org/article/showarticle.jsp?column=106&thread=2164),不過(guò)可能源碼沒(méi)有全部給出,只給出了最重點(diǎn)的源碼,所以還是有很多網(wǎng)友給我發(fā)信索取全部源碼。因為那個(gè)項目是以前做的,所以我手頭上也沒(méi)有原來(lái)的代碼了,所以可能有的網(wǎng)友的要求就滿(mǎn)足不了了,在這里一并致歉。
第一篇文章是基于Servlet2.2規范編寫(xiě)的,那時(shí)候沒(méi)有HttpSessionListener,鑒于目前絕大多數的應用服務(wù)器都支持2.3的規范,所以為了回應網(wǎng)友的提問(wèn),特地又基于2.3以上的規范編寫(xiě)了一個(gè)簡(jiǎn)單的測試例子。 這個(gè)例子的最主要功能就是提供在線(xiàn)用戶(hù)列表顯示(既然用戶(hù)列表都可以顯示了,那人數統計自然也不在話(huà)下了)。
在給出代碼之前,先簡(jiǎn)單說(shuō)一下監聽(tīng)器的常識。
HttpSessionListener:網(wǎng)友rdfei 在他的文章(http://www.javaresearch.org/article/showarticle.jsp?column=106&thread=18541)中也已經(jīng)進(jìn)行了比較詳細的描述,這是2.3以上規范所提供的一個(gè)新功能,也就是可以定義監聽(tīng)器監聽(tīng)HttpSession對象的創(chuàng )建和銷(xiāo)毀。每當有新的用戶(hù)訪(fǎng)問(wèn)網(wǎng)站,應用服務(wù)器會(huì )創(chuàng )建一個(gè)HttpSession對象,每當Session超時(shí),應用服務(wù)器則會(huì )銷(xiāo)毀這個(gè)對象。 HttpSessionBindingListener:每當往Session中存入一個(gè)對象(setAttribute)或從Session中刪除一個(gè)對象的時(shí)候,如果這個(gè)對象實(shí)現了此監聽(tīng)器接口,應用服務(wù)器將會(huì )自動(dòng)調用接口相應的方法。
需要注意的一點(diǎn)就是,在sessionDestroyed方法和valueUnbound方法中,你可以得到HttpSession對象的實(shí)例,但是其getAttribute方法不再可用,也就是在這兩個(gè)方法中,你不能再次得到存入session中的對象。
基于以上這些粗淺的認識,再簡(jiǎn)單介紹一下我提供的測試例子的情況:
測試例子總共包含如下文件: OnlineUserListener.java:它實(shí)現了HttpSessionListener接口 OnlineUsers.java:它包含了所有正在訪(fǎng)問(wèn)網(wǎng)站的用戶(hù)信息,為了方便起見(jiàn),它也實(shí)現了HttpSessionBindingListener接口(實(shí)際中你最好把他們分開(kāi)吧) User.java:這是用戶(hù)的信息 test.jsp:為了方便,我把登錄,退出,顯示在線(xiàn)用戶(hù)列表等功能都做在同一個(gè)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 {
-
- /**
- * 瀏覽器第一次訪(fǎng)問(wèn)的時(shí)候,調用本方法
- * @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超時(shí)的時(shí)候,調用本方法
- * @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
- * 在線(xiàn)用戶(hù)統計
- */
- 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);
- }
-
- /**
- * 對象實(shí)例(即OnlineUserListener的實(shí)例)作為一個(gè)屬性被設置到session的
- * 時(shí)候,會(huì )調用本方法,這種情況一般發(fā)生在點(diǎn)擊登錄按鈕以后的處理過(guò)程中
- * 設置
- * @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent)
- */
- public void valueBound(HttpSessionBindingEvent event) {
- //現在暫時(shí)不需要額外處理,你可以在這里記錄日志等
- }
-
- /**
- * 當Session超時(shí),或本實(shí)例被從session中移除的時(shí)候被調用,這種情況一般
- * 發(fā)生在注銷(xiāo)方法的處理過(guò)程中
- * @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>
附件:SessionTest.rar(95K)
|