2024年9月12日学习笔记--关于servlet5

5.4 监听器

5.4.1 监听器的概念

Servlet规范中的三大接口,除了Servlet接口,Filter接口,剩下的就是==Listener接口==了。

监听器采用了设计模式中的观察者模式,监听器本身是观察者,被监听的对象是被观察者。当被监听对象的状态发生改变时,就会通知观察者,也就是监听器,监听器在收到通知后可以做出相应的处理逻辑。

Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext、HttpSession和ServletRequest等域对象的创建与销毁事件,以及监听这些域对象中属性发生修改的事件。

5.4.2 监听器的分类

在Servlet2.5版本以来,定义了以下三类8种监听器:

第一大类:监听 Session、request、context 这三个==对象的创建与销毁==的:

  • HttpSessionListener

  • ServletContextListener

  • ServletRequestListener

第二大类:监听==对象属性==变化的:

  • HttpSessionAttributeListener

  • ServletContextAttributeListener

  • ServletRequestAttributeListener

第三类:监听Session 内的对象的:

  • HttpSessionBindingListener

  • HttpSessionActivationListener。

  • 与上面六类不同,这两类 Listener 监听的是Session 内的对象,而非 Session 本身,不需要在 web.xml中配置。

5.5 案例演示

5.5.1 ServletContextListener

package com.servlet.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 自定义一个类,实现Servlet上下文的监听器接口
 * 作用:可以监听Servlet上下文的创建和销毁时机。
 */
public class MyServletContextListener implements ServletContextListener {
    /**
     *
     * @param sce:  当监听器被通知时,事件对象自创创建,并赋值给方法的形参
     *
     *   监听器的方法:都是在发生事件时,自动调用的
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //获取时间,格式化成yyyy-MM-dd HH:mm:ss
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStr = sdf.format(now);
        //从监听事件对象上,获取Servlet上下文对象,然后从其身上获取当前项目名称
        String appName = sce.getServletContext().getContextPath();
        System.out.println("项目"+appName+"的ServletContext对象在"+timeStr+"被创建");

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //获取时间,格式化成yyyy-MM-dd HH:mm:ss
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStr = sdf.format(now);
        //从监听事件对象上,获取Servlet上下文对象,然后从其身上获取当前项目名称
        String appName = sce.getServletContext().getContextPath();
        System.out.println("项目"+appName+"的ServletContext对象在"+timeStr+"被销毁");
    }
}

在web.xml中注册监听, 放在servlet标签之前

<listener>
   <listener-class>com.servlet.listener.MyServletContextListener</listener-class>
</listener>

5.5.2 测试

启动服务器,进行查看控制台。。。。     关闭服务器,进行查看控制台

5.5.3 HttpSessionListener

package com.servlet.listener;
​
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
​
/**
 * 自定义一个类型,实现HttpSession监听器接口,用于监听Session对象的创建和销毁
 *
 * 对应的方法:
 *     sessionCreated():  Session对象创建时,被主动调用
 *     sessionDestroyed(): Session对象销毁时时,被主动调用
 */
public class MySessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("---创建了一个session对象----");
    }
​
    /**
     * session销毁的方式:
     *    1.  程序员主动调用session.invalidate()
     *    2.  session超时
     * @param se
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("---销毁了一个session对象----");
    }
}
​

在web.xml中注册监听, 放在servlet标签之前

<listener>
   <listener-class>com.servlet.listener.MySessionListener</listener-class>
</listener>

5.5.4 测试

随便访问该项目的一个请求资源路径,   换一个浏览器或者重开一个浏览器,再次访问。
​
测试销毁:  程序员主动调用session.invalidate()
           或者   session超时

5.5.5 ServletRequestListener

package com.servlet.listener;
​
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
​
/**
 * ServletRequestListener接口,用来监听request对象的创建和销毁
 *
 * 方法如下:
 *     requestInitialized(): 当request对象被创建时,自动调用
 *     requestDestroyed(): 当request对象被销毁时,自动调用
 */
public class MyRequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("------request对象被销毁了----------");
    }
​
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("------request对象被创建出来了----------");
    }
}
​

