// 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、或改名後舊值殘留
@Resource(name="w") 查找的是 java:comp/env/w。若 web.xml 宣告在 <web-app> 層級,屬於 Web 模組環境項目,僅對該 Web 應用可見。java:comp/env 並綁定 env-entry,再實例化 Servlet 並注入。若 Servlet 為 load-on-startup,注入發生在 init() 前;若非預載,首次請求時注入。name="wa" 後重啟 Tomcat,若舊應用未完全卸載 (類別載入器未釋放),舊 JNDI 綁定可能殘留,導致「改名後仍能取到舊值」。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,部署階段即可覆寫 (如測試/生產環境不同值)。
@Value("${w}") + PropertyPlaceholderConfigurer若專案已用 Spring,棄用 J2EE @Resource,改用 Spring 統一配置管理,支援 .properties/.yml/環境變數/命令列參數多源覆寫,穩定性遠優於 JNDI env-entry。
web.xml 中 env-entry-name 與 @Resource(name=...) 完全一致 (區分大小寫)。work/Catalina/localhost/ 下無殘留舊版應用目錄 (清理 work 目錄重啟)。init() 中使用 w,確保注入已完成 (加 @PostConstruct 或移至 doGet 首行)。J2EE @Resource 注入 env-entry 字串不穩定,主因在於 JNDI 綁定時序與熱部署殘留。生產環境建議:改用 Spring 配置體系 或 @PostConstruct 手動查找並加入啟動檢查,徹底消除「有時能注入、有時不能」的非決定行為。