首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java Servlet 監聽器完整指南:ServletContextListener、HttpSessionListener 實戰與常用介面速查

     編輯:Java 綜合教學

監聽器核心作用

監聽器 (Listener) 實現觀察者模式,監聽 Web 容器中的關鍵事件 (上下文啟動/銷毀、Session 創建/銷毀、屬性增刪改),自動觸發業務邏輯 (如統計在線人數、初始化緩存、清理資源)。

八大標準監聽介面

介面監聽事件核心方法典型應用
ServletContextListenerWeb 應用啟動/關閉contextInitialized / contextDestroyed初始化數據源、載入配置、啟動定時任務
ServletContextAttributeListenerApplication 域屬性增刪改attributeAdded / attributeRemoved / attributeReplaced審計日誌、集群同步
HttpSessionListenerSession 創建/銷毀sessionCreated / sessionDestroyed在線人數統計、Session 異常清理
HttpSessionAttributeListenerSession 域屬性增刪改attributeAdded / attributeRemoved / attributeReplaced購物車變更通知、權限即時刷新
ServletRequestListenerRequest 創建/銷毀requestInitialized / requestDestroyed請求耗時統計、鏈路追蹤 ID 生成
ServletRequestAttributeListenerRequest 域屬性增刪改attributeAdded / attributeRemoved / attributeReplaced參數過濾、安全審計
HttpSessionIdListenerSession ID 變更sessionIdChangedSession Fixation 防護
ServletContextListener (Servlet 4.0+)同上同上同上

實戰案例:統計在線用戶數

1. 監聽器實現

@WebListener
public class OnlineCounter implements HttpSessionListener {
    private static final AtomicInteger ONLINE_COUNT = new AtomicInteger(0);

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        int cnt = ONLINE_COUNT.incrementAndGet();
        se.getSession().getServletContext().setAttribute("onlineCount", cnt);
        System.out.println("用戶上線,當前在線:" + cnt);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        int cnt = ONLINE_COUNT.decrementAndGet();
        se.getSession().getServletContext().setAttribute("onlineCount", cnt);
        System.out.println("用戶下線,當前在線:" + cnt);
    }

    public static int getOnlineCount() { return ONLINE_COUNT.get(); }
}

2. web.xml 註冊 (或用 @WebListener 註解,Servlet 3.0+ 自動掃描)

<listener>
    <listener-class>com.example.OnlineCounter</listener-class>
</listener>

3. JSP 頁面顯示

<%@ page contentType="text/html;charset=UTF-8" %>
<html><body>
    當前在線用戶數:${applicationScope.onlineCount}
</body></html>

ServletContextListener 完整生命週期

@WebListener
public class AppInitializer implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext ctx = sce.getServletContext();
        // 1. 載入配置
        String configPath = ctx.getInitParameter("configPath");
        // 2. 初始化連接池/緩存
        DataSource ds = createDataSource();
        ctx.setAttribute("dataSource", ds);
        // 3. 啟動後台任務
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> refreshCache(ds), 0, 1, TimeUnit.HOURS);
        ctx.setAttribute("scheduler", scheduler);
        System.out.println("應用啟動完成");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        ServletContext ctx = sce.getServletContext();
        // 關閉資源
        ((ScheduledExecutorService) ctx.getAttribute("scheduler")).shutdown();
        ((DataSource) ctx.getAttribute("dataSource")).close();
        System.out.println("應用關閉,資源已釋放");
    }
}

最佳實踐與避坑

  • 線程安全:監聽器方法可能被多線程併發調用 (如 sessionCreated),共享狀態用 AtomicInteger/ConcurrentHashMap。
  • 異常處理:contextInitialized 拋異常會導致應用啟動失敗,關鍵初始化務必 try-catch 並記錄錯誤。
  • 資源釋放:contextDestroyed 必須關閉線程池、連接池、定時任務,否則內存洩漏。
  • 啟動順序:多個 Listener 按 web.xml 聲明順序 / 類名字母序執行;有依賴關係時顯式排序。
  • 分布式環境:單機監聽器只能統計本節點在線數,集群需結合 Redis 集合/廣播實現全局統計。

總結

Servlet 監聽器是 Web 應用「感知容器生命週期」的官方擴展點。熟練掌握八大介面、註冊方式、線程安全與資源管理,能優雅實現啟動初始化、在線統計、審計日誌、緩存刷新等橫切功能,保持 Controller/Service 純淨專注業務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved