文章目录

  • 1.监听器Listener概述
  • 2.第一类:监听域对象的生命周期
    • 3.1.ServletContextListener
      • 3.1.1.案例1:任务调度(使用 Timer和TimerTask)
    • 3.2.HttpSessionListener
      • 3.2.1.全网在线人数统计
  • 3.第二类:监听值变化
    • 3.1.ServletContextAttributeListener
    • 3.2.HttpSessionAttributeListener
    • 3.3.ServletRequestAttributeListener
  • 4.监听器小结
  • 5.第三类:监听HttpSession中的对象的(JavaBean)面试题
    • 5.1.HttpSessionBindingListener
    • 5.2.HttpSessionActivationListener 监听session钝化和活化

1.监听器Listener概述

监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

监听器是一个对象,用来监听另一个对象的变化。

例如:
汽车上,安装一个报警器。
监听其他对象的对象叫做监听器。
被监听的对象叫做事件源。
报警器就是一个监听器。
汽车就是事件源。

 触发  踹一脚汽车。

监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行.

2.第一类:监听域对象的生命周期

JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSessionServletRequest等域对象的创建与销毁事件。

域对象 类型 范围
Request HttpServletRequest 一次请求中有效 (转发)
Session HttpSession 一次会话中有效
Application ServletConext 整个应用APP有效 存储的数据所有用户共享

3.1.ServletContextListener

ServletContextListener接口用于监听ServletContext对象的创建和销毁事件。实现了ServletContextListener接口的类都可以对ServletContext对象的创建和销毁进行监听。

当ServletContext对象被创建时,激发contextInitialized (ServletContextEvent sce)方法。
当ServletContext对象被销毁时,激发contextDestroyed(ServletContextEvent sce)方法。

  • 范例:编写一个MyServletContextListener类,实现ServletContextListener接口,监听ServletContext对象的创建和销毁
public class MyServletContextListener implements ServletContextListener {public void contextInitialized(ServletContextEvent arg0) {System.out.println("ServletContext 出生了....");}public void contextDestroyed(ServletContextEvent arg0) {// ServletContext销毁时调用的方法System.out.println("ServletContext 升天了....");}
}
  • 在web.xml文件中注册监听器
    要想监听事件源,那么必须将监听器注册到事件源上才能够实现对事件源的行为动作进行监听,在JavaWeb中,监听的注册是在web.xml文件中进行配置的,如下:
 <!-- 注册针对ServletContext对象进行监听的监听器 --><listener><!--实现了ServletContextListener接口的监听器类 --><listener-class>com.bruceliu.filter.MyServletContextListener</listener-class></listener>
  • 注解式配置
@WebListener
public class MyServletContextListener implements ServletContextListener {public void contextInitialized(ServletContextEvent arg0) {System.out.println("ServletContext 出生了....");}public void contextDestroyed(ServletContextEvent arg0) {// ServletContext销毁时调用的方法System.out.println("ServletContext 升天了....");}
}

3.1.1.案例1:任务调度(使用 Timer和TimerTask)

@WebListener
public class TimerListener implements ServletContextListener {public void contextInitialized(ServletContextEvent arg0) {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("发邮件....");}}, 5000, 2000);}public void contextDestroyed(ServletContextEvent arg0) {}
}

3.2.HttpSessionListener

HttpSessionListener 接口用于监听HttpSession对象的创建和销毁

