Servlet 监听器(Listener):Web 应用的事件响应机制
监听器(Listener)是 Servlet 规范中用于监听 Web 应用中关键对象(如 ServletContext
、HttpSession
、ServletRequest
)的创建、销毁及属性变化的组件。它基于事件驱动模型,当特定事件触发时自动执行预设逻辑,常用于初始化资源、监控会话状态、记录请求日志等场景。本文将系统解析监听器的类型、使用方式及典型应用。
监听器的核心概念
什么是监听器?
监听器是实现了特定事件接口的 Java 类,通过监听 Web 应用中的域对象(ServletContext
、HttpSession
、ServletRequest
)或属性变化,在事件发生时执行回调方法。其核心作用是:
- 感知对象生命周期(创建 / 销毁);
- 监控对象属性变更(添加 / 移除 / 替换);
- 实现跨组件通信或资源初始化。
事件与监听器的关系
- 事件源:触发事件的对象(如
ServletContext
、HttpSession
); - 事件对象:封装事件源及相关信息(如
ServletContextEvent
、HttpSessionEvent
); - 监听器:监听事件并处理(如
ServletContextListener
、HttpSessionListener
)。
当事件源发生状态变化(如创建、属性修改)时,容器会创建对应的事件对象,并调用注册的监听器的回调方法。
监听器的分类与核心接口
Servlet 规范定义了多种监听器接口,按监听对象可分为三类:域对象生命周期监听器、域对象属性监听器、会话相关监听器。
域对象生命周期监听器
监听 ServletContext
、HttpSession
、ServletRequest
的创建与销毁。
监听器接口 | 事件对象 | 核心方法 | 触发时机 |
---|---|---|---|
ServletContextListener |
ServletContextEvent |
contextInitialized() contextDestroyed() |
Web 应用启动 / 关闭时 |
HttpSessionListener |
HttpSessionEvent |
sessionCreated() sessionDestroyed() |
会话创建(首次调用 getSession() )/ 销毁(超时或 invalidate() ) |
ServletRequestListener |
ServletRequestEvent |
requestInitialized() requestDestroyed() |
请求创建(客户端发起请求)/ 销毁(响应完成) |
示例:ServletContextListener
初始化资源
1 | // 监听Web应用启动与关闭,初始化数据库连接池 |
域对象属性监听器
监听域对象中属性的添加、移除或替换。
监听器接口 | 事件对象 | 核心方法 |
---|---|---|
ServletContextAttributeListener |
ServletContextAttributeEvent |
attributeAdded() attributeRemoved() attributeReplaced() |
HttpSessionAttributeListener |
HttpSessionBindingEvent |
同上 |
ServletRequestAttributeListener |
ServletRequestAttributeEvent |
同上 |
示例:监控 Session 属性变化
1 | // 监听Session中属性的添加、移除、替换 |
会话相关监听器
感知会话中对象的绑定、钝化 / 活化等状态变化,无需在 web.xml
中注册。
监听器接口 | 核心方法 | 作用描述 |
---|---|---|
HttpSessionBindingListener |
valueBound() valueUnbound() |
当对象被绑定到 Session 或从 Session 解绑时触发 |
HttpSessionActivationListener |
sessionWillPassivate() sessionDidActivate() |
当 Session 被钝化(写入磁盘)或活化(从磁盘加载)时触发 |
session会被存储在tomcat当前项目下 .cer文件
示例:HttpSessionBindingListener
感知对象绑定
1 | // 用户类:感知自己是否被绑定到Session |
监听器的配置方式
监听器需注册到 Servlet 容器才能生效,配置方式有两种:
XML 配置(web.xml
)
1 | <!-- 注册监听器,顺序不影响执行(除特殊情况外) --> |
注意:
ServletContextListener
的contextInitialized()
会在 Filter 和 Servlet 的init()
之前执行,保证资源优先初始化。
注解配置(Servlet 3.0+)
直接在监听器类上添加 @WebListener
注解:
1 |
|
监听器的典型应用场景
- 应用初始化:
通过ServletContextListener
在 Web 应用启动时初始化全局资源(如数据库连接池、Spring IOC 容器、加载配置文件),在关闭时释放资源。 - 会话监控:
通过HttpSessionListener
统计在线用户数量(sessionCreated()
加 1,sessionDestroyed()
减 1)。 - 请求日志:
通过ServletRequestListener
记录每个请求的 URL、访问时间、客户端 IP 等信息,用于审计或性能分析。 - 对象持久化:
通过HttpSessionActivationListener
处理 Session 钝化 / 活化(如 Tomcat 重启时保存会话数据到磁盘,恢复时重新加载)。 - 属性变更通知:
通过属性监听器监控关键属性变化(如配置修改),实时触发相应逻辑(如刷新缓存)。
注意事项
- 执行顺序:
- 多个
ServletContextListener
的contextInitialized()
执行顺序与注册顺序一致,contextDestroyed()
则相反。 - 其他监听器的执行顺序未明确规定,避免依赖顺序逻辑。
- 多个
- 性能影响:
- 监听器会拦截每一次事件(如每个请求、每个属性修改),避免在回调方法中执行耗时操作(如复杂计算、网络请求)。
- 会话钝化 / 活化:
- 实现
HttpSessionActivationListener
的类需实现Serializable
接口,否则对象无法被序列化到磁盘。
- 实现
- 资源共享:
- 全局资源(如连接池)建议存入
ServletContext
,通过getAttribute()
在整个应用中共享。
- 全局资源(如连接池)建议存入
v1.3.10