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

2016-02-19 18:08 8 1 收藏

清醒时做事,糊涂时读书,大怒时睡觉,无聊时关注图老师为大家准备的精彩内容。下面为大家推荐JSP中基于Session的在线用户统计分析,无聊中的都看过来。

【 tulaoshi.com - Web开发 】

  JSP作为后起之秀能够在服务器编程环境中占据一定地位,是和它良好支持一系列业界标准密切相关的。Session就是它提供的基础设施之一。作为一个程序员,你可以不介意具体在客户端是如何实现,就方便的实现简单的基于session的用户管理。现在对于处理在线用户,有几种不同的处理方法。

  一种是页面刷新由用户控制,服务器端控制一个超时时间比如30分钟,到了时间之后用户没有动作就被踢出。这种方法的优点是,如果用户忘了退出,可以防止别人恶意操作。缺点是,如果你在做一件很耗时间的事情,超过了这个时间限制,submit的时候可能要再次面临登陆。如果原来的叶面又是强制失效的话,就有可能丢失你做的工作。在实现的角度来看,这是最简单的,Server端默认实现的就是这样的模式。

  另一种方式是,站点采用框架结构,有一个Frame或者隐藏的iframe在不断刷新,这样你永远不会被踢出,但是服务器端为了判断你是否在线,需要定一个发呆时间,如果超过这个发呆时间你除了这个自动刷新的页面外没有刷新其他页面的话,就认为你已经不在线了。采取这种方式的典型是xici.net。 他的优点是可以可以利用不断的刷新实现一些类似server-push的功能,比如网友之间发送消息。

  不管哪一种模式,为了实现浏览当前所有的在线用户,还需要做一些额外的工作。Servlet API中没有得到Session列表的API。

  可以利用的是Listener. Servlet 2.2和2.3规范在这里略微有一些不一样。2.2中HttpSessionBindingListener可以实现当一个HTTPSession中的Attribute变化的时候通知你的类。而2.3中还引入了HttpSessionAttributeListener.鉴于我使用的环境是Visual age for Java 4和JRun server 3.1,他们还不直接支持Servlet 2.3的编程,这里我用的是HttpSessionBindingListener.

  需要做的事情包括做一个新的类来实现HttpSessionBindingListener接口。这个接口有两个方法:

  public void valueBound(HttpSessionBindingEvent event)
  public void valueUnbound(HttpSessionBindingEvent event)

  当你执行Session.addAttribute(String,Object)的时候,如果你已经把一个实现了HttpSessionBindingListener接口的类加入为Attribute,Session会通知你的类,调用你的valueBound方法。相反,Session.removeAttribute方法对应的是valueUndound方法。

  public class HttpSessionBinding implements javax.servlet.http.HttpSessionBindingListener
  {
   ServletContext application = null;

   public HttpSessionBinding(ServletContext application)
   {
  super();
  if (application ==null)
   throw new IllegalArgumentException("Null application is not accept.");
  this.application = application;
   }

   public void valueBound(javax.servlet.http.HttpSessionBindingEvent e)
   {
  Vector activeSessions = (Vector) application.getAttribute("activeSessions");
  if (activeSessions == null)
  {
   activeSessions = new Vector();
  }

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  JDBCUser sessionUser = (JDBCUser)e.getSession().getAttribute("user");
  if (sessionUser != null)
  {
   activeSessions.add(e.getSession());
  }
  application.setAttribute("activeSessions",activeSessions);
   }

   public void valueUnbound(javax.servlet.http.HttpSessionBindingEvent e)
   {
  JDBCUser sessionUser = (JDBCUser)e.getSession().getAttribute("user");
  if (sessionUser == null)
  {
   Vector activeSessions = (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.

  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);
  }

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  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类假设为格式化时间的类。

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

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

来源:http://www.tulaoshi.com/n/20160219/1616891.html

延伸阅读
标签: Web开发
术语session 在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相同的。 session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。有时候我们可以看到这样的话“在...
标签: PHP
  可以实现在线人数统计,日访问量统计,月访问量统计。。。。。 <? $sql = "CREATE TABLE guestinfo(id integer DEFAULT '0' NOT NULL       AUTO_INCREMENT,                    &nbs...
标签: ASP
       在线人数统计内幕      Like most of our topics, I''m covering this one due to user demand for it. If you''ve been to any one of a few dozen ASP-based sites recently, you''ve probably seen an example of the script we''ve going to cover in this article. It'...
标签: Web开发
可以实现在线人数统计,日访问量统计,月访问量统计。。。。。 ? $sql = "CREATE TABLE guestinfo(id integer DEFAULT '0' NOT NULL       AUTO_INCREMENT,                      &nbs...
标签: ASP
  网络之门 在浏览网页的时侯,常常可以看见一些“当前网站上的人数是XXX人”的在线人数同计。如何用ASP来做一个呢?首先,分析一下它的做法,一般来说,这些线上人数统计都是指一个时段内的访客人数统计。比如(5分钟内,10分钟内)而这个时间的长短,是由设计者设定的。 在这个时段内同计各个不同I...

经验教程

310

收藏

66
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部