JavaWeb 基础之 Listener

290 阅读3分钟

基本概念

  • Servlet 规范中定义的一种特殊的组件,用来监听 Servlet 容器发生的事件并进行相应的处理
  • 容器发生的事件分类如下:
    • 生命周期相关的事件:主要监听生命周期,例如创建、销毁等事件
    • 属性状态相关的事件:主要监听属性变化,例如添加,修改,删除
    • 存值状态相关的事件
  • 底层原理是采用接口的回调方式实现

基本分类

Request 监听器

生命周期监听器:ServletRequestListener

  • 在 servletRequest 创建与关闭都会通知到监听器 |常用方法|触发情况| |-|-| |void requestInitailized(ServletRequestEvent sre)| 在servletRequset 初始化时会触发此方法| |void requestDestoryed(ServletRequestEvent sre)| 在servletRequset 销毁时会触发此方法|

属性状态监听器:ServletRequestAttributeListener

  • 向 servletRequest 添加、删除、替换一个属性值时会通知到监听器 |常用方法|触发情况| |-|-| |void attributeAdded(ServletRequestAttributeEvent srar)|添加属性时触发| |void attributeReplaced(ServletRequestAttributeEvent srar)|修改属性时触发| |void attributeRemoved(ServletRequestAttributeEvent srar)|删除属性时触发|

Session 监听器

生命周期监听器:HttpSessionListener

  • 在 HttpSession 创建与关闭都会通知到监听器 |常用方法|触发情况| |-|-| |void sessionCreated(ServletRequestEvent sre)|HttpSession 创建时调用| |void sessionDestoryed(ServletRequestEvent sre)|HttpSession 销毁时调用|

属性状态监听器:HttpSessionAttributeListener

  • 向 HttpSession 添加、删除、替换一个属性值时会通知到监听器 |常用方法|触发情况| |-|-| |void attributeAdded(HttpSessionBindingEvent srar)|在会话中添加属性时调用| |void attributeReplaced(HttpSessionBindingEvent srar)|在会话中修改属性时调用| |void attributeRemoved(HttpSessionBindingEvent srar)|在会话中删除属性时调用|

Application 监听器

生命周期监听器:ServletContextListener

  • 在 ServletContext 创建与关闭都会通知到监听器 |常用方法|触发情况| |-|-| |void contextInitailized(ServletRequestEvent sre)|当 ServletContext 创建时会调用| |void contextDestoryed(ServletRequestEvent sre)|当 ServletContext销毁时会调用
    (例如关闭服务器或者重新加载应用)|

属性状态监听器:ServletContextAttributeListener

  • 向 ServletContext 添加、删除、替换一个属性值时会通知到监听器 |常用方法|触发情况| |-|-| |void attributeAdded(ServletContextAttributeEvent srar)|往ServletContext中加入一个属性的时候触发| |void attributeReplaced(ServletContextAttributeEvent srar)|改变ServletContext中属性的时候触发| |void attributeRemoved(ServletContextAttributeEvent srar)|从ServletContext中删除一个属性的时候触发|

存值相关监听器

对象与 session 的绑定与解绑:HttpSessionBindingListener

  • HttpSession中实现此监听器的对象绑定了或者解绑时,会通知到 HttpSessionListener 监听器 |常用方法|触发情况| |-|-| |void valueBound(HttpSessionBindingEvent event)|有对象绑定时调用该方法| |void valueUnbound(HttpSessionBindingEvent event)|有对象解除绑定时调用该方法|

session 属性的钝化(序列化)与活化(反序列化):HttpSessionActivationListener

  • 实现此类的对象类也需要实现 Serialized 接口
  • 当有 session 数值的钝化和活化操作时,将会通知 HttpSessionActivationListener 监听器
  • 同时需要配置 context.xml 文件。否则默认钝化的文件存放在 work 目录先,一旦tomcat重新启动就会删除掉里面的文件 |常用方法|触发情况| |-|-| |void sessionWillPassivate(HttpSessionEvent event)|有钝化操作时调用| |void sessionDidActivate(HttpSessionEvent event)|有活化操作时调用|
<!--配置 context.xml 文件-->
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
      <!-- 配置文件存放的路径信息,可以自由指定 -->
      <Store className="org.apache.catalina.session.FileStore" directory="C:\session"/>
</Manager>

监听器案例(在线人数统计)

@WebListener
//实现 httpsessionListener 与 ServletContextListener接口 ,
//所以一旦session或servletContext 发生变化都会触发某一个方法
public class OnlineUserListener implements ServletContextListener, HttpSessionListener {
    ServletContext servletContext = null;


    //一旦 serlvetContext 初始化就会触发此方法
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
    	//一旦 serlvetContext 初始化就会触发此方法
        //获取 servlet 全局实例,用于保存在线人数
        servletContext = servletContextEvent.getServletContext();
    }
    
    //一旦 serlvetContext 被销毁就会触发此方法
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        servletContext = null;
    }

    //一旦有会话创建,触发此方法
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        Object onlineCount = servletContext.getAttribute("onlineCount");
        //如果是第一个 session,则添加属性为 1 的在线统计
        if (null == onlineCount) {
            servletContext.setAttribute("onlineCount", 1);
        } else {
            //不是第一个则将人数 + 1
            Integer integer = (Integer) onlineCount;
            integer++;
            servletContext.setAttribute("onlineCount", integer);
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
    }
}