0%

Listener监听器

  • 什么是监听器?
    • 监听器是 Servlet 规范中的一员,就像 Filter 一样,Filter 也是 Servlet 规范中的一员。
    • 在 Servlet 中,所有的监听器接口都是以 “Listener” 结尾。
  • 监听器有什么用?
    • 监听器实际上是 Servlet 规范留给我们 javaweb 程序员的特殊时机。
    • 如果在某一段特殊的时刻想执行一段特定的代码,就需要想到使用对应的监听器。

8.★Listener监听器

8.1 监听器概述

  • 什么是监听器?

    • 监听器是 Servlet 规范中的一员,就像 Filter 一样,Filter 也是 Servlet 规范中的一员。
    • 在 Servlet 中,所有的监听器接口都是以 “Listener” 结尾。
  • 监听器有什么用?

    • 监听器实际上是 Servlet 规范留给我们 javaweb 程序员的特殊时机。
    • 如果在某一段特殊的时刻想执行一段特定的代码,就需要想到使用对应的监听器。
  • Servlet 规范中提供了哪些监听器?

    • jakarta.servlet 包下:

      • ServletContextListener:监听 ServletContext 对象的创建和销毁。
      • ServletContextAttributeListener:监听 ServletContext 域中数据的变化。
      • ServletRequestListener:监听 Request 对象的创建和销毁。
      • ServletRequestAttributeListener:监听 Request 域中数据的变化。
    • jakarta.servlet.http 包下:

      • HttpSessionListener:监听 Session 对象的创建和销毁。

      • HttpSessionAttributeListener

        • 该监听器需要使用 @WebListener 注解进行标注。
        • 该监听器监听的是什么?是 session 域中数据的变化。只要数据变化,则执行相应的方法。主要监测点在 session 域对象上。
      • HttpSessionBindingListener

        • 该监听器不需要使用 @WebListener 进行标注。是由要被监听的特定的类来实现该接口的。

        • 假设 User 类实现了该监听器,那么 User 对象在被放入 session 的时候触发 bind 事件,User 对象从 session 中删除的时候,触发 unbind 事件。

          假设 Customer 类没有实现该监听器,那么 Customer 对象放入 session 或者从 session 删除的时候,不会触发 bind 和 unbind 事件。

      • HttpSessionIdListener

        • session 的 id 发生改变的时候,监听器中的唯一一个方法就会被调用。
      • HttpSessionActivationListener

        • 监听 session 对象的钝化和活化的。
          • 钝化:session 对象从内存存储到硬盘文件。
          • 活化:从硬盘文件把 session 恢复到内存。

8.2 监听器的使用

  • 实现一个监听器的步骤:以 ServletContextListener 为例。

    • 第一步:编写一个类实现 ServletContextListener 接口。并且实现里面的方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      // ServletContextListener监听器主要监听的是ServletContext对象的状态
      @WebListener
      public class MyServletContextListener implements ServletContextListener {
      @Override
      public void contextInitialized(ServletContextEvent sce) {
      // 这个方法在ServletContext对象被创建的时候调用, 由web服务器自动调用。
      System.out.println("ServletContext对象创建了...");
      }

      @Override
      public void contextDestroyed(ServletContextEvent sce) {
      // 这个方法在ServletContext对象被销毁的时候调用, 由web服务器自动调用。
      System.out.println("ServletContext对象销毁了...");
      }
      }
    • 第二步:在 web.xml 文件中对 ServletContextListener 进行配置,如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
      version="6.0">

      <listener>
      <listener-class>com.f.javaweb.listener.MyServletContextListener</listener-class>
      </listener>

      </web-app>
      • 当然,第二步也可以不使用配置文件,也可以用注解,例如:@WebListener
    • 第三步:在 ServletContext 对象创建或者销毁的时候,web 服务器就会调用相应的方法。不需要你去 new MyServletContextListener 对象,也不需要你去主动调用其中的方法。

  • 注意:所有监听器中的方法都是不需要 javaweb 程序员调用的,由服务器来负责调用?什么时候被调用呢?

    • 当某个特殊的事件发生(特殊的事件发生其实就是某个时机到了)之后,被 web 服务器自动调用
  • 思考一个业务场景:

    • 请编写一个功能,记录该网站实时的在线用户的个数。

    • 我们可以通过服务器端有没有分配 session 对象来实现,因为一个 session 代表了一个用户。有一个 session 就代表有一个用户。如果你采用这种逻辑去实现的话,session 有多少个,在线用户就有多少个。

      这种方式的话:HttpSessionListener 够用了。session 对象只要新建,则 count++,然后将 count 存储到 ServletContext 域当中,在页面展示在线人数即可。有会话但是不一定登录了。

    • 业务发生改变了,只统计登录的用户的在线数量,这个该怎么办?这里和上面的区别在于,用户是登录了的。

      • session.setAttribute("user", userObj);
      • 用户登录的标志是什么?session 域中存储了 User 类型的对象。那么这个时候可以让 User 类型的对象实现 HttpSessionBindingListener 监听器,只要 User 类型对象存储到 session 域中,则 count++,然后将 count++ 存储到 ServletContext 对象中。页面展示在线人数即可。
---------------The End---------------