创建一个Session时,激发sessionCreated (HttpSessionEvent se) 方法
销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se) 方法。

  • 范例:编写一个MyHttpSessionListener类,实现HttpSessionListener接口,监听HttpSession对象的创建和销毁
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {@Overridepublic void sessionCreated(HttpSessionEvent arg0) {// arg0.getSession(); 获取事件源System.out.println("Session创建了<<<<<");}@Overridepublic void sessionDestroyed(HttpSessionEvent arg0) {System.out.println("Session销毁<<<<<");}
}

HttpSession的销毁时机需要在web.xml中进行配置,如下:

<session-config><session-timeout>1</session-timeout>
</session-config>
  • 当我们访问jsp页面时,HttpSession对象就会创建,此时就可以在HttpSessionListener观察到HttpSession对象的创建过程了,我们可以写一个jsp页面观察HttpSession对象创建的过程。
    如下:index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>HttpSessionListener监听器监听HttpSession对象的创建</title>
</head>
<body>session已经创建对象:${pageContext.session.id}<br/><%=session.getId()%>
</body>
</html>

3.2.1.全网在线人数统计

所有用户看到的在线人数都是一样的!那么在线人数这个数据保存在哪里?
ServletContext对象中!

在线人数:session的个数,当用户访问服务器时,服务器就会为当前用户创建一个session对象,因此session的个数就是在线人数!

实现思路:创建session对象的监听器,当session创建时,人数+1,销毁时,人数-1;

  • session的创建和销毁的监听器:
@WebListener
public class OnlineListener implements HttpSessionListener {public void sessionCreated(HttpSessionEvent hse) {// 从ServletContext对象中获取当前的在线人数ServletContext context = hse.getSession().getServletContext();Long online = (Long)context.getAttribute("online");// 判断online是否为null:说明是第一个用户if ( online == null ) {//online = 45751245L; // 初始化在线人数online = 0L; // 初始化在线人数}// 人数+1online++;context.setAttribute("online", online);}public void sessionDestroyed(HttpSessionEvent hse) {ServletContext context = hse.getSession().getServletContext();Long online = (Long)context.getAttribute("online");context.setAttribute("online", --online);}
}
  • 显示在线人数的online.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>当前的在线人数是:${online }
</body>
</html>

3.第二类:监听值变化

域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信息事件的监听器。
这三个监听器接口分别是ServletContextAttributeListener, HttpSessionAttributeListenerServletRequestAttributeListener,这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。

3.1.ServletContextAttributeListener

  • 编写ServletContextAttributeListener监听器监听ServletContext域对象的属性值变化情况,代码如下:
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {@Overridepublic void attributeAdded(ServletContextAttributeEvent scab) {String str = MessageFormat.format("ServletContext域对象中添加了属性:{0},属性值是:{1}", scab.getName(), scab.getValue());System.out.println(str);}@Overridepublic void attributeRemoved(ServletContextAttributeEvent scab) {String str = MessageFormat.format("ServletContext域对象中删除属性:{0},属性值是:{1}", scab.getName(), scab.getValue());System.out.println(str);}@Overridepublic void attributeReplaced(ServletContextAttributeEvent scab) {String str = MessageFormat.format("ServletContext域对象中替换了属性:{0}的值", scab.getName());System.out.println(str);}
}
  • 编写test.jsp测试页面
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>ServletContextAttributeListener监听器测试</title>
</head><body><%//往application域对象中添加属性application.setAttribute("name", "哈哈");//替换application域对象中name属性的值application.setAttribute("name", "呵呵");//移除application域对象中name属性application.removeAttribute("name");%>
</body>
</html>

3.2.HttpSessionAttributeListener

@WebListener
public class MySessionAttrListener implements HttpSessionAttributeListener {@Overridepublic void attributeAdded(HttpSessionBindingEvent se) {String str = MessageFormat.format("HttpSession域对象中添加了属性:{0},属性值是:{1}", se.getName(), se.getValue());System.out.println(str);}@Overridepublic void attributeRemoved(HttpSessionBindingEvent se) {String str = MessageFormat.format("HttpSession域对象中删除属性:{0},属性值是:{1}", se.getName(), se.getValue());System.out.println(str);}@Overridepublic void attributeReplaced(HttpSessionBindingEvent se) {String str = MessageFormat.format("HttpSession域对象中替换了属性:{0}的值", se.getName());System.out.println(str);}
}
  • 编写test1.jsp测试页面
<html>
<head>
<title>ServletContextAttributeListener监听器测试</title>
</head><body><%//往session域对象中添加属性session.setAttribute("aa", "bb");//替换session域对象中aa属性的值session.setAttribute("aa", "xx");//移除session域对象中aa属性session.removeAttribute("aa");%>
</body>
</html>

3.3.ServletRequestAttributeListener

@WebListener
public class MyRequestAttributeListener implements ServletRequestAttributeListener {@Overridepublic void attributeAdded(ServletRequestAttributeEvent srae) {String str = MessageFormat.format("ServletRequest域对象中添加了属性:{0},属性值是:{1}", srae.getName(), srae.getValue());System.out.println(str);}@Overridepublic void attributeRemoved(ServletRequestAttributeEvent srae) {String str = MessageFormat.format("ServletRequest域对象中删除属性:{0},属性值是:{1}", srae.getName(), srae.getValue());System.out.println(str);}@Overridepublic void attributeReplaced(ServletRequestAttributeEvent srae) {String str = MessageFormat.format("ServletRequest域对象中替换了属性:{0}的值", srae.getName());System.out.println(str);}
}
  • 编写test2.jsp测试页面
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>ServletContextAttributeListener监听器测试</title>
</head><body><%//往request域对象中添加属性request.setAttribute("aa", "bb");//替换request域对象中aa属性的值request.setAttribute("aa", "xx");//移除request域对象中aa属性request.removeAttribute("aa");%>
</body>
</html>

4.监听器小结

5.第三类:监听HttpSession中的对象的(JavaBean)面试题

前两类监听器是作用在 ServletContext HttpSession ServletRequest上的,第三类监听器是作用在JavaBean上的。
这类监听器不需要在web.xml中配置。

5.1.HttpSessionBindingListener

实现了HttpSessionBindingListener接口的JavaBean对象可以感知自己被绑定到Session中和 Session中删除的事件

当对象被绑定到HttpSession对象中时,web服务器调用该对象的void valueBound(HttpSessionBindingEvent event)方法
当对象从HttpSession对象中解除绑定时,web服务器调用该对象的void valueUnbound(HttpSessionBindingEvent event)方法

public class User implements HttpSessionBindingListener {private int id;private String name;public User() {}public User(int id, String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void valueBound(HttpSessionBindingEvent arg0) {System.out.println("对象绑定到了Session中");}public void valueUnbound(HttpSessionBindingEvent arg0) {System.out.println("对象从Session中移除");}
}

测试页面

<%@ page import="com.bruceliu.bean.User"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>ServletContextAttributeListener监听器测试</title>
</head><body><%User user = new User(1, "aaa");session.setAttribute("user", user);session.removeAttribute("user");%>
</body>
</html>

5.2.HttpSessionActivationListener 监听session钝化和活化

实现了HttpSessionActivationListener接口的JavaBean对象可以感知自己被活化(反序列化)和钝化(序列化)的事件.当绑定到HttpSession对象中的javabean对象将要随HttpSession对象被钝化(序列化)之前,web服务器调用该javabean对象的void sessionWillPassivate(HttpSessionEvent event) 方法。这样javabean对象就可以知道自己将要和HttpSession对象一起被序列化(钝化)到硬盘中.

当绑定到HttpSession对象中的javabean对象将要随HttpSession对象被活化(反序列化)之后,web服务器调用该javabean对象的void sessionDidActive(HttpSessionEvent event)方法。这样javabean对象就可以知道自己将要和 HttpSession对象一起被反序列化(活化)回到内存中

放在Session中的 没有实现Serilizable接口的对象,在Session钝化时,不会被序列化到磁盘上。

public class Person implements Serializable, HttpSessionActivationListener {private int id;private String name;public Person() {}public Person(int id, String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void sessionDidActivate(HttpSessionEvent arg0) {// 活化System.out.println("对象被活化......");}public void sessionWillPassivate(HttpSessionEvent arg0) {// 钝化System.out.println("对象被钝化.......");}
}

为了观察绑定到HttpSession对象中的javabean对象随HttpSession对象一起被钝化到硬盘上和从硬盘上重新活化回到内存中的的过程,我们需要借助tomcat服务器帮助我们完成HttpSession对象的钝化和活化过程,具体做法如下:

在WebRoot\META-INF文件夹下创建一个context.xml文件,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Context><!-- maxIdleSwap:1 session如果1分钟没有使用 就序列化. directory:序列化后 文件所保存的路径. --><Manager className="org.apache.catalina.session.PersistentManager"maxIdleSwap="1"><Store className="org.apache.catalina.session.FileStore" directory="bruce123" /></Manager>
</Context>

在context.xml文件文件中配置了1分钟之后就将HttpSession对象钝化到本地硬盘的一个bruce123文件夹中

jsp测试代码如下:

<%@page import="com.bruceliu.bean.Person"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>测试</title>
</head><body><%Person p = new Person(1, "zhangsan");session.setAttribute("p", p);%>
</body>
</html>

访问这个jsp页面,服务器就会马上创建一个HttpSession对象,然后将实现了HttpSessionActivationListener接口的JavaBean对象绑定到session对象中,这个jsp页面在等待1分钟之后没有人再次访问,那么服务器就会自动将这个HttpSession对象钝化(序列化)到硬盘上,我们可以在tomcat服务器文件夹下找到序列化到本地存储的session,如下图所示:

当再次访问这个Jsp页面时,服务器又会自动将已经钝化(序列化)到硬盘上HttpSession对象重新活化(反序列化)回到内存中。运行结果如下:

JavaWeb开发专题-监听器相关推荐

  1. JavaWeb开发专题(一)-JavaWeb入门

    1.JavaEE的概念 Java Enterprice Edtion(Java企业版).JavaEE并不是一个具体的技术.而是由SUN公司提出的一个Java 企业级开发的平台,是一种标准.其中包含13 ...

  2. JavaWEB开发-Servlet事件监听器

    JavaWEB开发-Servlet事件监听器 l  监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法 ...

  3. java面试(二十六)--(1)J2EE中常用名词(2)讲一下redis的主从复制怎么做的?(3)请谈谈你对Javaweb开发中的监听器的理解?(4)按之字形顺序打印二叉树(5)内部类大全

    1.J2EE中常用名词 web容器:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使 JSP,SERVLET直接跟容器中的环境变量接**互,不必关注其它系统问题.主要有WEB服务器来 ...

  4. 深入体验JavaWeb开发内幕——简述JSP中的自定义标签叫你快速学会

    转载自   深入体验JavaWeb开发内幕--简述JSP中的自定义标签叫你快速学会 自定义标签,顾名思义,就是自己定义的标签.那么我们为什么要自己定义一些标签呢? 我们知道,如果要在JSP中获取数据我 ...

  5. Javaweb开发了解前端知识七、Servlet(一)

    1.Servlet技术 2.Servlet类的继承体系 3.ServletConfig类 4.ServletContext类 1.Servlet技术 a) 什么是Servlet Servlet是jav ...

  6. JavaWeb 开发 06 —— smbms项目实践

    系列文章 JavaWeb 开发 01 -- 基本概念.Web服务器.HTTP.Maven JavaWeb 开发 02 -- ServletContext.读取资源.下载文件.重定向和请求转发 Java ...

  7. JavaWeb开发一

    javaWeb 1.基本概念 1.1 前言 web开发: web:网页 www.baidu.com 静态web:html,css 提供给所有人看的数据不会发生变化 动态web 发生变化,每个人在不同的 ...

  8. 最详细的JavaWeb开发基础之java环境搭建(Windows版)

    首先欢迎大家来学习JavaWeb,在这里会给你比较详细的教程,从最基本的开始,循序渐进的深入.会让初学者的你少踩很多坑(大实话),如果你已经掌握了JavaWeb开发的基础部分,请耐心等待后续的进阶阶段 ...

  9. JavaWeb学习总结(一)——JavaWeb开发入门(转载)

    一.基本概念 1.1.WEB开发的相关知识 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资源分为: 静态web资源( ...

最新文章

  1. Redis源码分析:AOF策略与时间触发任务
  2. php 的包管理工具 composer
  3. Hadoop完全分布式HA环境搭建
  4. Martix工作室考核题 —— 输入一串数字,按要求打印。
  5. 磁盘分区原理:从MBR到GPT
  6. Java是否越来越接受静态导入?
  7. SRV记录注册不成功的可能的原因
  8. CAN和CANOpen的关系
  9. PHP5: mysqli 插入, 查询, 更新和删除 Insert Update Delete Using mysqli (CRUD)
  10. 【Linux】Mac在VMware中安装ubuntu教程和安装时遇到键盘鼠标失效等问题的解决方案
  11. 数据结构严蔚敏4.7习题2应用题(1)
  12. 电子海图与雷达图像的融合显示
  13. Python基础 Day03 列表
  14. 百度快照劫持的解决方法
  15. 得到头条【四线城市宜宾,靠什么逆袭?】
  16. Android一键锁屏与抬手亮屏的实现
  17. 设计新鲜事(News Feed)系统
  18. 图可视化工具Gephi使用教程
  19. C# 提取Word文档中的图片(用Spire)
  20. 企业中台最佳实践--阿里数据中台最佳实践(九)

热门文章

  1. 《React-Native系列》44、基于多个TextInput的键盘遮挡处理方案优化
  2. 美味奇缘_新美味终于来了
  3. 打开虚拟机左上角会弹出大小写切换的图标
  4. 又是推公式推到头晕的一天
  5. Android笔记(翻译):card.io SDK for Android银行卡扫描
  6. android版本对so支持,Android so文件兼容之abiFilters的使用
  7. 大学计算机基础课程 研究,非计算机专业“大学计算机基础”课程教学研究
  8. 显卡导致Ubuntu无法启动
  9. [opencv] 伪彩色和彩虹图
  10. python for循环求和_pythonfor循环语句求和