Java Web学习总结(13)Listener监听器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Web学习总结(13)Listener监听器相关的知识,希望对你有一定的参考价值。

一,监听器介绍

监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。

监听器的相关概念:

事件源

被监听的对象

监听器

监听事件源对象,事件源对象的状态的变化都会触发监听器

注册监听器

将监听器与事件源进行绑定。

响应行为

监听器监听到事件源的状态变化时 所涉及的功能代码。

二,监听器的分类

分类1:按照被监听的对象划分

ServletRequest域

HttpSession域

ServletContext域

分类2:监听的内容分

监听域对象的创建与销毁的

监听域对象的属性变化的

技术分享

三,监听三大域对象的创建与销毁的监听器

监听器的编写步骤:

1、编写一个监听器类去实现监听器接口

2、覆盖监听器的方法

3、需要在web.xml中进行配置

1,监听ServletContext域的创建与销毁的监听器ServletContextListener

当ServletContext对象被创建时,触发contextInitialized (ServletContextEvent arg0)方法。

当ServletContext对象被销毁时,触发contextDestroyed(ServletContextEvent arg0)方法。

ServletContext域对象创建和销毁时机:

创建:服务器启动针对每一个Web应用创建ServletContext。

销毁:服务器关闭前先关闭代表每一个web应用的ServletContext。

例如:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
 
public class MyServletContextListener implements ServletContextListener{
 
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println("ServletContext对象销毁了!");
    }
 
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println("ServletContext对象创建了!");
    }
}

在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">
    <display-name>Listener</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <!-- 注册针对ServletContext对象的监听器 -->
    <listener>
        <listener-class>com.zender.MyServletContextListener</listener-class>
    </listener>
</web-app>

web服务器启动:

技术分享

web服务器关闭:

技术分享

2,监听Httpsession域的创建于销毁的监听器HttpSessionListener

当创建一个Session时,触发sessionCreated (HttpSessionEvent arg0) 方法

当销毁一个Session时,触发sessionDestroyed (HttpSessionEvent arg0) 方法。

Httpsession域对象创建和销毁时机:

创建:第一次调用request.getSession时创建。

销毁:服务器关闭销毁 session过期 手动销毁。

例如:

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
 
public class MyHttpSessionListener implements HttpSessionListener {
 
    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
        System.out.println("session创建:" + arg0.getSession().getId());
    }
 
    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {
        System.out.println("session销毁了!");
    }
}

在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">
    <display-name>Listener</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <!-- 注册针对HttpSession对象的监听器 -->
    <listener>
        <listener-class>com.zender.MyHttpSessionListener</listener-class>
    </listener>
</web-app>

访问页面时:

技术分享

3,监听ServletRequest域创建与销毁的监听器ServletRequestListener

当Request对象被创建时,触发requestInitialized(ServletRequestEvent arg0)方法。

当Request对象被销毁时,触发requestDestroyed(ServletRequestEvent arg0)方法。

ServletRequest域对象创建和销毁时机:

创建:用户每一次访问都会创建request对象

销毁:当前访问结束,request对象就会销毁

例如:

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
 
public class MyServletRequestListener implements ServletRequestListener {
 
    @Override
    public void requestDestroyed(ServletRequestEvent arg0) {
        System.out.println("request对象销毁了");
    }
 
    @Override
    public void requestInitialized(ServletRequestEvent arg0) {
        System.out.println("request对象创建了");
    }
}

在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">
    <display-name>Listener</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <!-- 注册针对Request对象的监听器 -->
    <listener>
        <listener-class>com.zender.MyServletRequestListener</listener-class>
    </listener>
</web-app>

访问页面时:

技术分享

可以看出用户每一次访问都会创建request对象,当访问结束后,request对象就会销毁。

四.监听三大域对象的属性变化的监听器

1,监听ServletContext域的属性变化的监听器ServletContextAttributeListener

