文章目录

  • 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. python中常见的流程结构-Python分支结构(switch)操作简介
  2. PAT甲级1058 A+B in Hogwarts :[C++题解]字符串,进制,简单
  3. 一文介绍 Mysql 索引模型 B+ 树
  4. sscanf 的应用noj——663弟弟的作业
  5. tar 压缩与解压缩打包命令
  6. python对Excel的操作 xlrd、xlwt包详解
  7. mysql 配置自动截断_MySql超长自动截断实例详解
  8. Centos镜像使用帮助
  9. python pandas 处理相同标题的csv文件_Python使用pandas处理CSV文件的实例讲解
  10. java Session生命周期讨论
  11. winform遍历bartender_C# 调用Bartender打印的2种方式
  12. window强制删除文件bat
  13. 2021年茶艺师(中级)复审考试及茶艺师(中级)模拟考试题
  14. 这几款app疫情期间活跃度为何如此高?方法太可了吧
  15. 第二章 马尔可夫决策过程及表格型方法
  16. 【小程序】小程序托管平台的功能展望与想法
  17. 2021赤峰二中高考成绩查询,2021年赤峰高考状元名单公布,赤峰文理科状元是谁多少分...
  18. 计算机网络知识全面讲解:电子邮件发送和接收的过程
  19. 统计员工信息c语言设计,工资信息管理系统C语言设计
  20. 2022值得入手的运动装备有哪些?618超值得买合集

热门文章

  1. 推荐一个 Python 手绘图形库
  2. [图文教程] 包车预约App - 用小白接口快速开发App
  3. idea取消每次打开上次项目
  4. Android项目实战系列—基于博学谷(七)课程模块(下)
  5. 儿时的游戏,你还记得多少?谨以此献给80年以前出生那一代人,80年以后出生的勿入!
  6. ElasticSearch进行进行权限验证
  7. 距离大决战777天——目前的进度
  8. 原达摩院大模型 M6 带头人杨红霞离职!
  9. 与领导说话要注意的几个方法
  10. 福大软工 · 第七次作业 - 需求分析报告(404 Note Found队)