Servlet 規範定義多種監聽器,用於感知 Web 應用生命週期、會話變化、屬性增刪改等事件。本文詳細講解三大類監聽器:域對象屬性監聽、Session 綁定感知、Servlet 請求/上下文/會話生命週期監聽,附完整代碼與配置示例。
監聽 ServletContext、HttpSession、ServletRequest 三大域對象的屬性增、刪、改事件。
| 監聽器介面 | 對應域 | 事件方法 |
|---|---|---|
ServletContextAttributeListener | Application | attributeAdded/Removed/Replaced |
HttpSessionAttributeListener | Session | attributeAdded/Removed/Replaced |
ServletRequestAttributeListener | Request | attributeAdded/Removed/Replaced |
@WebListener
public class MyContextAttrListener implements ServletContextAttributeListener {
@Override public void attributeAdded(ServletContextAttributeEvent e) {
log.info("Application 新增屬性: {} = {}", e.getName(), e.getValue());
}
@Override public void attributeRemoved(ServletContextAttributeEvent e) {
log.info("Application 移除屬性: {} = {}", e.getName(), e.getValue());
}
@Override public void attributeReplaced(ServletContextAttributeEvent e) {
log.info("Application 替換屬性: {} = {}", e.getName(), e.getValue());
}
}
web.xml 註冊(或用 @WebListener 註解):
<listener><listener-class>com.example.MyContextAttrListener</listener-class></listener>
這兩個介面由被綁定的 JavaBean 實作,無需在 web.xml 註冊。
HttpSessionBindingListenervalueBound(HttpSessionBindingEvent) / valueUnbound(...)HttpSessionActivationListenersessionWillPassivate(HttpSessionEvent) / sessionDidActivate(...)Serializable,且容器配置支援 Session 持久化(如 Tomcat context.xml 配置 PersistentManager)。public class UserSessionData implements HttpSessionBindingListener, Serializable {
private String username;
@Override public void valueBound(HttpSessionBindingEvent e) {
log.info("用戶 {} 登入,Session ID: {}", username, e.getSession().getId());
}
@Override public void valueUnbound(HttpSessionBindingEvent e) {
log.info("用戶 {} 登出/超時", username);
}
}
// 使用
session.setAttribute("userData", new UserSessionData("admin")); // 觸發 valueBound
session.removeAttribute("userData"); // 觸發 valueUnbound
| 監聽器 | 監聽對象 | 典型用途 |
|---|---|---|
ServletContextListener | Web 應用啟動/銷毀 | 初始化資源(連接池、配置、定時任務)、銷毀釋放 |
HttpSessionListener | Session 建立/銷毀 | 在線人數統計、Session 創建時預載資料 |
ServletRequestListener | Request 進入/銷毀 | 請求耗時統計、ThreadLocal 清理、Open-in-View 模式 |
@WebListener
public class AppInitializer implements ServletContextListener {
@Override public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
// 載入配置、初始化連接池、啟動排程器
DataSource ds = createDataSource();
ctx.setAttribute("dataSource", ds);
log.info("應用啟動完成");
}
@Override public void contextDestroyed(ServletContextEvent sce) {
DataSource ds = (DataSource) sce.getServletContext().getAttribute("dataSource");
if (ds instanceof HikariDataSource) ((HikariDataSource) ds).close();
log.info("應用關閉,資源釋放完成");
}
}
ServletContextListener:啟動時按配置順序 contextInitialized;銷毀時逆序 contextDestroyed。contextInitialized 拋出異常會導致應用啟動失敗。ContextLoaderListener、RequestContextListener 等,自動橋接 Spring 容器生命週期。監聽器是 JavaWeb 事件驅動架構的核心組件。掌握三大域屬性監聽、Session 綁定/鈍化感知、上下文/會話/請求生命週期監聽,能實現資源管理、統計分析、安全審計、快取預熱等橫切關注點。實務中配合 Spring 事件機制(ApplicationListener)可構建更靈活的業務事件體系。