动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > JSP技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ JSP技巧 ]的信息

本月文章推荐
.用JSP下载word文件(不会直接用I.
.JSP应用语法详解大全 (1).
.提升JSP应用程序的七大绝招.
.在Windows/NT上建立JSP环境.
.JSP中tomcat的SQL Server2000数据.
.JSP中读文件和写文件的例子.
.JSP生成静态页实践及其设计思想[.
.jsp从数据库取得数据作为下拉菜单.
.无边框窗口代码详解.
.windows中双击jar文件即可运行写.
.访问Access数据库(JSP+Tomcat 5..
.JSP内部对象详解.
.java/jsp中 中文问题详解.
.jsp中文问题解决方案(完整版).
.困扰JSP的一些问题与解决方法.
.JSP登录验证功能的实现.
.JSP连接mysql数据库攻略.
.用连接池提高Servlet访问数据库的.
.JDBC之代码重复使用.
.jsp中的数据库编程.

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

发表日期:2006-11-18 |


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

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

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超时。如果需要实现刷新模型,就必须使用这种每个叶面进行刷新判断的方法。

上一篇:TOMCAT用https替换http的方法 人气:6602
下一篇:JSP和JSF双剑合并 打造完美Web应用 人气:4282
浏览全部JSP的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-9-5 Coppermine Photo Gallery v1.4.
2008-9-5 清松网络日记本 v2.4
2008-9-5 AyWeb企业网站管理系统 v2.3 bui
2008-9-5 美女写真小偷程序联盟 v3.0 buil
2008-9-5 老Y文章管理系统 v2.1
2008-9-5 SiteDynamic企业网站管理系统 v1
2008-9-5 MyCOM企业网站管理系统 v1.0 Bui
2008-9-5 乐风CMS影视版 2008
2008-9-5 幻影电影视频系统TvsCms v1.3 伪
2008-8-23 Mini WinMount V0.4
2008-8-23 Vista优化大师3.11正式版
2008-8-23 Wine 1.13
2008-8-23 KlipFolio 5.0 Build 5899-80
2008-8-23 Windows Sysinternals Desktops
2008-8-23 OneTap Movies1.2破解版
2008-8-23 AnnotaterPDF阅读1.1.503 破解版
2008-8-23 SoundMeter分贝测量仪 v1.0汉化破
2008-8-23 iDrum音乐节拍1.0破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | 广告代码 | Html转换js | js/vbs加密 | md5加密 | 进制转换
实用工具:汉字翻译拼音 | 符号对照表 | 个税计算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 国家代码与域名缩写 | 文字加密解密 | 健康查询 | 万年历 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