在java web应用中,listener监听器似乎是不可缺少的。经常常使用来监听servletContext、httpSession、servletRequest等域对象的创建、销毁以及属性的变化等等,能够在这些事件动作前后进行一定的逻辑处理。

比較经常使用的应用场景是利用监听器来初始化一些数据、统计在线人数、统计web应用浏览量等等。

这里所说的监听器实际上是servlet规范中定义的一种特殊类,须要实现特定的接口。 
而我临时先说当中三个用来监听域对象的,各自是servletContextListener、httpSessionListener、servletRequestListener。 
这三个接口写法上实际是几乎相同的。都有两个分别代表了该域对象创建时调用和销毁时调用的方法。据我的理解,这三个对象最大的差别应该就是作用域不一样。

servletContext在整个应用启动到结束中生效。启动系统时创建这个对象,整个过程中这个对象是唯一的。 
httpSession则是在一个session会话中生效,在一个session被创建直到失效的过程中都起作用,只是一个启动的应用中httpSession对象能够有多个,比方同一台电脑两个浏览器訪问。就会创建两个httpSession对象。 
而servletRequest是在一个request请求被创建和销毁的过程中生效,每发起一次请求就会创建一个新的servletRequest对象,比方刷新浏览器页面、点击应用的内链等等。 
这三个监听器的写法基本例如以下伪代码所看到的: 
首先创建一个监听器类实现对应的接口及方法:

package packageName;
public class ListenerName implements *Listener { @Override
public void 对象创建时被调用的方法(对应的事件 arg0) { } @Override
public void 对象销毁时被调用的方法(对应的事件 arg0) { }
}

然后在web.xml中注冊:

<listener>
<listener-class>packageName.ListenerName</listener-class>
</listener>

到这里,基本上这个监听器在启动web服务器以后就能够正常跑了,仅仅是有时候我们还会在注冊监听器的时候配置一些其它的。 
比方配置servletContextListener的时候,可能会加上context-param參数:

<context-param>
<param-name>paramName</param-name>
<param-value>paramValue</param-value>
</context-param>

配置httpSessionListener的时候,可能会加上session超时:

<session-config>
<session-timeout>1</session-timeout>
</session-config>

我感觉经过这样一整理后,就会发现起始监听器写起来还是非常easy的。于是便模拟简单的实现了在线用户统计和应用訪问量,基本代码例如以下: 
首先是实现了servletContext

package webTest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; public class ListenerTest1 implements ServletContextListener { @Override
public void contextDestroyed(ServletContextEvent arg0) { System.out.println("contextDestroyed" + "," + new Date());
Object count = arg0.getServletContext().getAttribute("count");
File file = new File("count.txt");
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(count.toString());
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("contextInitialized" + "," + new Date());
File file = new File("count.txt");
if (file.exists()) {
try {
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
BufferedReader bReader = new BufferedReader(inputStreamReader);
String count = bReader.readLine();
System.out.println("历史訪问次数:" + count);
arg0.getServletContext().setAttribute("count", count);
bReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

这里我把訪问次数存在一个txt文件里。以便于持久化保存。当项目启动的时候。也就是创建servletContext对象的时候调用载入方法。从txt文件里读取历史訪问量,然后使用setAttribute方法把这个数据存入到内存中。 
之后当应用被关闭,servletContext对象被销毁的时候把内存中新的訪问量数据覆盖写入到txt文件。以便于下次启动应用后继续读取之前的訪问量。 
然后使用servletRequestListener来实现web浏览量的变化,当然了。这里仅仅是简单的实现,假设是要实现那种同一个用户刷新页面不添加浏览量的功能,还须要做很多其它的处理。

package webTest;
import java.util.Date;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener; public class ListenerTest3 implements ServletRequestListener { @Override
public void requestDestroyed(ServletRequestEvent arg0) {
System.out.println("requestDestroyed" + "," + new Date());
System.out.println("当前訪问次数:" + arg0.getServletContext().getAttribute("count"));
} @Override
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("requestInitialized" + "," + new Date());
Object count = arg0.getServletContext().getAttribute("count");
Integer cInteger = 0;
if (count != null) {
cInteger = Integer.valueOf(count.toString());
}
System.out.println("历史訪问次数::" + count);
cInteger++;
arg0.getServletContext().setAttribute("count", cInteger);
} }

这里相同是两个方法,在servletRequest对象被建立的时候调用初始化方法。从内存中读取servletContext对象的count属性,而后输出历史訪问量。

同一时候在此基础上加一又一次设置servletContext对象的count属性的内容。当servletRequest对象被销毁的时候调用销毁时的方法打印出当前浏览量。这样就简单的实现了web浏览的量的累加计数。 
然后就是利用httpSessionListener来实如今线人数的统计:

package webTest;
import java.util.Date;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; public class ListenerTest2 implements HttpSessionListener { @Override
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("sessionCreated" + "," + new Date());
Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
Integer count = 0;
if (lineCount == null) {
lineCount = "0";
}
count = Integer.valueOf(lineCount.toString());
count++;
System.out.println("新上线一人,历史在线人数:" + lineCount + "个,当前在线人数有: " + count + " 个");
arg0.getSession().getServletContext().setAttribute("lineCount", count);
} @Override
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("sessionDestroyed" + "," + new Date());
Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
Integer count = Integer.valueOf(lineCount.toString());
count--;
System.out.println("一人下线,历史在线人数:" + lineCount + "个。当前在线人数: " + count + " 个");
arg0.getSession().getServletContext().setAttribute("lineCount", count);
} }

这里的代码都非常easy。太多必要解释,须要说明的是。这里把lineCount存放在servletContext对象中并非唯一的方式,有兴趣的朋友能够尝试其它的方式。比如使用类属性。

最新文章

  1. 跳转时候提示Attempt to present on while a presentation is in progress
  2. Xcode7 Cocoapods 安装或更新出现错误
  3. jQuery实现购物车多物品数量的加减+总价计算
  4. Divide and conquer:Matrix(POJ 3685)
  5. Nginx_Lua
  6. 人们对Python在企业级开发中的10大误解
  7. 锋利的jQuery第2版学习笔记8~11章
  8. 8款功能强大的最新HTML5特效实例
  9. html&amp;nbsp;&amp;nbsp;特殊字符(转)
  10. 浅谈c语言程序为什么需要内存 栈又是什么?
  11. C/C++基本数据类型
  12. android媒体--图库与API层MediaPlayer的交互
  13. VR上天了!全景商业化落地了!——VR全景智慧城市
  14. linux常用命令汇总(更新中...)
  15. mysql 及 posgresql之优劣势大比拼
  16. [Swift]LeetCode326. 3的幂 | Power of Three
  17. python 操作RabbitMq详解
  18. Atcoder Grand Contest 032
  19. 从SQLServer转储数据到MySQL
  20. uboot常用的函数

热门文章

  1. maven的安装和配置
  2. js中的数值转换
  3. leetcode105
  4. ios unicode
  5. Spring学习整理
  6. linux启动http服务
  7. 【转载】我为什么弃用OpenStack转向VMware vsphere
  8. Robotics Tools
  9. java特殊字符分隔符
  10. Blast