当ServletContext对象添加属性时,触发attributeAdded(ServletContextAttributeEvent arg0)方法。

当ServletContext对象修改属性时,触发attributeReplaced(ServletContextAttributeEvent arg0)方法。

当ServletContext对象删除属性时,触发attributeRemoved(ServletContextAttributeEvent arg0)方法。

例如:

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
 
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
 
    @Override
    public void attributeAdded(ServletContextAttributeEvent arg0) {
        System.out.println("属性被添加,name:" + arg0.getName() + "value:" + arg0.getValue());
    }
 
    @Override
    public void attributeRemoved(ServletContextAttributeEvent arg0) {
        System.out.println("属性被删除,name:" + arg0.getName() + "value:" + arg0.getValue());
    }
 
    @Override
    public void attributeReplaced(ServletContextAttributeEvent arg0) {
        //获得是修改前的数据
        System.out.println("属性被修改,name:" + arg0.getName() + "value:" + arg0.getValue());
    }
}

Servlet:

import java.io.IOException;
 
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class TestMyServletContextAttributeListener extends HttpServlet{
    
    private static final long serialVersionUID = -7057319189693064505L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //存储一个数据
        context.setAttribute("name", "Zender");
        //修改一个数据
        context.setAttribute("name", "Zender2");
        //删除一个数据
        context.removeAttribute("name");
    }
}

在web.xml文件中注册监听器和Servlet:

<?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">
    <display-name>Listener</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    
    <!-- 注册Servlet -->
    <servlet>
        <servlet-name>TestMyServletContextAttributeListener</servlet-name>
        <servlet-class>com.zender.servlet.TestMyServletContextAttributeListener</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestMyServletContextAttributeListener</servlet-name>
        <url-pattern>/index.html</url-pattern>
    </servlet-mapping>
    
    <!-- 注册针对ServletContext对象的属性的监听器 -->
    <listener>
        <listener-class>com.zender.MyServletContextAttributeListener</listener-class>
    </listener>
</web-app>

访问http://localhost:8081/Listener/index.html,后台结果:

技术分享

2, HttpSessionAttributeListener监听器(同上)

3,ServletRequestAriibuteListenr监听器(同上)

五,与session中的绑定的对象相关的监听器(对象感知监听器)

即将要被绑定到session中的对象有4种状态:

绑定状态

就一个对象被放到session域中

解绑状态

就是这个对象从session域中移除了

钝化状态

是将session内存中的对象持久化(序列化)到磁盘

活化状态

就是将磁盘上的对象再次恢复到session内存中

1,绑定与解绑的监听器HttpSessionBindingListener

当Person类在HttpSession对象绑定属性时,触发valueBound(HttpSessionBindingEvent arg0)方法。

当Person类在HttpSession对象解绑属性时,触发valueUnbound(HttpSessionBindingEvent arg0)方法。

例如:

首先创建一个Person类实现HttpSessionBindingListener接口:

    public class Person implements HttpSessionBindingListener {
        private int id;
        private String name;
        public int getId() {
            return id;
        }
        
        public Person(int id, String name) {
            this.id = id;
            this.name = name;
        }
        public Person() {
        }
        
        public void setId(int id) {
            this.id = id;
        }
     
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        @Override
        public void valueBound(HttpSessionBindingEvent arg0) {
            System.out.println("person对象被绑定了!");
        }
     
        @Override
        public void valueUnbound(HttpSessionBindingEvent arg0) {
            System.out.println("person对象被解绑了!");
        }
    }

Servlet:

import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.zender.Person;
 
public class TestPersonBindingListener extends HttpServlet {
 
    private static final long serialVersionUID = -4836536065640905707L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //将Person绑定到Session域中
        session.setAttribute("persion", new Person(1,"Zender"));
        //将Person从Session域中解绑
        session.removeAttribute("persion");
    }
}

在web.xml文件中注册Servlet:

