**JNDI (Java Naming and Directory Interface)** 是 Java 命名與目錄接口,提供統一的 API 訪問各種命名服務(如 DNS、LDAP、RMI Registry)與目錄服務。在 J2EE 規範中,它是**組件查找資源、服務、彼此的核心粘合劑**,被專家視為「真正掌握 J2EE/EJB 的分水嶺」。
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");
// 使用連接...
} catch (Exception e) { ... }
問題:
核心思想: 將資源配置(數據源、EJB、JMS、環境變量等)交給 **J2EE 容器** 管理,應用代碼僅通過**邏輯名稱**查找引用。
<!-- mysql-ds.xml 部署到 server/default/deploy -->
<datasources>
<local-tx-datasource>
<jndi-name>MySqlDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/lw</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password>rootpassword</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata><type-mapping>mySQL</type-mapping></metadata>
</local-tx-datasource>
</datasources>
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:MySqlDS"); // 邏輯名稱
Connection conn = ds.getConnection();
// 使用連接...
conn.close(); // 歸還連接池,非物理關閉
收益:
| 概念 | 本質 | 生活類比 | 技術例子 |
|---|---|---|---|
| 命名服務 | 名稱 → 對象 的映射 (Name → Object) | 域名 → IP (DNS) 身份證號 → 人 學號 → 學生 | RMI Registry、COS Naming、DNS |
| 目錄服務 | 名稱 → 帶屬性的對象 (Name → Object + Attributes) 支援搜索、屬性查詢 | 電話簿:姓名 → {電話、地址、公司} 黃頁分類查找 | LDAP、Active Directory、NDS |
JNDI 統一了這兩類服務的訪問 API,使 Java 應用能以一致方式查找「數據源」(命名)或「打印機/用戶信息」(目錄)。
容器部署時將這些綁定到 JNDI 命名樹(通常在 `java:comp/env` 子樹下),組件通過 `
<resource-ref>
<res-ref-name>jdbc/MyDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
代碼中查找 `java:comp/env/jdbc/MyDataSource`(標準可移植寫法)JNDI 是 J2EE 的**交換機**,提供運行時的間接尋址能力,將組件與資源、服務、彼此解耦。它使應用具備**可配置、可部署、可伸縮**的企業級特質。掌握 JNDI,不僅是會用 `lookup`,更是理解**容器如何管理資源、組件如何聲明依賴、系統如何實現環境無關性**——這正是從「寫代碼」到「做架構」的關鍵認知躍遷。