文章目录
- 初识监听器
- Listener接口分类
- ServletContext监听器
- HttpSession监听器
- ServletRequest监听器
- Java代码实现
- ServletContextListener
- ServletContextAttributeListener
- HttpSessionListener
- HttpSessionAttributeListener
- HttpSessionActivationListener
- HttpSessionBindingListener
- ServletRequestListener
- ServletRequestAttributeListener
- 模仿监听器Demo
初识监听器
== 什么是监听器==
监听器也叫Listener,是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。
监听器,字面上的理解就是监听观察某个事件(程序)的发生情况,当被监听的事件真的发生了的时候,事件发生者(事件源) 就会给注册该事件的监听者(监听器)发送消息,告诉监听者某些信息,同时监听者也可以获得一份事件对象,根据这个对象可以获得相关属性和执行相关操作。
监听器模型涉及以下三个对象,模型图如下:
- (1)事件:用户对组件的一个操作,或者说程序执行某个方法,称之为一个事件,如机器人程序执行工作。
- (2)事件源:发生事件的组件就是事件源,也就是被监听的对象,如机器人可以工作,可以跳舞,那么就可以把机器人看做是一个事件源。
- (3)事件监听器(处理器):监听并负责处理事件的方法,如监听机器人工作情况,在机器人工作前后做出相应的动作,或者获取机器人的状态信息。
执行顺序如下:
1、给事件源注册监听器。
2、组件接受外部作用,也就是事件被触发。
3、组件产生一个相应的事件对象,并把此对象传递给与之关联的事件处理器。
4、事件处理器启动,并执行相关的代码来处理该事件。
java监听器监听的内容是什么?监听器作用在哪个事件上?是在哪配置的监听内容的?
首先,监听器要怎么实现?
Java事件由事件类和监听接口组成,自定义一个事件前,必须提供一个事件的监听接口以及一个事件类。JAVA中监听接口是继承java.util.EventListener的类,事件类继承java.util.EventObject的类。很多基本的事件系统已经为我们定义好了,我们只要学会调用即可,但是为了更加灵活地满足特定的需求,我们有时候也需要自定义事件。
监听器的实质是什么?
一个类实现某个监听器接口,然后实现接口对应的方法,达到监听具体事项的动作。
Listener接口分类
监听器的接口有哪些?
监听器接口分三类:ServletContext,HttpSession,ServletRequest。
ServletContext监听器
ServletContext
- ServletContextListener 监听ServletContext对象
- ServletContextAttributeListener 监听对ServletContext属性的操作,比如说增加,删除,修改
HttpSession监听器
HttpSession
- HttpSessionListener 监听Session对象
- HttpSessionAttributeListener 监听Session的属性操作
- HttpSessionActivationListener 监听HTTP会话的active和passivate情况,passivate是指非活动的session被写入持久设备(如硬盘),active相反。
- HttpSessionBindingListener 监听器感知Session绑定的事件监听器
注意:Servlet 规范中定义了两个特殊的监听器接口"HttpSessionBindingListener和HttpSessionActivationListener"来帮助JavaBean
对象了解自己在Session域中的这些状态: ,实现这两个接口的类不需要 web.xml 文件中进行注册。
HttpSessionActivationListener 监听
实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件
活化:javabean对象和Session一起被反序列化(活化)到内存中(硬盘到内存);
钝化:javabean对象和Session一起序列化到硬盘中(内存到硬盘);
javabean对象存在Session中,当服务器把session序列化到硬盘上时,如果Session中的javabean对象实现了Serializable接口
那么服务器会把session中的javabean对象一起序列化到硬盘上,javabean对象和Session一起被序列化到硬盘中的这个操作称之为钝化
如果Session中的javabean对象没有实现Serializable接口,那么服务器会先把Session中没有实现Serializable接口的javabean对象移除
然后再把Session序列化(钝化)到硬盘中;
当绑定到 HttpSession对象中的javabean对象将要随 HttpSession对象被钝化之前,
web服务器调用该javabean对象的 sessionWillPassivate方法,
这样javabean对象就可以知道自己将要和 HttpSession对象一起被序列化(钝化)到硬盘中
当绑定到HttpSession对象中的javabean对象将要随 HttpSession对象被活化之后,
web服务器调用该javabean对象的sessionDidActive方法,
这样javabean对象就可以知道自己将要和 HttpSession对象一起被反序列化(活化)回到内存中
HttpSessionBindingListener 监听
保存在Session域中的对象可以有多种状态:
(1)绑定(session.setAttribute("bean",Object))到Session中;
(2)从Session域中解除(session.removeAttribute("bean"))绑定;
(3)随Session对象持久化到一个存储设备中;
(4)随Session对象从一个存储设备中恢复;
Servlet 规范中定义了两个特殊的监听器接口"HttpSessionBindingListener和HttpSessionActivationListener"来帮助JavaBean 对象了解自己在Session域中的这些状态: ,实现这两个接口的类不需要 web.xml 文件中进行注册。
ServletRequest监听器
ServletRequest
- ServletRequestListener监听Requst对象
- ServletRequestAttributeListener监听Request中的属性操作。
怎么知道我到底要实现哪个监听器?
看需求,看要监听的东西是什么,比如说监听上下文的有:ServletContextListener,ServletContextAttributeListener
监听request的有:ServletRequestListener,ServletRequestAttributeListener
监听器是怎样被调用的?为什么直接在web.xml里面配置一个listerner,程序就会自动去监听?
因为监听器是需要实现监听器接口的,接口的底层应该是封装好了怎样去监听的逻辑的,所以说直接实现监听器接口,程序启动后就能直接去监听。
Java代码实现
ServletContextListener
监听器类代码
package cn.itcast.erp.listener.request;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class ServletRequestListener1 implements ServletRequestListener {
/**
* 该请求即将超出Web应用程序的范围。
* request将要销毁
*/
@Override
public void requestDestroyed(ServletRequestEvent event) {
System.out.println("request将要销毁");
}
/**
* 该请求即将进入Web应用程序的范围。
* request初始化
*/
@Override
public void requestInitialized(ServletRequestEvent event) {
System.out.println("request初始化");
}
}
web.xml配置代码
<!-- ServletContext对象监听器 -->
<listener>
<listener-class>cn.itcast.erp.listener.servletContext.ServletContextListener1</listener-class>
</listener>
ServletContextAttributeListener
监听器类代码:
package cn.itcast.erp.listener.request;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class ServletRequestAttributeListener1 implements ServletRequestAttributeListener {
/**
* 通知一个新的属性被添加到servlet请求。 在添加属性后调用。
*/
@Override
public void attributeAdded(ServletRequestAttributeEvent event) {
System.out.println("request添加属性后调用");
}
/**
* 通知现有的属性已经从servlet请求中删除。 在属性被删除后调用。
*/
@Override
public void attributeRemoved(ServletRequestAttributeEvent event) {
System.out.println("request删除属性后调用");
}
/**
* 通知servlet请求中已经替换了一个属性。 在属性被替换后调用。
*/
@Override
public void attributeReplaced(ServletRequestAttributeEvent event) {
System.out.println("request替换属性后调用");
String name = event.getName();
Object value = event.getValue();
System.out.println("request被替换的key:" + name + " ,替换前的value:" + value);
}
}
web.xml配置代码:
<!-- ServletContext属性的操作监听器 -->
<listener>
<listener-class>cn.itcast.erp.listener.servletContext.ServletContextAttributeListener1</listener-class>
</listener>
HttpSessionListener
监听器类代码:
package cn.itcast.erp.listener.session;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class HttpSessionListener1 implements HttpSessionListener{
/**
* 通知会话已创建。
* session创建之后调用
*/
@Override
public void sessionCreated(HttpSessionEvent event) {
System.out.println("session创建之后");
HttpSession session = event.getSession();
}
/**
* 通知会话即将失效。
* session销毁之前调用
*/
@Override
public void sessionDestroyed(HttpSessionEvent event) {
System.out.println("session销毁之前");
HttpSession session = event.getSession();
}
}
web.xml配置代码:
<!-- HttpSession对象监听器 -->
<listener>
<listener-class>cn.itcast.erp.listener.session.HttpSessionListener1</listener-class>
</listener>
HttpSessionAttributeListener
package cn.itcast.erp.listener.session;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class HttpSessionAttributeListener1 implements HttpSessionAttributeListener{
/**
* 通知某个属性已被添加到会话中。 在添加属性后调用。
*/
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("session添加属性后调用");
HttpSession session = event.getSession();
String name = event.getName();
Object value = event.getValue();
System.out.println("被添加到session中的属性:" + "key=" + name + " ,value=" + value);
}
/**
* 通知某个属性已从会话中删除。 在属性被删除后调用。
*/
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("session删除属性后调用");
HttpSession session = event.getSession();
String name = event.getName();
Object value = event.getValue();
System.out.println("被删除的session中的属性:" + "key=" + name + " ,value=" + value);
}
/**
* 在会话中通知属性已被替换。 在属性被替换后调用。
*/
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("session替换属性后调用");
HttpSession session = event.getSession();
String name = event.getName();
Object value = event.getValue();
System.out.println("被替换的session中的属性:" + "key=" + name + " ,替换之前的value=" + value);
}
}
web.xml配置代码:
<!-- HttpSession属性的操作监听器 -->
<listener>
<listener-class>cn.itcast.erp.listener.session.HttpSessionAttributeListener1</listener-class>
</listener>
HttpSessionActivationListener
监听器类代码(不需要配置web.xml):
package cn.itcast.erp.listener.session;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
public class HttpSessionActivationListener1 implements HttpSessionActivationListener {
/**
* 通知该会话即将被钝化。
* 当前javaBean绑定到session中钝化之前
*/
@Override
public void sessionWillPassivate(HttpSessionEvent event) {
System.out.println("session钝化之前");
HttpSession session = event.getSession();
}
/**
* 通知该会话刚刚被激活。
* 当前javaBean绑定到session中活化之后
*/
@Override
public void sessionDidActivate(HttpSessionEvent event) {
System.out.println("session活化之后");
HttpSession session = event.getSession();
}
}
配置Session对象的管理org.apache.catalina.session.PersistentManager方便序列化测试:
添加配置文件webapp/META-INF/context.xml
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Session对象的管理 -->
<!-- maxIdleSwap="1" (秒):n秒之后就将HttpSession对象钝化到本地硬盘的一个文件夹中 -->
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="e:/session/"></Store>
</Manager>
</Context>
测试代码:jsp页面
<%@page import="cn.itcast.erp.listener.session.HttpSessionBindingListener1"%>
<%@page import="cn.itcast.erp.listener.session.HttpSessionActivationListener1"%>
<%@page language="java" pageEncoding="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>测试HttpSessionActivationListener监听(session的活化和钝化)</title>
</head>
<body>
<%
//测试session活化和钝化监听器HttpSessionActivationListener
session.setAttribute("sessionActivation",new HttpSessionActivationListener1());
//测试session绑定和解绑监听器
session.setAttribute("sessionBind", new HttpSessionBindingListener1());
session.removeAttribute("sessionBind");
%>
<h1>session活化和钝化监听</h1>
</body>
</html>
HttpSessionBindingListener
监听器类代码(不需要配置web.xml):
package cn.itcast.erp.listener.session;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class HttpSessionBindingListener1 implements HttpSessionBindingListener {
/**
* 通知对象它正在被绑定到会话并标识会话。(还未绑定)
*/
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("当前对象正在绑定到session中,还未绑定");
HttpSession session = event.getSession();
String name = event.getName();
Object value = event.getValue();
System.out.println("将要被绑定到session中的key值:" + name + "value值:" + value);
System.out.println("value值是否是当前对象:" + (value == this));//true
Object valueNow = session.getAttribute(name);
System.out.println("valueNow:" + valueNow);//null,还未绑定
}
/**
* 通知对象它正在从会话中解除绑定并标识会话。(还未解除绑定)
*/
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("当前对象它正在从会话中解除绑定");
HttpSession session = event.getSession();
String name = event.getName();
Object value = event.getValue();
System.out.println("将要解除绑定session中的key值:" + name + "value值:" + value);
System.out.println("value值是否是当前对象:" + (value == this));//true
Object valueNow = session.getAttribute(name);
System.out.println("valueNow:" + valueNow);//null,还未解除绑定
}
}
测试代码:jsp页面
<%@page import="cn.itcast.erp.listener.session.HttpSessionBindingListener1"%>
<%@page import="cn.itcast.erp.listener.session.HttpSessionActivationListener1"%>
<%@page language="java" pageEncoding="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>测试HttpSessionActivationListener监听(session的活化和钝化)</title>
</head>
<body>
<%
//测试session活化和钝化监听器HttpSessionActivationListener
session.setAttribute("sessionActivation",new HttpSessionActivationListener1());
//测试session绑定和解绑监听器
session.setAttribute("sessionBind", new HttpSessionBindingListener1());
session.removeAttribute("sessionBind");
%>
<h1>session活化和钝化监听</h1>
</body>
</html>
ServletRequestListener
监听器类代码:
package cn.itcast.erp.listener.request;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class ServletRequestListener1 implements ServletRequestListener {
/**
* 该请求即将超出Web应用程序的范围。
* request将要销毁
*/
@Override
public void requestDestroyed(ServletRequestEvent event) {
System.out.println("request将要销毁");
}
/**
* 该请求即将进入Web应用程序的范围。
* request初始化
*/
@Override
public void requestInitialized(ServletRequestEvent event) {
System.out.println("request初始化");
}
}
web.xml配置代码:
<!-- ServletRequest对象监听器 -->
<listener>
<listener-class>cn.itcast.erp.listener.request.ServletRequestListener1</listener-class>
</listener>
ServletRequestAttributeListener
监听器类代码:
package cn.itcast.erp.listener.request;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class ServletRequestAttributeListener1 implements ServletRequestAttributeListener {
/**
* 通知一个新的属性被添加到servlet请求。 在添加属性后调用。
*/
@Override
public void attributeAdded(ServletRequestAttributeEvent event) {
System.out.println("request添加属性后调用");
}
/**
* 通知现有的属性已经从servlet请求中删除。 在属性被删除后调用。
*/
@Override
public void attributeRemoved(ServletRequestAttributeEvent event) {
System.out.println("request删除属性后调用");
}
/**
* 通知servlet请求中已经替换了一个属性。 在属性被替换后调用。
*/
@Override
public void attributeReplaced(ServletRequestAttributeEvent event) {
System.out.println("request替换属性后调用");
String name = event.getName();
Object value = event.getValue();
System.out.println("request被替换的key:" + name + " ,替换前的value:" + value);
}
}
web.xml配置代码:
<!-- ServletRequest属性的操作监听器 -->
<listener>
<listener-class>cn.itcast.erp.listener.request.ServletRequestAttributeListener1</listener-class>
</listener>
模仿监听器Demo
需求:实现机器人工作和跳舞,在机器人开始工作和跳舞之前输出相关提示。
首先创建一个事件源Robot:
package com.ssm.listener.robotListener;
/**
* 事件源:机器人
*/
public class Robot {
private RobotListener listener;
/**
* 注册机器人监听器
* @param listener
*/
public void registerListener(RobotListener listener){
this.listener = listener;
}
/**
* 工作
*/
public void working(){
if(listener!=null){
Even even = new Even(this);
this.listener.working(even);
}
System.out.println("机器人开始工作......");
}
/**
* 跳舞
*/
public void dancing(){
if(listener!=null){
Even even = new Even(this);
this.listener.dancing(even);
}
System.out.println("机器人开始跳舞......");
}
}
创建时间对象Even:
package com.ssm.listener.robotListener;
/**
* 事件对象
*/
public class Even {
private Robot robot;
public Even(){
super();
}
public Even(Robot robot){
super();
this.robot = robot;
}
public Robot getRobot() {
return robot;
}
public void setRobot(Robot robot) {
this.robot = robot;
}
}
创建时间监听器接口RobotListener:
package com.ssm.listener.robotListener;
/**
* 事件监听器
*/
public interface RobotListener {
public void working(Even even);
public void dancing(Even even);
}
实现事件监听器MyRobotListener:
package com.ssm.listener.robotListener;
public class MyRobotListener implements RobotListener{
@Override
public void working(Even even) {
Robot robot = even.getRobot();
System.out.println("机器人工作提示:请看管好的你机器人,防止它偷懒!");
}
@Override
public void dancing(Even even) {
Robot robot = even.getRobot();
System.out.println("机器人跳舞提示:机器人跳舞动作优美,请不要走神哦!");
}
}
事件监听器测试类
TestListener:
package com.ssm.listener.robotListener;
public class TestListener {
public static void main(String[] args) {
Robot robot = new Robot();
robot.registerListener(new MyRobotListener());
robot.working();
robot.dancing();
}
}
输出结果:
参考文章(侵删):
https://blog.csdn.net/menghuanzhiming/article/details/79042182
https://www.cnblogs.com/againn/p/9512013.html