您当前的位置: 首页 > 网站编程 > JSP教程 > JSP环境基于Session的在线用户统计深入分析

JSP环境基于Session的在线用户统计深入分析

作者:guanchaofeng 来源:本站整理 发布时间: 2009-11-02 09:31 点击:
JSP环境基于Session的在线用户统计深入分析 JSP作为后起之秀能够在服务器编程环境中占据一定地位,是和它良好支持一系列业界标准 密切相关的。Session就是它提供的基础设施之一。作为一个程序员,你可以不介意具体在 客户端是如何实现,就方便的实现简单的基

JSP环境基于Session的在线用户统计深入分析

  JSP环境基于Session的在线用户统计深入分析
  
  JSP作为后起之秀能够在服务器编程环境中占据一定地位,是和它良好支持一系列业界标准
  密切相关的。Session就是它提供的基础设施之一。作为一个程序员,你可以不介意具体在
  客户端是如何实现,就方便的实现简单的基于session的用户管理。
  
  现在对于处理在线用户,有几种不同的处理方法。
  
  一种是叶面刷新由用户控制,服务器端控制一个超时时间比如30分钟,到了时间之后用户
  没有动作就被踢出。这种方法的优点是,如果用户忘了退出,可以防止别人恶意操作。
  缺点是,如果你在做一件很耗时间的事情,超过了这个时间限制,submit的时候可能要
  再次面临登陆。如果原来的叶面又是强制失效的话,就有可能丢失你做的工作。在实现
  的角度来看,这是最简单的,Server端默认实现的就是这样的模式。
  
  另一种方式是,站点采用框架结构,有一个Frame或者隐藏的iframe在不断刷新,这样你
  永远不会被踢出,但是服务器端为了判断你是否在线,需要定一个发呆时间,如果超过
  这个发呆时间你除了这个自动刷新的叶面外没有刷新其他叶面的话,就认为你已经不在
  线了。采取这种方式的典型是xici.net。他的优点是可以可以利用不断的刷新实现一些
  类似server-push的功能,比如网友之间发送消息。
  
  不管哪一种模式,为了实现浏览当前所有的在线用户,还需要做一些额外的工作。
  servletAPI中没有得到Session列表的API。
  
  可以利用的是Listener.Servlet2.2和2.3规范在这里略微有一些不一样。
  2.2中HttpSessionBindingListener可以实现当一个HTTPSession中的Attribute变化的
  时候通知你的类。而2.3中还引入了HttpSessionAttributeListener.鉴于我使用的环境
  是Visualageforjava4和JRunserver3.1,他们还不直接支持Servlet2.3的编程,
  这里我用的是HttpSessionBindingListener.
  
  需要做的事情包括做一个新的类来实现HttpSessionBindingListener接口。这个接口有
  两个方法:
  publicvoidvalueBound(HttpSessionBindingEventevent),和
  publicvoidvalueUnbound(HttpSessionBindingEventevent)。
  当你执行Session.addAttribute(String,Object)的时候,如果你已经把一个实现了
  HttpSessionBindingListener接口的类加入为Attribute,Session会通知你的类,调用
  你的valueBound方法。相反,Session.removeAttribute方法对应的是valueUndound方法。
  
  
  
  publicclassHttpSessionBindingimplementsjavax.servlet.http.HttpSessionBindingListener
  {
  ServletContextapplication=null;
  
  publicHttpSessionBinding(ServletContextapplication)
  {
  super();
  if(application==null)
  thrownewIllegalArgumentException("Nullapplicationisnotaccept.");
  
  this.application=application;
  
  }
  
  publicvoidvalueBound(javax.servlet.http.HttpSessionBindingEvente)
  {
  VectoractiveSessions=(Vector)application.getAttribute("activeSessions");
  if(activeSessions==null)
  {
  activeSessions=newVector();
  }
  
  JDBCUsersessionUser=(JDBCUser)e.getSession().getAttribute("user");
  if(sessionUser!=null)
  {
  activeSessions.add(e.getSession());
  }
  application.setAttribute("activeSessions",activeSessions);
  }
  
  publicvoidvalueUnbound(javax.servlet.http.HttpSessionBindingEvente)
  {
  JDBCUsersessionUser=(JDBCUser)e.getSession().getAttribute("user");
  if(sessionUser==null)
  {
  VectoractiveSessions=(Vector)application.getAttribute("activeSessions");
  if(activeSessions!=null)
  {
  activeSessions.remove(e.getSession().getId());
  application.setAttribute("activeSessions",activeSessions);
  }
  }
  }
  }
  
  
  
  假设其中的JDBCUser类是一个任意User类。
  在执行用户登录时,把User类和HttpSessionBinding类都加入到Session中去。
  这样,每次用户登录后,在application中的attribute"activeSessions"这个vector中
  都会增加一条记录。
  每当session超时,valueUnbound被触发,在这个vector中删去将要被超时的session.
  
  
  publicvoidlogin()
  throwsACLException,SQLException,IOException
  {
  /*getJDBCUserClass*/
  if(user!=null)
  {
  logout();
  }
  {
  //ifsessiontimeout,oruserdidn'tlogin,savethetargeturltemporary.
  
  JDBCUserFactoryuf=newJDBCUserFactory();
  
  if((this.request.getParameter("userID")==null)
  ||(this.request.getParameter("password")==null))
  {
  thrownewACLException("PleaseinputavaliduserNameandpassword.");
  }
  
  JDBCUseruser=
  (JDBCUser)uf.UserLogin(
  this.request.getParameter("userID"),
  this.request.getParameter("password"));
  user.touchLoginTime();
  this.session.setAttribute("user",user);
  this.session.setAttribute("BindingNotify",newHttpSessionBinding(application));
  }
  }
  
  
  
  Login的时候,把User和这个BindingNotofy目的的类都加入到session中去。
  
  logout的时候,就要主动在activeSessions这个vector中删去这个session.
  
  publicvoidlogout()
  throwsSQLException,ACLException
  {
  if(this.user==null
  &&this.session.getAttribute("user")==null)
  {
  return;
  }
  
  VectoractiveSessions=(Vector)this.application.getAttribute("activeSessions");
  if(activeSessions!=null)
  {
  activeSessions.remove(this.session);
  application.setAttribute("activeSessions",activeSessions);
  }
  
  java.util.Enumeratione=this.session.getAttributeNames();
  
  while(e.hasMoreElements())
  {
  Strings=(String)e.nextElement();
  this.session.removeAttribute(s);
  }
  this.user.touchLogoutTime();
  this.user=null;
  }
  
  
  
  这两个函数位于一个HttpSessionManager类中.这个类引用了jsp里面的application全局
  对象。
  这个类的其他代码和本文无关且相当长,我就不贴出来了。
  
  下面来看看jsp里面怎么用。
  假设一个登录用的表单被提交到doLogin.jsp,表单中包含UserName和password域。
  
  节选部分片段:
  
  <%
  HttpSessionManagerhsm=newHttpSessionManager(application,request,response);
  try
  {
  hsm.login();
  }
  catch(UserNotFoundExceptione)
  {
  response.sendRedirect("InsufficientPrivilege.jsp?detail=User%20does%20not%20exist.");
  return;
  }
  catch(InvalidPasswordExceptione2)
  {
  response.sendRedirect("InsufficientPrivilege.jsp?detail=Invalid%20Password");
  return;
  }
  catch(Exceptione3)
  {
  %>Error:<%=e3.toString()%><br>
  Press<ahref="login.jsp">Here</a>torelogin.
  <%return;
  }
  response.sendRedirect("index.jsp");
  %>
  
  
  
  再来看看现在我们怎么得到一个当前在线的用户列表。
  
  <bodybgcolor="#FFFFFF">
  <tablecellspacing="0"cellpadding="0"width="100%">
  
  <tr>
  <tdstyle="width:24px">SessionId
  </td>
  <tdstyle="width:80px">User
  </td>
  <tdstyle="width:80px">LoginTime
  </td>
  <tdstyle="width:80px">LastaccessTime
  </td>
  </tr>
  <%
  VectoractiveSessions=(Vector)application.getAttribute("activeSessions");
  if(activeSessions==null)
  {
  activeSessions=newVector();
  application.setAttribute("activeSessions",activeSessions);
  }
  
  Iteratorit=activeSessions.iterator();
  while(it.hasNext())
  {
  HttpSessionsess=(HttpSession)it.next();
  JDBCUsersessionUser=(JDBCUser)sess.getAttribute("user");
  StringuserId=(sessionUser!=null)?sessionUser.getUserID():"None";
  %>
  <tr>
  <tdnowrap=''><%=sess.getId()%></td>
  <tdnowrap=''><%=userId%></td>
  <tdnowrap=''>
  <%=BeaconDate.getInstance(newjava.util.Date(sess.getCreationTime())).getDateTimeString()%></td>
  <tdclass="<%=stl%>3"nowrap=''>
  <%=BeaconDate.getInstance(newjava.util.Date(sess.getLastAccessedTime())).getDateTimeString()%></td>
  </tr>
  <%
  }
  %>
  </table>
  </body>
  
  
  
  以上的代码从application中取出activeSessions,并且显示出具体的时间。其中
  BeaconDate类假设为格式化时间的类。
  
  这样,我们得到了一个察看在线用户的列表的框架。至于在线用户列表分页等功能,
  与本文无关,不予讨论。
  这是一个非刷新模型的例子,依赖于session的超时机制。我的同事sonymusic指出很
  多时候由于各个厂商思想的不同,这有可能是不可信赖的。考虑到这种需求,需要在
  每个叶面刷新的时候都判断当前用户距离上次使用的时间是否超过某一个预定时间值。
  这实质上就是自己实现session超时。
  如果需要实现刷新模型,就必须使用这种每个叶面进行刷新判断的方法。

分享到:
本文"JSP环境基于Session的在线用户统计深入分析"由远航站长收集整理而来,仅供大家学习与参考使用。更多网站制作教程尽在远航站长站。
顶一下
(0)
0%
踩一下
(0)
0%
[点击 次] [返回上一页] [打印]
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
关于本站 - 联系我们 - 网站声明 - 友情连接- 网站地图 - 站点地图 - 返回顶部
Copyright © 2007-2013 www.yhzhan.com(远航站长). All Rights Reserved .
远航站长:为中小站长提供最佳的学习与交流平台,提供网页制作与网站编程等各类网站制作教程.
官方QQ:445490277 网站群:26680406 网站备案号:豫ICP备07500620号-4