5.5.6 测试

随便访问一个该项目下的请求资源路径, 查看控制台

5.5.7 属性监听器

ServletContextAttributeListener/ServletRequestAttributeListener/HttpSessionAttributeListener三个监听接口,功能相似

package com.servlet.listener;
​
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
​
/**
 * 监听Servlet上下文对象的属性的。
 *   当绑定属性,修改属性,移除属性时,会被监听到
 */
public class MyContextAttributeListener implements ServletContextAttributeListener {
    /**
     * 添加属性时被触发
     * @param scae
     */
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        System.out.println("添加属性时被触发");
    }
    /**
     * 移除属性时被触发
     * @param scae
     */
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        System.out.println("移除属性时被触发");
    }
    /**
     * 替换修改属性时被触发
     * @param scae
     */
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        System.out.println("替换修改属性时被触发");
    }
}
​

5.5.8 测试

访问三个"/sctAdd","/sctReplace","/sctRemove"请求资源路径,进行测试即可

package com.servlet.listener;
​
import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
​
@WebServlet(urlPatterns = {"/sctAdd","/sctReplace","/sctRemove"})
public class MyContextAttributeListenerTest extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext sct = getServletContext();
​
        String uri = req.getRequestURI();
        if (uri.contains("sctAdd")) {
            sct.setAttribute("username","zhangsan");
        } else if (uri.contains("sctReplace")) {
            sct.setAttribute("username","lisi");
        }else if (uri.contains("sctRemove")) {
            sct.removeAttribute("username");
        }
    }
}

5.5.9 HttpSessionBindingListener

package com.servlet.vo;
​
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
​
/**
 * 自定义一个类,如果你想监听这个类的实例是否被绑定到session上时,
 * 就可以实现HttpSessionBindingListener接口
 *
 * 或者你想监听这个类的实例从session身上移除了,也可以实现该接口
 */
public class Student implements HttpSessionBindingListener {
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("--valueBound--");
    }
​
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("---valueUnbound---");
    }
}
​

5.5.10 测试

测试绑定

        Student student = new Student();
        session.setAttribute("s1",student);

测试移除

         session.removeAttribute("s1");

5.5.11 HttpSessionActivationListener

package com.servlet.vo;
​
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import java.io.Serializable;
​
/**
 * 自定义的类型:如果该类的实例对象,随着HttpSession对象一起序列化或者反序列时,你想要监听到这种状态,那就实现
 * 该接口
 */
public class Teacher implements Serializable, HttpSessionActivationListener {
    /**
     * 对象被钝化时触发:   钝化,就是序列化的意思
     * @param se
     */
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println("----对象被钝化了-----");
    }
​
    /**
     * 对象被活化时触发:   活化,就是反序列化的意思
     *
     *
     * 使用Session获取对象时,应该提前钝化一下,然后再读取钝化后文件里的数据
     * 就会激活活化方法,如果第二次再次读取,不会触发该方法,原因是第一次读取的
     * 已经保存到session里。第二次是从session中获取的,并不是从文件中获取的。
     * @param se
     */
    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println("----对象被活化了-----");
    }
}
​

5.5.12 测试

添加配置文件:与WEB-INF并列创建一个文件夹META-INF, 创建一个context.xml配置文件,放入下面配置信息

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!--    classname:  配置用于持久化Session的类型。
            saveOnRestart: true表示在重启时保存
              maxIdleSwap:session中的对象多久不使用就钝化,单位:分钟 -->
    <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true" maxIdleSwap="1">
        <!-- classname:  用于持久化的文件流, 
                directory:钝化文件的位置 -->
        <Store className="org.apache.catalina.session.FileStore" directory="D:/bb" />
    </Manager>
</Context>
​
​
默认钝化的位置:
%CATALINA_BASE%\work\Catalina\localhost\项目名\下

测试钝化:绑定对象到Session上,1分钟后查看控制台输出内容

        Teacher t1 = new Teacher();
        session.setAttribute("t1",t1);

测试活化: 获取session对象即可,不用获取session里的t1。当然必须是同一个session对象

                                                                   ---Servlet(完)---

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值