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

J2EE @Resource 字串注入不穩定:JNDI 名稱綁定時序與作用域分析

     編輯:程式設計綜合問答

現象回顧

// web.xml
<env-entry>
  <env-entry-name>w</env-entry-name>
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>建築and環境學院</env-entry-value>
</env-entry>

// Servlet
@Resource(name="w")
private String w;
// 輸出 w + "ni zai na li?"
// 現象:間歇性注入失敗 (NameNotBoundException)、或注入為 null、或改名後舊值殘留

根因分析

  1. JNDI 名稱空間隔離: @Resource(name="w") 查找的是 java:comp/env/w。若 web.xml 宣告在 <web-app> 層級,屬於 Web 模組環境項目,僅對該 Web 應用可見。
  2. Servlet 類別載入時序: 容器啟動時,先建立 java:comp/env 並綁定 env-entry,再實例化 Servlet 並注入。若 Servlet 為 load-on-startup,注入發生在 init() 前;若非預載,首次請求時注入。
  3. 熱部署/重新部署殘留: 修改 name="wa" 後重啟 Tomcat,若舊應用未完全卸載 (類別載入器未釋放),舊 JNDI 綁定可能殘留,導致「改名後仍能取到舊值」。
  4. 容器 Bug / 版本差異: Tomcat 6/7/8/9 對 env-entry 處理有細微差異,早期版本存在注入競態。

穩健解決方案

方案一:改用 @PostConstruct 手動查找 (最可控)

@Resource(lookup = "java:comp/env/w") // 明確指定 JNDI 名稱
private String w; // 欄位可保留或移除

@PostConstruct
public void init() {
    try {
        Context ctx = new InitialContext();
        this.w = (String) ctx.lookup("java:comp/env/w");
        System.out.println("注入成功: " + w);
    } catch (NamingException e) {
        throw new IllegalStateException("環境項目 w 未綁定", e);
    }
}

方案二:統一放入 context.xml (全域/應用級)

<!-- META-INF/context.xml 或 conf/context.xml -->
<Context>
  <Environment name="w" value="建築and環境學院" type="java.lang.String" override="false"/>
</Context>

優點:不修改 web.xml,部署階段即可覆寫 (如測試/生產環境不同值)。

方案三:改用 Spring @Value("${w}") + PropertyPlaceholderConfigurer

若專案已用 Spring,棄用 J2EE @Resource,改用 Spring 統一配置管理,支援 .properties/.yml/環境變數/命令列參數多源覆寫,穩定性遠優於 JNDI env-entry。

驗證清單

  • web.xml 中 env-entry-name 與 @Resource(name=...) 完全一致 (區分大小寫)。
  • Servlet 類別非抽象、非內部類、有無參建構子。
  • Tomcat work/Catalina/localhost/ 下無殘留舊版應用目錄 (清理 work 目錄重啟)。
  • 若在 init() 中使用 w,確保注入已完成 (加 @PostConstruct 或移至 doGet 首行)。

總結

J2EE @Resource 注入 env-entry 字串不穩定,主因在於 JNDI 綁定時序與熱部署殘留。生產環境建議:改用 Spring 配置體系 或 @PostConstruct 手動查找並加入啟動檢查,徹底消除「有時能注入、有時不能」的非決定行為。

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