在线统计人数和访问量设计

Servlet监听器主要有三种,在ServletContext(上下文对象)、Session(会话)和request(请求)这三对象上进行监听,可以监听对象的创建、销毁、添加属性、删除属性、属性值的改变等。ServletContext对象的作用域在整个WEB应用程序,类似于Static属性;Session的作用域在一个会话,一个会话可以理解为一个从一个浏览器发出请求到服务器开始,一直到浏览器关闭(但通常我们可以设置会话的生命期,防止那些获得连接后却长时间没有再向服务器发出请求的情况),相当于类的成员变量;request的作用域仅在一次请求,即浏览器发送一次请求到服务器处理该请求并发回响应就结束了,相当于局部变量。

要实现统计网站的历史访问量就要利用ServletContext的全局属性的特点了,为了在服务器停止后,之前的访问量不会消失,我们就应该在服务器关闭前将当前的访问量存放到文件里面,以便下一次重启服务器后,可以继续使用。在ServletContext上面创建监听器,监听上下文对象的销毁和创建,并同时在创建上下文的时候从文件读取历史数据,在上下文销毁的时候将当前访问量写入到文件保存起来。以后每当创建一个会话(Session)的时候,就将当前的计数值加一。在线人数的统计是利用在创建会话的时候,将在线人数之加一,在会话对象销毁的时候,将在线人数值减一。因为两种人数统计都是被所有用户共享的信息,所以使用ServletContext的setAttribute()和getAttribut()方法来对总人数和在线人数进行管理。

创建对上下文对象的监听器:

