JNDI (Java Naming and Directory Interface) 為 Java 應用提供統一 API 存取命名/目錄服務。命名服務將名稱綁定至物件(如 DNS 解析網址、RMI 註冊表查找遠端物件);目錄服務更進一步賦予物件屬性(如 LDAP 中使用者的 email、電話),支援依屬性搜尋。集中儲存共享資訊讓網路應用更協調、易管理(如印表機設定集中於目錄服務)。
JNDI 架構(圖 1)採雙層設計:
javax.naming.* 等五大包,獨立於具體命名系統。開發者只需確保目標服務有對應的 JNDI 服務提供者(Sun 內建 LDAP、RMI、COS、DNS 四大提供者;更多可至 官網下載,含 Windows Registry、DSML v2.0、LDAP Booster Pack 等)。
javax.naming:核心命名操作,Context 介面為查詢入口。javax.naming.directory:目錄服務擴充,DirContext、Attributes 處理屬性。javax.naming.event:事件通知機制,NamingEvent、NamingListener。javax.naming.ldap:LDAP v3 專屬擴充操作與控制。javax.naming.spi:服務提供者開發用,動態擴充支援。「綁定」將名稱關聯物件,「上下文」是一組綁定的集合,提供 lookup、bind/unbind、list 等操作。子上下文類似檔案系統子目錄(/home 下的 guests)。
javax.naming.InitialContext 實作 Context,為命名服務入口。建構時需傳入環境屬性 Hashtable/Properties,關鍵屬性 Context.INITIAL_CONTEXT_FACTORY 指定服務提供者工廠類別(表 1):
| 服務 | 工廠類別 |
|---|---|
| LDAP | com.sun.jndi.ldap.LdapCtxFactory |
| RMI | com.sun.jndi.rmi.registry.RegistryContextFactory |
| CORBA COS | com.sun.jndi.cosnaming.CNCtxFactory |
| DNS | com.sun.jndi.dns.DnsContextFactory |
| 檔案系統 | com.sun.jndi.fscontext.RefFSContextFactory (需另載) |
程式碼範例:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=MyOrg");
Context ctx = new InitialContext(env);
查詢物件:Object obj = ctx.lookup("cn=JohnDoe,ou=People");
Context 方法提供雙重載:
lookup(String name):字串名稱lookup(Name name):結構化名稱——CompositeName (跨命名系統) 或 CompoundName (單一命名系統)。cn=mydir,cn=Q Mahmoud,ou=People (LDAP DN);cn=mydir,cn=Q Mahmoud,ou=People/myfiles/max.txt (複合名稱,後半段為檔案系統路徑)。設定 PROVIDER_URL 指向 LDAP 伺服器,使用 DirContext 操作屬性:getAttributes()、modifyAttributes()、search() (支援過濾條件)。LDAP v3 控制與擴充操作透過 javax.naming.ldap 套件存取。
J2EE 容器透過 JNDI 發布資源參考。應用元件以 java:comp/env 為前綴查詢:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/MyDB");
EJBHome home = (EJBHome) envCtx.lookup("ejb/MyBean");
部署描述檔 (web.xml/ejb-jar.xml) 宣告資源參考,容器負責綁定實際物件。
NamingListener、註冊 addNamingListener(),接收物件新增/修改/刪除事件。CompositeName 跨越多個命名系統(如 LDAP + 檔案系統),實現統一命名空間。JNDI 以統一 API 屏蔽底層命名/目錄服務差異,配合 SPI 機制實現無縫擴展。無論是企業級 LDAP 整合、J2EE 資源查找、或是檔案系統/RMI/CORBA 互操作,掌握 Context/DirContext 核心操作與環境屬性配置,即可輕鬆駕馭分散式命名資源。