-  Servlet规范中的监听器:

-  Servlet规范中已经定义好了八个监听器接口,它们要监听的对象分别是request、session、servletContext对象,触发监听器事件是这三个对象的创建和销毁,它们的域属性空间中的属性的添加、删除、修改,以及session的钝化和活化操作。

-  在JavaWeb项目中使用监听器,需要在web.xml文件中对监听器进行注册。

<!-- 注册监听器 -->
<listener>
     <listener-class>com.abc.listener.MyRequestListener</listener-class>
</listener>


-  下面对这八个监听器接口接口进行介绍。

1、javax.servlet.ServletRequestListener接口:该监听器用于完成对Request对象的创建以及销毁的监听,即当Request对象被创建或者被销毁的时候,会触发该监听器中相应方法的执行。

-  该ServletRequestListener接口有两个方法需要实现:接收通知,ServletRequest对象即将离开/进入web应用的范围,可以通过在实现类中重写这两个方法来监听ServletRequest对象。

Servlet编程专题8之Servlet规范中的监听器_接口


-  javax.servlet.ServletRequestEvent类:这类事件表示ServletRequest对象生命周期的事件。

-  可以通过该ServletRequestEvent类的以下两个方法获取web应用的ServletContext对象和当前ServletRequest对象。

Servlet编程专题8之Servlet规范中的监听器_seesion_02


-  示例代码:

-  需要自定义ServletRequestListener实现类,并实现requestDestroyed(ServletRequestEvent sre)方法和requestInitialized(ServletRequestEvent sre)方法。

package com.geeklicreed.listeners;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyRequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("请求对象被销毁");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("请求对象被创建");
    }

}


-  并且在web.xml文件中定义监听器标签。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <listener>
        <listener-class>com.geeklicreed.listeners.MyRequestListener</listener-class>
    </listener>
</web-app>


-  可以发现,在浏览器访问web应用的任何资源,都会在控制台打印如下内容:

Servlet编程专题8之Servlet规范中的监听器_监听器_03


2、javax.servlet.ServletRequestAttributeListener接口:该监听器用于完成对Request对象域属性添加、修改和删除的监听,即当Request对象域属性被添加、修改和删除时,会触发该监听器中相应方法的执行。

-  该ServletRequestAttributeListener接口有三个方法需要实现:用于接收ServletRequest域属性被添加、删除或者修改时的通知。(监听ServletRequest域属性的添加、删除或者修改操作)

Servlet编程专题8之Servlet规范中的监听器_监听器_04


-  javax.servlet.ServletRequestAttributeEvent类:这类事件表示在应用中request对象域属性被改动时的通知事件。

-  该ServletRequestAttributeEvent类有以下两个方法:用于获取ServletRequest对象域属性改动的名字和值:

Servlet编程专题8之Servlet规范中的监听器_监听器_05


-  示例代码:

-  需要自定义ServletRequestAttributeListener实现类,并实现attributeAdded(ServletRequestAttributeEvent srae)方法、attributeRemoved(ServletRequestAttributeEvent srae)方法和attributeReplaced(ServletRequestAttributeEvent srae)方法。

package com.geeklicreed.listeners;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