public class ContextListener implements ServletContextListener{

public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
Properties pro = new Properties();
try {
pro.setProperty("counter", arg0.getServletContext().getAttribute("counter").toString());
String filePath = arg0.getServletContext().getRealPath("/WEB-INF/classes/db/count.txt");

//上下文对象销毁时,将当前访问量写入文件
OutputStream os = new FileOutputStream(filePath);
pro.store(os, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
arg0.getServletContext().setAttribute("online", 0);
Properties pro = new Properties();
InputStream in = ContextListener.class.getResourceAsStream("/db/count.txt");
String n = null;
try {
pro.load(in);
n = pro.getProperty("counter");//从计数文件中读取该站的历史访问量
arg0.getServletContext().setAttribute("counter", Integer.parseInt(pro.getProperty("counter")));
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("读取计数文件失败");
}
System.out.println("创建上下文对象" + n);
}

}


创建对会话对象的监听:


public class SessionListener implements HttpSessionListener{

public void sessionCreated(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
HttpSession session = arg0.getSession();
int i = (Integer)session.getServletContext().getAttribute("online");//获得当前在线人数,并将其加一
session.getServletContext().setAttribute("online", i+1);
int n = (Integer)session.getServletContext().getAttribute("counter");//创建一个会话就将访问量加一
session.getServletContext().setAttribute("counter", n+1);
Properties pro = new Properties();
try {//访问人数加一后就将结果写入文件(防止不正常关闭服务器)
pro.setProperty("counter", session.getServletContext().getAttribute("counter").toString());
String filePath = session.getServletContext().getRealPath("/WEB-INF/classes/db/count.txt");
OutputStream os = new FileOutputStream(filePath);
pro.store(os, null);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("写入计数文件失败");
}
System.out.println("创建一个会话");
}

public void sessionDestroyed(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
//销毁会话的时候,需要将在线人数减一
ServletContext context = arg0.getSession().getServletContext();
Integer i = (Integer)context.getAttribute("online");
context.setAttribute("online", i-1);
arg0.getSession().invalidate();
System.out.println("销毁一个会话");
}
}



在web.xml文件中将监听器注册,在创建和销毁对象时就会触发该事件了。 因为我们通常做测试的时候,服务器的关闭是没有通过正常的方式来进行的,所以程序中在创建一个会的时候将网站历史访问数据值加一后就将该值在文件中进行更新,否则可能该值不会改变。创建一个会话是通过request.getSession()来触发的,所以在做测试的Servlet中需要加上HttpSession session = request.getSession();
//设置会话的最大不活动时间为60秒
session.setMaxInactiveInterval(60);。
package org.leeyohn.listener; 

import java.util.HashMap;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletContext;

import org.leeyohn.User;
import org.leeyohn.OnLineUser;

public class OnLineUserListener
implements HttpSessionListener
{
//在线注册用户的累加器
private int userCount = 0;

//在线游客的累加器
private int visitorCount = 0;

@Override
public void sessionCreated(HttpSessionEvent se)
{
System.out.println("sessionCreated");
//获取一个session
HttpSession session = se.getSession();
//获取application
ServletContext application = session.getServletContext();

System.out.println("创建了一个游客Session");
//包装成一个在线游客信息
OnLineUser onLineUser = new OnLineUser(session.getId(), null, null, null);
//获取在线游客的HashMap
HashMap<String, OnLineUser> visitorMap = (HashMap<String, OnLineUser>)application.getAttribute("visitormap");
//将访问网站的游客放入Map中
visitorMap.put(session.getId(), onLineUser);
//当前在线游客总数
visitorCount = visitorMap.size();
System.out.println(visitorCount);
//设置全局的在线游客人数
application.setAttribute("visitorCount", visitorCount);

//总人数
application.setAttribute("onLineUserCount", (visitorCount + userCount));
}

@Override
public void sessionDestroyed(HttpSessionEvent se)
{
System.out.println("sessionDestoryed");
HttpSession session = se.getSession();
ServletContext application = session.getServletContext();

//注册用户
if (session.getAttribute("user") != null)
{
System.out.println("注销了一个注册用户Session");
User user = (User)session.getAttribute("user");
HashMap<String, OnLineUser> userMap = (HashMap<String, OnLineUser>)application.getAttribute("usermap");
userMap.remove(session.getId());
userCount = userMap.size();
System.out.println(userCount);
application.setAttribute("userCount", userCount);
}
//游客
else
{
System.out.println("注销了一个游客Session");
HashMap<String, OnLineUser> visitorMap = (HashMap<String, OnLineUser>)application.getAttribute("visitormap");
visitorMap.remove(session.getId());
visitorCount = visitorMap.size();
System.out.println(visitorCount);
application.setAttribute("visitorCount", visitorCount);
}
//总人数
application.setAttribute("onLineUserCount", (visitorCount + userCount));
}
}

LoginServlet.java文件

import java.util.HashMap;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Cookie;
import javax.servlet.RequestDispatcher;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.JspFactory;
import javax.servlet.ServletContext;
import java.sql.ResultSet;
import org.leeyohn.User;
import org.leeyohn.DbDao;
import org.leeyohn.OnLineUser;
import org.leeyohn.dao.DataSourcePool;

public class LoginServlet extends HttpServlet
{

@Override
public void service(HttpServletRequest request
, HttpServletResponse response)
{
//获取session对象
HttpSession session = request.getSession(true);

//创建一个application对象
ServletContext application = getServletContext();
String errMsg = "";
try
{
//获取应用程序名称
String webName = request.getContextPath().substring(1);
//用户名
String username = new String(request.getParameter("username").getBytes("iso-8859-1"), "gbk");
//密码
String password = new String(request.getParameter("password").getBytes("iso-8859-1"), "gbk");
//Cookie生存周期
int maxAge = Integer.parseInt(request.getParameter("cookietime"));

System.out.println("Cookie生存周期=" + maxAge);
System.out.println("应用程序名称=" + webName);

DataSourcePool dsp = (DataSourcePool)application.getAttribute("dsp");
ResultSet rs = dsp.query("select user_id, user_name, user_password from user_table where user_name='" + username + "'");

if (rs.next())
{
if (rs.getString("user_password").equals(password))
{

//调用Model,将用户名密码和ID封装成User对象
User user = new User(rs.getInt(1), username, password);

Cookie cookieName = new Cookie(webName + ".loginname", username);
Cookie cookiePass = new Cookie(webName + ".loginpass", password);

cookieName.setPath("/");
cookiePass.setPath("/");

//设置Cookie对象的保存期限
cookieName.setMaxAge(maxAge);
cookiePass.setMaxAge(maxAge);

//写入Cookie对象
response.addCookie(cookieName);
response.addCookie(cookiePass);

//设置session属性,跟踪用户状态
session.setAttribute("user", user);
//--------统计在线人数并分别统计在线会员人数和在线游客-------
OnLineUser onLineUser = new OnLineUser(session.getId(), user
, request.getRemoteAddr(), request.getServletPath());
//获取在线注册用户的HashMap
HashMap<String, OnLineUser> userMap = (HashMap<String, OnLineUser>)
application.getAttribute("usermap");
//将新登录的注册用户放入Map中
userMap.put(session.getId(), onLineUser);
//Map的容量
int userCount = userMap.size();
System.out.println(userCount);
//设置全局的在线注册用户人数
application.setAttribute("userCount", userCount);

//一次游客访问为session,但登录也是session,要减去游客数量,增加登录用户数量
HashMap<String, OnLineUser> visitorMap = (HashMap<String, OnLineUser>)
application.getAttribute("visitormap");
//从游客的Map中移除当前游客
visitorMap.remove(session.getId());
//移除当前游客后的游客数量
int visitorCount = visitorMap.size();
application.setAttribute("visitorCount", visitorCount);

//总人数
application.setAttribute("onLineUserCount", (visitorCount + userCount));

request.getRequestDispatcher("/autoturn.jsp").forward(request, response);
}
else
{
//用户名密码不匹配
errMsg += "您的用户名密码不符合,请重新输入";
}
}
else
{
//用户名不存在
errMsg += "您的用户名不存在,请先注册";
}
}
catch (Exception e)
{
e.printStackTrace();
}
if (errMsg != null && !errMsg.equals(""))
{
request.setAttribute("err", errMsg);
try
{
request.getRequestDispatcher("/error.jsp").forward(request, response);
}
catch (Exception e)
{
e.</p>
<div align="center" class="pager"><span id="pagesSpan"> <span id="1">1</span> <a href="183186_2.html">2</a></span></div>
<div class="ad7"><script language="javascript" src="/ad/2010/article/ad7.js"></script></div>
<div class="ad8"><script language="javascript" src="/ad/2010/article/ad8.js"></script></div>
<div class="index_main_err">如果图片或页面不能正常显示请<a href="javascript:void(0)" onClick="ReportError()" class= "redlink"><font color="#990000"><strong>点击这里</strong></font></a></div>
</div>
<div class="index_main_left_foot">
<div class="index_main_left_foot1">
<p><a href="javascript:window.external.addFavorite(self.location,document.title);">【收藏此页】</a><a href="http://bbs.firnow.com" target="_blank">【飞诺社区】</a><a href="#comment">【发表评论】</a><a href="javascript:window.close()">【关闭】</a></p>
<a href="#comment"><img src="/images/2010/article/ping.gif" width="149" height="34" border="0" /></a>
</div>
<div class="index_main_left_foot2">
<p>上一篇:<a href="/course/3_program/java/javajs/20091122/183185.html">java中涉及构造器的相关问题</a></p>
<p>下一篇:<a href="/course/3_program/java/javajs/20091122/183187.html">监听用户离线,自定义离线时间</a></p>
</div>
</div>
</div>
<div class="ad9"><script language="javascript" src="/ad/2010/article/ad9.js"></script></div>
<div class="index_main_left_3">Java技术文章推荐文章</div>
<div class="index_main_left_4">
<ul>
<li><a href="/course/3_program/java/javajs/2008710/132607.html" target="_blank">Eclipse 编译错误问题解决</a></li>
<li><a href="/course/3_program/java/javajs/200824/98544.html" target="_blank">Hibernate3.x调用存储过程 </a></li>
<li><a href="/course/3_program/java/javajs/2008313/104430.html" target="_blank">面向 Java 开发人员的 db4o 指南: 超越简单对象,使用 db4o 创建、更新与删除结构化对象</a></li>
<li><a href="/course/3_program/java/javajs/2007128/91108.html" target="_blank">Solaris shell脚本</a></li>
<li><a href="/course/3_program/java/javajs/2008325/107299.html" target="_blank">Java 5.0 Generics</a></li>
<li><a href="/course/3_program/java/javajs/20091112/182214.html" target="_blank">基于Java的数据库连接池技术研究</a></li>
<li><a href="/course/3_program/java/javajs/20100107/187388.html" target="_blank">Struts 2杂谈(2):如何向标签文件中的Struts 2标签传递参数值</a></li>
<li><a href="/course/3_program/java/javajs/20100106/186819.html" target="_blank">Java线程:新特征-阻塞队列</a></li>
</ul>
<ul>
<li><a href="/course/3_program/java/javajs/200896/139343.html" target="_blank"> JAVA代码:通过Socket执行HTTP的GET方法</a></li>
<li><a href="/course/3_program/java/javajs/20091120/183028.html" target="_blank">java.IO搜索指定文件</a></li>
<li><a href="/course/3_program/java/javajs/200818/96005.html" target="_blank">连接池与使用Tomcat的连接池</a></li>
<li><a href="/course/3_program/java/javajs/20081012/150137.html" target="_blank"> 基于Eclipse RCP的油田开发决策支持系统(一)</a></li>
<li><a href="/course/3_program/java/javajs/200899/141527.html" target="_blank">Hibernate 使用DB2 for Z/OS 序列 的一个BUG</a></li>
<li><a href="/course/3_program/java/javajs/20090302/156398.html" target="_blank">详细讲解Java中log4j的使用方法</a></li>
<li><a href="/course/3_program/java/javajs/20091006/178011.html" target="_blank">NHibernate的各种保存方式的区别 (save,persist,update,saveOrUp</a></li>
<li><a href="/course/3_program/java/javajs/20090407/164588.html" target="_blank">Integer</a></li>
</ul>
</div>
<div class="index_main_left_5">
<div class="index_main_left_5_top"><p><a name="comment"></a>文章评论</p></div>
<div id="divComment" class="index_main_left_5_main"></div>
</div>
<div class="index_main_left_6">
<div class="index_main_left_6_left">
<div class="index_main_left_6_left_top">请您留言</div>
<div class="index_main_left_6_left_ceneter">
<form>
<table width="84%" height="216" border="0" cellpadding="10">
<tr>
<td width="19%" height="29">昵称:</td>
<td width="81%"><label>
<input type="text" class="index_main_left_6_left_ceneter_text" style="width:150px;" name="tbName" id="tbName" onclick="this.focus();this.select()" maxlength="20" />
</label></td>
</tr>
<tr>
<td>验证码:</td>
<td>
<span style="float:left;"><input name="tbCode" id="tbCode" class="index_main_left_6_left_ceneter_text" type="text" size="6" /></span><span id="spanCode" style="float:left; clear:right;"><img id="Img2" onclick="this.src=this.src" style="display:none;"/></span>
</tr>
<tr>
<td height="26" colspan="2"><a href="http://bbs.firnow.com/register.aspx" style="color:#FF0000">注册会员</a> <a href="http://bbs.firnow.com/login.aspx">会员登录</a></td>
</tr>
<tr>
<td height="100" colspan="2"><label>
<a name="comment"></a><textarea name="tbContent" id="tbContent" class="index_main_left_6_left_ceneter_textarea" rows="5">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值