基本概念
- Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理
- 容器产生的事件分类如下:
- 生命周期相关的事件
- 属性状态相关的事件
- 存值状态相关的事件
- 底层原理是采用接口回调的方式实现
基本分类
Listener监听三个域对象创建与销毁
ServletRequestListener监听器
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("创建请求...");
}
}
在web.xml文件中配置监听器。
<listener>
<listener-class>com.lagou.demo03.MyRequestListener</listener-class>
</listener>
HttpSessionListener监听器
ServletContextListener监听器
Listener监听三个域对象属性状态的改变
ServletRequestAttributeListener监听器
向ServletRequest添加、删除或者替换一个属性的时候,将会通知 ServletRequestAttributeListener监听器。
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());
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现请求中属性状态的改变</title>
</head>
<body>
<%
// 实现属性的添加
request.setAttribute("name", "zhangfei");
// 实现属性的修改
request.setAttribute("name", "guanyu");
// 实现属性的删除
request.removeAttribute("name");
%>
</body>
</html>
在web.xml文件中配置监听器。
<listener>
<listener-class>com.lagou.demo03.MyRequestAttributeListener</listener-class>
</listener>
HttpSessionAttributeListener监听器
ServletContextAttributeListener监听器
Listener监听HttpSession域对象存值的状态变更
这两种监听器不用配置(注册)。
HttpSessionBindingListener监听器
HttpSession中有对象绑定和解除绑定时,将会通知HttpSessionListener监听器。
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>
HttpSessionActivationListener监听器
当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
- 可以理解为序列化操作:将一个对象的所有数据内容转换成字节序列
session
的钝化活化的用意:
-
session
中的值可能会很多,并且我们有很长一段时间不会去使用这个内存中的值,那么可以考虑把session
中的值存储到硬盘上(钝化),等下一次要使用的时候,从硬盘上提取到内存中(活化) -
停止服务器时会执行钝化操作
-
启动服务器时会执行活化操作
-
IDEA重启时会把tomcat的work目录下的内容删掉重新生成,存在该目录下的被钝化的数据被删除,此时无法活化
-
改配置文件context.xml,更改存储位置
directory="C:\session"要确保该目录存在,没有就手动创建
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true"> <!-- 配置文件存放的路径信息,可以自由指定 --> <Store className="org.apache.catalina.session.FileStore" directory="C:\session"/> </Manager>
-
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("活化操作进行中...");
}
}
钝化:
<%@ page import="com.lagou.demo03.Student" %><%--
Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现session中数据的钝化和活化操作</title>
</head>
<body>
<%
// 创建Student类型的对象
Student student = new Student();
student.setName("zhangfei");
// 将数据放入到session中
session.setAttribute("student", student);
%>
</body>
</html>
活化:
<%--
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:浏览器向服务器发送一个请求,服务器就会创建一个session对象,即有多少个用户访问就有多少个session
ServletContext:一个web项目只对应一个
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("有用户已下线...");
}
}
在web.xml中配置监听器
<listener>
<listener-class>com.lagou.demo04.OnlineUser</listener-class>
</listener>
测试功能
<%--
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>