Listener监听器
1.基本概念
- Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。
- 容器产生的事件分类如下:
- 生命周期相关的事件。
- 属性状态相关的事件。
- 存值状态相关的事件。
- 底层原理是采用接口回调的方式实现。
2.基本分类
监听器类型 |
功能介绍 |
javax.servlet.ServletRequestListener |
监听request作用域的创建和销毁 |
javax.servlet.ServletRequestAttributeListener |
监听request作用域的属性状态变化 |
javax.servlet.http.HttpSessionListener |
监听session作用域的创建和销毁 |
javax.servlet.http.HttpSessionAttributeListener |
监听session作用域的属性状态变化 |
javax.servlet.ServletContextListener |
监听application作用域的创建和销毁 |
javax.servlet.ServletContextAttributeListener |
监听application作用域的属性状态变化 |
javax.servlet.http.HttpSessionBindingListener |
监听对象与session的绑定和解除 |
javax.servlet.http.HttpSessionActivationListener |
监听session数值的钝化和活化 |
3.监听器详解
(1)ServletRequestListener监听器
在ServletRequest创建和关闭时都会通知ServletRequestListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void requestInitialized(ServletRequestEvent sre) |
实现ServletRequest对象的初始化 |
void requestDestroyed(ServletRequestEvent sre) |
实现ServletRequest对象的销毁 |
package com.lagou.demo03;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class MyRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("请求销毁了...");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("创建请求...");
}
}
<listener>
<listener-class>com.lagou.demo03.MyRequestListener</listener-class>
</listener>
(2)ServletRequestAttributeListener监听器
向ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void attributeAdded(ServletRequestAttributeEvent srae) |
增加属性时触发 |
void attributeReplaced(ServletRequestAttributeEvent srae) |
修改属性时触发 |
void attributeRemoved(ServletRequestAttributeEvent srae) |
删除属性时触发 |
package com.lagou.demo03;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class MyRequestAttributeListener implements ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("增加了属性" + servletRequestAttributeEvent.getName());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("属性" + servletRequestAttributeEvent.getName() + "被删除了" );
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("修改属性" + servletRequestAttributeEvent.getName());
}
}
<listener>
<listener-class>com.lagou.demo03.MyRequestAttributeListener</listener-class>
</listener>
(3)HttpSessionListener监听器
当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void sessionCreated(HttpSessionEvent se) |
当一个HttpSession对象被创建时会调用这个方法 |
void sessionDestroyed(HttpSessionEvent se) |
当一个HttpSession超时或者调用HttpSession的 invalidate()方法让它销毁时,将会调用这个方法 |
package com.lagou.demo03;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MySessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("创建了session...");
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("session销毁!");
}
}
<listener>
<listener-class>com.lagou.demo03.MySessionListener</listener-class>
</listener>
(4)HttpSessionAttributeListener监听器
HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监 听器
常用方法如下:
方法声明 |
功能介绍 |
void attributeAdded(HttpSessionBindingEvent se) |
当往会话中加入一个属性的时候会调用这个方法 |
void attributeRemoved(HttpSessionBindingEvent se) |
当从会话中删除一个属性的时候会调用这个方法 |
void attributeReplaced(HttpSessionBindingEvent se) |
当改变会话中的属性的时候会调用这个方法 |
package com.lagou.demo03;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class MySessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("增加了属性" + httpSessionBindingEvent.getName());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("属性" + httpSessionBindingEvent.getName() + "被删除!");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("修改属性" + httpSessionBindingEvent.getName());
}
}
<listener>
<listener-class>com.lagou.demo03.MySessionAttributeListener</listener-class>
</listener>
(5)ServletContextListener监听器
在ServletContext创建和关闭时都会通知ServletContextListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void contextInitialized(ServletContextEvent sce) |
当ServletContext创建的时候,将会调用这个方法 |
void contextDestroyed(ServletContextEvent sce) |
当ServletContext销毁的时候(例如关闭应用服务器或者重新加载应用),将会调用这个方法 |
package com.lagou.demo03;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象创建了...");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("销毁ServletContext对象...");
}
}
<listener>
<listener-class>com.lagou.demo03.MyContextListener</listener-class>
</listener>
(6)ServletContextAttributeListener监听器
向ServletContext添加、删除或者替换一个属性的时候,将会通知ServletContextAttributesListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void attributeAdded(ServletContextAttributeEvent scae) |
往ServletContext中加入一个属性的时候触发 |
void attributeRemoved(ServletContextAttributeEvent scae) |
从ServletContext中删除一个属性的时候触发 |
void attributeReplaced(ServletContextAttributeEvent scae) |
改变ServletContext中属性的时候触发 |
package com.lagou.demo03;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class MyContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("增加了属性" + servletContextAttributeEvent.getName());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("属性" + servletContextAttributeEvent.getName() + "被删除!");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("修改属性" + servletContextAttributeEvent.getName());
}
}
<listener>
<listener-class>com.lagou.demo03.MyContextAttributeListener</listener-class>
</listener>
(7)HttpSessionBindingListener监听器
HttpSession中绑定和解除绑定时,将会通知HttpSessionListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void valueBound(HttpSessionBindingEvent event) |
有对象绑定时调用该方法 |
void valueUnbound(HttpSessionBindingEvent event) |
有对象解除绑定时调用该方法 |
package com.lagou.demo03;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Person implements HttpSessionBindingListener {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("对象绑定到session中了" + httpSessionBindingEvent.getName());
}
@Override
public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("解除绑定成功!");
}
}
<%@ page import="com.lagou.demo03.Person" %><%--
Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现session中对象的绑定和解除</title>
</head>
<body>
<%
// 准备一个Person类型的对象
Person person = new Person();
person.setName("zhangfei");
person.setAge(30);
// 将对象与session对象进行绑定
session.setAttribute("person", person);
// 解除绑定
session.removeAttribute("person");
%>
</body>
</html>
(8)HttpSessionActivationListener监听器
当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器
常用方法如下:
方法声明 |
功能介绍 |
void sessionWillPassivate(HttpSessionEvent se) |
有钝化操作时调用该方法 |
void sessionDidActivate(HttpSessionEvent se) |
有活化操作时调用该方法 |
package com.lagou.demo03;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
public class Student implements Serializable, HttpSessionActivationListener {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
@Override
public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
System.out.println("执行了钝化操作..." + httpSessionEvent.getSession());
}
@Override
public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
System.out.println("活化操作进行中...");
}
}
<%--
Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现session中数据的获取</title>
</head>
<body>
<%
Object student = session.getAttribute("student");
System.out.println("获取到的数据为:" + student);
%>
</body>
</html>
活化操作时,需要将session从硬盘中读取到内存中,但IDEA会默认在启动时从硬盘中删除保存的session,所以应该将配置context.xml文件的增加如下内容:
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
<!-- 配置文件存放的路径信息,可以自由指定 -->
<Store className="org.apache.catalina.session.FileStore" directory="C:\session"/>
</Manager>
案例:实现网站在线人数的统计(比如增加在线人数)
package com.lagou.demo04;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineUser implements HttpSessionListener, ServletContextListener {
// 声明一个ServletContex类型的引用负责作为全局对象来记录当前在线用户的数量,通过属性记录
private ServletContext servletContext = null;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
servletContext = servletContextEvent.getServletContext();
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
servletContext = null;
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("有新用户上线了...");
Object count = servletContext.getAttribute("count");
// 若当前用户为第一个用户,则将全局对象中的属性值设置为1即可
if (null == count) {
servletContext.setAttribute("count", 1);
}
// 若当前用户不是第一个用户,则将全局对象中原有的数据取出来加1后再设置进去
else {
Integer integer = (Integer)count;
integer++;
servletContext.setAttribute("count", integer);
}
System.out.println("当前在线用户数量为:" + servletContext.getAttribute("count"));
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("有用户已下线...");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>com.lagou.demo04.OnlineUser</listener-class>
</listener>
</web-app>
<%--
Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现当前在线的用户数量</title>
</head>
<body>
<h1>当前在线用户人数为:${applicationScope.count}</h1>
</body>
</html>
节选自拉钩教育JAVA系列课程。