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

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

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

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

  1. package packageName;
  2. public class ListenerName implements *Listener {
  3.  
  4. @Override
  5. public void 对象创建时被调用的方法(对应的事件 arg0) {
  6.  
  7. }
  8.  
  9. @Override
  10. public void 对象销毁时被调用的方法(对应的事件 arg0) {
  11.  
  12. }
  13. }

然后在web.xml中注冊:

  1. <listener>
  2. <listener-class>packageName.ListenerName</listener-class>
  3. </listener>

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

  1. <context-param>
  2. <param-name>paramName</param-name>
  3. <param-value>paramValue</param-value>
  4. </context-param>

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

  1. <session-config>
  2. <session-timeout>1</session-timeout>
  3. </session-config>

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

  1. package webTest;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.File;
  6. import java.io.FileInputStream;
  7. import java.io.FileOutputStream;
  8. import java.io.IOException;
  9. import java.io.InputStreamReader;
  10. import java.io.OutputStreamWriter;
  11. import java.util.Date;
  12. import javax.servlet.ServletContextEvent;
  13. import javax.servlet.ServletContextListener;
  14.  
  15. public class ListenerTest1 implements ServletContextListener {
  16.  
  17. @Override
  18. public void contextDestroyed(ServletContextEvent arg0) {
  19.  
  20. System.out.println("contextDestroyed" + "," + new Date());
  21. Object count = arg0.getServletContext().getAttribute("count");
  22. File file = new File("count.txt");
  23. try {
  24. FileOutputStream fileOutputStream = new FileOutputStream(file);
  25. OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
  26. BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
  27. bufferedWriter.write(count.toString());
  28. bufferedWriter.close();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33.  
  34. @Override
  35. public void contextInitialized(ServletContextEvent arg0) {
  36. System.out.println("contextInitialized" + "," + new Date());
  37. File file = new File("count.txt");
  38. if (file.exists()) {
  39. try {
  40. FileInputStream fileInputStream = new FileInputStream(file);
  41. InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
  42. BufferedReader bReader = new BufferedReader(inputStreamReader);
  43. String count = bReader.readLine();
  44. System.out.println("历史訪问次数:" + count);
  45. arg0.getServletContext().setAttribute("count", count);
  46. bReader.close();
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }
  52. }

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

  1. package webTest;
  2. import java.util.Date;
  3. import javax.servlet.ServletRequestEvent;
  4. import javax.servlet.ServletRequestListener;
  5.  
  6. public class ListenerTest3 implements ServletRequestListener {
  7.  
  8. @Override
  9. public void requestDestroyed(ServletRequestEvent arg0) {
  10. System.out.println("requestDestroyed" + "," + new Date());
  11. System.out.println("当前訪问次数:" + arg0.getServletContext().getAttribute("count"));
  12. }
  13.  
  14. @Override
  15. public void requestInitialized(ServletRequestEvent arg0) {
  16. System.out.println("requestInitialized" + "," + new Date());
  17. Object count = arg0.getServletContext().getAttribute("count");
  18. Integer cInteger = 0;
  19. if (count != null) {
  20. cInteger = Integer.valueOf(count.toString());
  21. }
  22. System.out.println("历史訪问次数::" + count);
  23. cInteger++;
  24. arg0.getServletContext().setAttribute("count", cInteger);
  25. }
  26.  
  27. }

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

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

  1. package webTest;
  2. import java.util.Date;
  3. import javax.servlet.http.HttpSessionEvent;
  4. import javax.servlet.http.HttpSessionListener;
  5.  
  6. public class ListenerTest2 implements HttpSessionListener {
  7.  
  8. @Override
  9. public void sessionCreated(HttpSessionEvent arg0) {
  10. System.out.println("sessionCreated" + "," + new Date());
  11. Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
  12. Integer count = 0;
  13. if (lineCount == null) {
  14. lineCount = "0";
  15. }
  16. count = Integer.valueOf(lineCount.toString());
  17. count++;
  18. System.out.println("新上线一人,历史在线人数:" + lineCount + "个,当前在线人数有: " + count + " 个");
  19. arg0.getSession().getServletContext().setAttribute("lineCount", count);
  20. }
  21.  
  22. @Override
  23. public void sessionDestroyed(HttpSessionEvent arg0) {
  24. System.out.println("sessionDestroyed" + "," + new Date());
  25. Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
  26. Integer count = Integer.valueOf(lineCount.toString());
  27. count--;
  28. System.out.println("一人下线,历史在线人数:" + lineCount + "个。当前在线人数: " + count + " 个");
  29. arg0.getSession().getServletContext().setAttribute("lineCount", count);
  30. }
  31.  
  32. }

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

<Listener>servletContextListener、httpSessionListener和servletRequestListener使用整理的更多相关文章

  1. java中servletContextListener、httpSessionListener和servletRequestListener使用整理

    在java web应用中,listener监听器似乎是必不可少的,常常用来监听servletContext.httpSession.servletRequest等域对象的创建.销毁以及属性的变化等等, ...

  2. 监听域对象创建和销毁的Listener

    1.什么是Servlet监听器? 先来看看什么是监听器.监听器是专门用于对其它对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时立即采取相应的行动.Servlet监听器是S ...

  3. [原创]java WEB学习笔记47:Servlet 监听器简介, ServletContext(Application 对象), HttpSession (Session 对象), HttpServletRequest (request 对象) 监听器,利用listener理解 三个对象的生命周期

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  4. JavaWeb学习笔记--Listener

    JSP中的监听器   Web程序在服务器运行的过程中,程序内部会发生多事件,如Web应用的启动和停止.Session会话的开始和销毁.用户请求的开始和结束等等.有时程序员需要在这些事件发生的时机执行一 ...

  5. JavaWeb之Listener监听器

    监听在Java体系中运用的很广泛,在安卓开发.JavaWeb开发中到处存在,在其他语言也有类似的,如果有了解过设计模式那很容易理解实现的原理.不过对于开发者来说,使用观察者模式只需实现相应的接口就好, ...

  6. javaWeb学习总结(11)- 监听器(Listener)学习

    一.监听器介绍 1.1.监听器的概念 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其 实就是一个实现特定接口的普 ...

  7. Filter、Listener 学习总结

    今天我们来介绍 Filter.Listener 这两个模块一些简单的知识和应用,接下来我们开始我们的正题 ! 1. Filter(过滤器) 1.1 对 Servlet 容器调用 Servlet 的过程 ...

  8. Servlet - Listener、Filter、Decorator

    Servlet 标签 : Java与Web Listener-监听器 Listener为在Java Web中进行事件驱动编程提供了一整套事件类和监听器接口.Listener监听的事件源分为Servle ...

  9. 【转】监听器(Listener)学习

    一.监听器介绍 1.1.监听器的概念 监听器是一个专门用于对其它对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监听的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通 ...

随机推荐

  1. java——IO流01

    移动文件有一种简单方法,不需要复制文件再删除文件. package com.unir.test01; import java.io.File; import java.io.IOException; ...

  2. 深度学习原理与框架-递归神经网络-RNN_exmaple(代码) 1.rnn.BasicLSTMCell(构造基本网络) 2.tf.nn.dynamic_rnn(执行rnn网络) 3.tf.expand_dim(增加输入数据的维度) 4.tf.tile(在某个维度上按照倍数进行平铺迭代) 5.tf.squeeze(去除维度上为1的维度)

    1. rnn.BasicLSTMCell(num_hidden) #  构造单层的lstm网络结构 参数说明:num_hidden表示隐藏层的个数 2.tf.nn.dynamic_rnn(cell, ...

  3. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  4. jsonArray返回

    dao <select id="selectShopInfo" resultType="java.util.HashMap"> SELECT * F ...

  5. 用java语言构建一个网络服务器,实现客户端和服务器之间通信,实现客户端拥有独立线程,互不干扰

    服务器: 1.与客户端的交流手段多是I/O流的方式 2.对接的方式是Socket套接字,套接字通过IP地址和端口号来建立连接 3.(曾经十分影响理解的点)服务器发出的输出流的所有信息都会成为客户端的输 ...

  6. Junit介绍以及使用

    在介绍junit之前,把一些知识点提前了解一下 单元测试是一个对单一实体(类或方法)的测试. 测试用例(Test Case)是为某个特殊目标而编制的一组测试输入.执行条件以及预期结果,以便测试某个程序 ...

  7. linux下redis4.0.2集群部署(利用原生命令)

    一.部署架构如下 每台服务器准备2个节点,一主一从,主节点为另外两台其中一台的主,从节点为另外两台其中一台的从. 二.准备6个节点配置文件 在172.28.18.75上操作 cd /etc/redis ...

  8. Selenium WebDriver 对Cookie进行处理绕过登录验证码

    首先需要手动登录一次你的测试网站,去Chrome的F12中获取这个网站的cookie信息,找到对应的保存登录信息的cookie,接下来在代码中将上述的cookie信息通过webdriver写入的自动化 ...

  9. Python学习—基础篇之基本数据类型(一)

    数据类型 在python中,能够直接处理的基本数据类型主要有数字类型.字符串类型.字节类型.布尔类型.列表.元组.字典.集合等. 一.数字类型 1.1 数字类型的创建 # 数字类型 a = 10 b ...

  10. 定义一个包含标签inclusion_tag, 调用模板时报错.. 应该是路径 不对吧...我的templates 是放在app 目录下的.<待处理>

    # 自定义模板标签. 标签的作用,在模板中 实现逻辑,如if ,for 等 from django.template import Library from datetime import datet ...