随锐旗下互动传媒:

关于JSP中基于Session的在线用户统计分析

http://www.weaseek.com  2008-04-30 09:40:34  来源:赛迪网

假设其中的JDBCUser类是一个任意User类。在执行用户登录时,把User类和HttpSessionBinding类都加入到Session中去。

这样,每次用户登录后,在application中的attribute "activeSessions"这个vector中都会增加一条记录。每当session超时,valueUnbound被触发,在这个vector中删去将要被超时的session.

public void login()

throws ACLException,SQLException,IOException

{

/* get JDBC User Class */

if (user != null)

{

logout();

}

{

// if session time out, or user didn't login, save the target url temporary.

JDBCUserFactory uf = new JDBCUserFactory();

if ( (this.request.getParameter("userID")==null) || (this.request.getParameter("password")==null) )

{

throw new ACLException("Please input a valid userName and password.");

}

JDBCUser user = (JDBCUser) uf.UserLogin(

this.request.getParameter("userID"),

this.request.getParameter("password") );

user.touchLoginTime();

this.session.setAttribute("user",user);

this.session.setAttribute("BindingNotify",new HttpSessionBinding(application));

}

}

Login的时候,把User和这个BindingNotofy目的的类都加入到session中去。logout的时候,就要主动在activeSessions这个vector中删去这个session.

public void logout()

throws SQLException,ACLException

{

if (this.user == null && this.session.getAttribute("user")==null)

{

return;

}

Vector activeSessions = (Vector) this.application.getAttribute("activeSessions");

if (activeSessions != null)

{

activeSessions.remove(this.session);

application.setAttribute("activeSessions",activeSessions);

}

java.util.Enumeration e = this.session.getAttributeNames();

while (e.hasMoreElements())

{

String s = (String)e.nextElement();

this.session.removeAttribute(s);

}

this.user.touchLogoutTime();

this.user = null;

}

这两个函数位于一个HttpSessionManager类中.这个类引用了jsp里面的application全局对象。这个类的其他代码和本文无关且相当长,我就不贴出来了。

下面来看看JSP里面怎么用。

假设一个登录用的表单被提交到doLogin.jsp, 表单中包含UserName和password域。节选部分片段:

<%

HttpSessionManager hsm = new HttpSessionManager(application,request,response);

try

{

hsm.login();

}

catch ( UserNotFoundException e)

{

response.sendRedirect("InsufficientPrivilege.jsp?detail=User%20does%20not%20exist.");

return;

}

catch ( InvalidPasswordException e2)

{

response.sendRedirect("InsufficientPrivilege.jsp?detail=Invalid%20Password");

return;

}

catch ( Exception e3)

{

%> Error:<%=e3.toString() %><br>

Press <a href="login.jsp">Here</a> to relogin.

<% return;

}

response.sendRedirect("index.jsp");

%>

再来看看现在我们怎么得到一个当前在线的用户列表。

<body bgcolor="#FFFFFF">

<table cellspacing="0" cellpadding="0" width="100%">

<tr >

<td style="width:24px">SessionId

</td>

<td style="width:80px" >User

</td>

<td style="width:80px" >Login Time

</td>

<td style="width:80px" >Last Access Time

</td>

</tr>

<%

Vector activeSessions = (Vector) application.getAttribute("activeSessions");

if (activeSessions == null)

{

activeSessions = new Vector();

application.setAttribute("activeSessions",activeSessions);

}

Iterator it = activeSessions.iterator();

while (it.hasNext())

{

HttpSession sess = (HttpSession)it.next();

JDBCUser sessionUser = (JDBCUser)sess.getAttribute("user");

String userId = (sessionUser!=null)?sessionUser.getUserID():"None";

%>

<tr>

<td nowrap=''><%= sess.getId() %></td>

<td nowrap=''><%= userId %></td>

<td nowrap=''>

<%= BeaconDate.getInstance( new Java.util.Date(sess.getCreationTime())).getDateTimeString()%></td>

<td class="<%= stl %>3" nowrap=''>

<%= BeaconDate.getInstance( new java.util.Date(sess.getLastAccessedTime())).getDateTimeString()%></td>

</tr>

<%

}

%>

</table>

</body>

以上的代码从application中取出activeSessions,并且显示出具体的时间。其中BeaconDate类假设为格式化时间的类。

这样,我们得到了一个察看在线用户的列表的框架。至于在线用户列表分页等功能,与本文无关,不予讨论。

记者百度(baidu.com)了一下这是一个非刷新模型的例子,依赖于session的超时机制。我的同事sonymusic指出很多时候由于各个厂商思想的不同,这有可能是不可信赖的。考虑到这种需求,需要在每个叶面刷新的时候都判断当前用户距离上次使用的时间是否超过某一个预定时间值。这实质上就是自己实现session超时。如果需要实现刷新模型,就必须使用这种每个叶面进行刷新判断的方法。

[责任编辑:梧桐]热门关键词: JSP Session 在线用户统计