<?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">
    <display-name>Listener</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    
    <!-- 注册Servlet -->
    <servlet>
        <servlet-name>TestPersonBindingListener</servlet-name>
        <servlet-class>com.zender.servlet.TestPersonBindingListener</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestPersonBindingListener</servlet-name>
        <url-pattern>/index.html</url-pattern>
    </servlet-mapping>
</web-app>

访问http://localhost:8081/Listener/index.html,后台结果:

技术分享

2,钝化与活化的监听器HttpSessionActivationListener

当Person类被钝化时,触发sessionWillPassivate(HttpSessionEvent arg0)方法。

当Person类被活化时,触发sessionDidActivate(HttpSessionEvent arg0)方法。

例如:

首先创建一个Person类实现HttpSessionActivationListener接口,并且这个类必须实现Serializable接口(序列化):

public class Person implements HttpSessionActivationListener,Serializable{
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    
    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public Person() {
    }
    
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public void sessionDidActivate(HttpSessionEvent arg0) {
        System.out.println("Person被活化了");
    }
 
    @Override
    public void sessionWillPassivate(HttpSessionEvent arg0) {
        System.out.println("Person被钝化了");
    }
}

Servlet:

import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.zender.Person;
 
public class TestPersonActivationListener extends HttpServlet {
 
    private static final long serialVersionUID = -4836536065640905707L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //将Person绑定到Session域中
        session.setAttribute("persion", new Person(1,"Zender"));
        System.out.println("Person被放到Session域中了!");
    }
}

在web.xml文件中注册Servlet:

<?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">
    <display-name>Listener</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    
    <!-- 注册Servlet -->
    <servlet>
        <servlet-name>TestPersonActivationListener</servlet-name>
        <servlet-class>com.zender.servlet.TestPersonActivationListener</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestPersonActivationListener</servlet-name>
        <url-pattern>/index.html</url-pattern>
    </servlet-mapping>
</web-app>

访问http://localhost:8081/Listener/index.html,后台结果:

技术分享

关闭服务器:

技术分享

控制台打印:

技术分享

钝化的文件:

技术分享

活化对象:

Servlet2:

import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.zender.Person;
 
public class TestPersonActivationListener2 extends HttpServlet {
 
    private static final long serialVersionUID = -4836536065640905707L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //获取Session域中的Person
        Person p = (Person) session.getAttribute("persion");
        System.out.println("name:" + p.getName());
    }
}

在web.xml文件中注册Servlet2:

    <!-- 注册Servlet -->
    <servlet>
        <servlet-name>TestPersonActivationListener2</servlet-name>
        <servlet-class>com.zender.servlet.TestPersonActivationListener2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestPersonActivationListener2</servlet-name>
        <url-pattern>/index2.html</url-pattern>
    </servlet-mapping>

启动服务器自动活化对象:

技术分享

访问:http://localhost:8081/Listener/index2.html,控制台打印:

技术分享

怎么控制对象的钝化时间呢?可以通过配置文件,指定对象钝化时间,对象多长时间不用会被钝化。

在META-INF下创建一个context.xml

技术分享

内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- 这样session在一分钟不动的情况下则会被钝化到tomcat工作目录下面的 cjq目录下,直到再次访问才被激活。 -->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">  
        <Store className="org.apache.catalina.session.FileStore" directory="cjq" />  
    </Manager>  
</Context>

启动服务器访问Servlet把对象放到Session中:

技术分享

控制台:过1分钟后对象会被自动钝化:

技术分享

钝化的文件:

技术分享

访问Servlet2时,对象会自动被活化:

技术分享

以上是关于Java Web学习总结(13)Listener监听器的主要内容,如果未能解决你的问题,请参考以下文章

Listener--监听器

javaweb学习总结(四十七)——监听器(Listener)在开发中的应用

java web学习:三大组件 Listener基础

2020/2/10学习总结

java web 之 listen 与 filter

Java中的监听器