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

Spring Session 監聽器無法啟動:WebApplicationContext 獲取 Bean 正確姿勢

     編輯:程式設計綜合問答

錯誤堆疊

javax.naming.NamingException: Cannot create resource instance
at org.apache.naming.factory.ResourceEnvFactory.getObjectInstance...
at org.apache.catalina.core.StandardContext.listenerStart...

根因

HttpSessionListener 由 Servlet 容器(Tomcat)實例化,**早於 Spring 容器初始化完成**。監聽器構造時嘗試注入 Spring Bean(如 @Autowired UserService),但 Spring 尚未就緒,導致 JNDI 查找失敗。

解決方案:手動從 WebApplicationContext 獲取 Bean

public class SessionListener implements HttpSessionListener {
    private UserService userService;

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // 1. 獲取 ServletContext
        ServletContext sc = se.getSession().getServletContext();
        // 2. 獲取 Spring WebApplicationContext
        WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sc);
        // 3. 手動獲取 Bean
        if (userService == null) {
            userService = wac.getBean(UserService.class);
        }
        // 4. 執行業務邏輯
        userService.updateUserStatusOffline(se.getSession().getId());
    }

    @Override
    public void sessionCreated(HttpSessionEvent se) { /* 同理 */ }
}

關鍵類

  • org.springframework.web.context.support.WebApplicationContextUtils
  • org.springframework.web.context.WebApplicationContext

web.xml 註冊監聽器

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

進階:Spring 管理監聽器(需 Spring 3.1+)

<!-- web.xml -->
<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!-- 監聽器作為 Spring Bean 定義,需實現 ApplicationListener 延遲注入 -->

但手動 WebApplicationContextUtils.getBean() 更簡單通用,推薦使用。

避坑指南

  • 不要在監聽器構造器/字段注入 Spring Bean。
  • 每次使用前檢查 wac != null,防止上下文銷毀後調用。
  • 異步任務中獲取 Bean 需傳入 ServletContext 或使用 @Autowired 在 Spring 管理的組件中代理調用。

理解容器啟動順序,在監聽器/Filter 中正確獲取 Spring Bean,是 Java Web 開發必備技能。

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