public class MyRequestAttributeListener implements
        ServletRequestAttributeListener {

    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("向request对象域中添加一个属性");
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {

    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {

    }

}


-  并且在web.xml文件中定义监听器标签。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <listener>
        <listener-class>com.geeklicreed.listeners.MyRequestAttributeListener</listener-class>
    </listener>
</web-app>


-  在index.jsp中添加java代码块,快中为request域空间添加属性,启动程序后打开这个页面,可以看到控制台中的打印如下。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    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>Insert title here</title>
</head>
<body>
    <%
        request.setAttribute("username", "geeklicreed");
    %>
</body>
</html>

Servlet编程专题8之Servlet规范中的监听器_seesion_06


3、javax.servlet.http.HttpSessionListener接口:该监听器用于完成对Session对象的创建以及销毁的监听。(其接口中定义的方法和ServletRequestListener接口方法定义类似,与其不同的是,session对象在页面第一次访问的时候被创建,且只被创建一次。)

-  HttpSessionListener接口中有两个方法定义,分别用于对session对象的创建和销毁进行监听:

Servlet编程专题8之Servlet规范中的监听器_seesion_07


-  javax.servlet.http.HttpSessionEvent类:这个类表示当web应用中的session被改动时的通知事件。该类中的方法只有一个,用于获取Session对象。

Servlet编程专题8之Servlet规范中的监听器_seesion_08



4、javax.servlet.http.HttpSessionAttributeListener接口:该监听器用于完成对session域属性空间中属性的添加、修改、删除操作的监听。(其接口定义的方法与ServletRequestAttributeListener接口定义的方法类似)

Servlet编程专题8之Servlet规范中的监听器_seesion_09


-  javax.servlet.http.HttpSessionBindingEvent类:这类事件表示在应用中request对象域属性被改动时的通知事件。

-  该类中有用于获取Session对象的getSession()方法,和获取从session对象绑定或者解绑时的域属性的名字或者值。

Servlet编程专题8之Servlet规范中的监听器_接口_10


5、javax.servlet.ServletContextListener接口:该监听器用于完成对SessionContext对象的创建以及销毁的监听。不过需要注意的是,由于ServletContext在一个应用中只有一个,且是在服务器启动时创建。另外,ServletContext的生命周期与整个应用的相同,所以当项目重新部署时,或者Tomcat正常关闭时(通过stop service关闭,不能是terminate关闭),可以销毁ServletContext。(其接口中定义的方法和ServletRequestListener接口方法定义类似)

Servlet编程专题8之Servlet规范中的监听器_接口_11


-  javax.servlet.ServletContextEvent类:这个类表示当web应用中的ServletContext被改动时的通知事件。该类中的方法只有一个,用于获取ServletContext对象。

Servlet编程专题8之Servlet规范中的监听器_接口_12


6、javax.servlet.ServletContextAttributeListener接口:该监听器用于完成对ServletContext域属性空间中属性的添加、修改、删除操作的监听。(其接口定义的方法与ServletRequestAttributeListener接口定义的方法类似)

Servlet编程专题8之Servlet规范中的监听器_seesion_13


-  javax.servlet.ServletContextAttributeEvent类:这类事件表示在应用中request对象域属性被改动时的通知事件。(类中的方法与ServletRequestAttributeEvent类中方法类似)

Servlet编程专题8之Servlet规范中的监听器_监听器_14


7、javax.servlet.http.HttpSessionBindingListener接口:使对象在绑定session或者从session解绑时得以监听。

Servlet编程专题8之Servlet规范中的监听器_接口_15

-  接口中定义的方法有两个:通知对象正在从session绑定(或者解绑),并标识该session。

Servlet编程专题8之Servlet规范中的监听器_接口_16


-  javax.servlet.http.HttpSessionBindingEvent类:当一个实现了HttpSessionBindingListener接口的对象从session域中绑定或者解绑时,这类事件将会被发送。

-  以下为该类中的三个方法:(与HttpSessionBindingEvent类类似,与之不同的是,getValue()方法返回的是实体类的对象)

Servlet编程专题8之Servlet规范中的监听器_接口_17


-  示例代码:

-  自定义Student实体类:

package com.geeklicreed.listeners;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
//实体类实现HttpSessionBindingListener接口
//该监听器不需要注册
public class Student implements HttpSessionBindingListener {
    private String name;
    private int age;

    public Student(String name, int age) {
        super();
        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 "Student [name=" + name + ", age=" + age + "]";
    }

    //当当前类的对象绑定到Session时(放入到Session域中),会触发该方法的执行
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("student对象放入到Session域中");
    }

    //当当前类的对象与Session解绑时(从Session域中删除),会触发该方法的执行
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("student对象从Session域中删除");
    }

}

-  index.jsp文件中的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="com.geeklicreed.listeners.Student"%>
<!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>
    <%
        //session绑定
        session.setAttribute("student", new Student("geeklicreed", 20));
        //session解绑
        session.removeAttribute("student");
    %>

</body>
</html>


8、javax.servlet.http.HttpSessionActivationListener接口:该监听器用于监听在session中存放的指定类型对象的钝化与活化。

-  钝化是指将内存中的数据写入到硬盘中,而活化是指将硬盘中的数据恢复到内存中。当用户正在访问的应用或者该应用所在的服务器由于种种原因被停掉,然后在短时间内又重启,此时用户再访问时session中的数据是不能丢失的,在应用关闭之前,需要将数据写入到硬盘中,在重启后可以立即重新恢复session中的数据,这就称之为session的钝化与活化。

-  那么session中的哪些数据能够钝化呢?只有存放在JVM堆内存中的实现Serializable类的对象才能够被钝化。也就是说,对于字符串常量,基本数据类型等存放在JVM方法区中常量池常量,是无法被钝化的。


HttpSessionActivationListener接口中定义的方法:当session已经被活化或者session将要被钝化时通知监听:

Servlet编程专题8之Servlet规范中的监听器_监听器_18


-  示例代码:

-  自定义Student实体类:

package com.geeklicreed.listeners;

import java.io.Serializable;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
//实体类实现HttpSessionActivationListener接口,Serializable接口
//该监听器不需要注册
public class Student implements HttpSessionActivationListener, Serializable {

    private static final long serialVersionUID = -6313305154694843468L;

    private String name;
    private int age;

    public Student(String name, int age) {
        super();
        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 "Student [name=" + name + ", age=" + age + "]";
    }

    // 当当前类的对象被钝化(内存中的数据写入到硬盘中)时,会触发该方法的执行
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println("Student将要被钝化");
    }

    // 当当前类的对象被活化(硬盘中的数据恢复到内存中)时,会触发该方法的执行
    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println("Student已经活化");
    }

}

-  index.jsp文件中的代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="com.geeklicreed.listeners.Student"%>
<!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>
    <%
        //session绑定
        session.setAttribute("student", new Student("geeklicreed", 20));
    %>
</body>
</html>


-  当服务器被关闭时,可以看到控制台打印,说明session将要被钝化时被通知监听:

Servlet编程专题8之Servlet规范中的监听器_接口_19

-  当服务器重新启动时,可以看到控制台打印,说明session已经活化时被通知监听:

Servlet编程专题8之Servlet规范中的监听器_接口_20