JNDI(The Java Naming and Directory Interface,Java命名和目錄接口)是一組在Java應用中訪問命名和目錄服務的API。命名服務將名稱和對象聯系起來,使得我們可以用名稱訪問對象。目錄服務是一種命名服務,在這種服務里,對象不但有名稱,還有屬性。
命名或目錄服務使你可以集中存儲共有信息,這一點在網絡應用中是重要的,因為這使得這樣的應用更協調、更容易管理。例如,可以將打印機設置存儲在目錄服務中,以便被與打印機有關的應用使用。
JNDI概述
我們大家每天都不知不覺地使用了命名服務。例如,當你在web瀏覽器輸入URL,http://java.sun.com時, DNS(Domain Name System,域名系統)將這個符號URL名轉換成通訊標識(IP地址)。命名系統中的對象可以是DNS記錄中的名稱、 應用服務器中的EJB組件(Enterprise JavaBeans Component)、LDAP (Lightweight Directory Access Protocol)中的用戶Profile。
目錄服務是命名服務的自然 擴展。兩者之間的關鍵差別是目錄服務中對象可以有屬性(例如,用戶有email地址),而命名服務中對象沒有屬性。因此,在目錄服務中,你可以根據屬性搜 索對象。JNDI允許你訪問文件系統中的文件,定位遠程RMI注冊的對象,訪問象LDAP這樣的目錄服務,定位網絡上的EJB組件。
對于象LDAP 客戶端、應用launcher、類瀏覽器、網絡管理實用程序,甚至地址薄這樣的應用來說,JNDI是一個很好的選擇。
JNDI架構
JNDI 架構提供了一組標準的獨立于命名系統的API,這些API構建在與命名系統有關的驅動之上。這一層有助于將應用與實際數據源分離,因此不管應用訪問的是 LDAP、RMI、DNS、還是其他的目錄服務。換句話說,JNDI獨立于目錄服務的具體實現,只要你有目錄的服務提供接口(或驅動),你就可以使用目錄。
J2SE和JNDI
Java 2 SDK 1.3及以上的版本包含了JNDI。對于JDK 1.1和1.2也有一個標準的擴展。Java 2 SDK 1.4.x的最新版本包括了幾個增強和下面的命名/目錄服務提供者:
LDAP (Lightweight Directory Access Protocol)服務提供者CORBA COS (Common Object Request Broker Architecture Common Object Services)命名服務提供者RMI(Java Remote Method Invocation)注冊服務提供者 l DNS(Domain Name System)服務提供者。
JNDI API
JNDI API由5個包組成:
Javax.naming: 包含了訪問命名服務的類和接口。例如,它定義了Context接口,這是命名服務執行查詢的入口。 Javax.naming.directory: 對命名包的擴充,提供了訪問目錄服務的類和接口。例如,它為屬性增加了新的類,提供了表示目錄上下文的DirContext接口,定義了檢查和更新目錄對 象的屬性的方法。Javax.naming.event:提供了對訪問命名和目錄服務時的時間通知的支持。例如,定義了NamingEvent類, 這個類用來表示命名/目錄服務產生的事件,定義了偵聽NamingEvents的NamingListener接口。 Javax.naming.ldap:這個包提供了對LDAP 版本3擴充的操作和控制的支持,通用包 javax.naming.directory沒有包含這些操作和控制。Javax.naming.spi:這個包提供了一個方法,通過 javax.naming和有關包動態增加對訪問命名和目錄服務的支持。這個包是為有興趣創建服務提供者的開發者提供的。
JNDI 上下文
正如在前面提到的,命名服務將名稱和對象聯系起來。這種聯系稱之為綁定(binding)。一組這樣的綁定稱之為上下文(context),上下文提供了解 析(即返回對象的查找操作)。其他操作包括:名稱的綁定和取消綁定,列出綁定的名稱。注意到一個上下文對象的名稱可以綁定到有同樣的命名約定的另一個上下 文對象。這稱之為子上下文。例如,如果UNIX中目錄/home是一個上下文,那么相對于這個目錄的子目錄就是子上下文?例如,/home/guests 中guests就是home的子上下文。在JNDI中,上下文用接口javax.naming.Context表示,這個接口是與命名服務交互的關鍵接 口。在Context(或稍后討論的DirContext)接口中的每一個命名方法都有兩種重載形式:
Lookup (String name):接受串名 l Lookup(javax.naming.Name):接受結構名,例如,CompositeName(跨越 了多個命名系統的名稱)或CompondName(單個命名系統中的名稱);它們都實現了Name接口。Compound name的一個例子是:cn= mydir,cn=Q Mahmoud,ou=People,composite name的一個例子是:cn=mydir,cn=Q Mahmoud, ou=People/myfiles/max.txt(這里,myfiles/max.txt是表示第二部分的文件名) Javax.naming.InitialContext是實現了Context接口的類。用這個類作為命名服務的入口。為了創建 InitialContext對象,構造器以java.util.Hashtable或者是其子類(例如,Properties)的形式設置一組屬性。下面給出了一個例子:
Hashtable env = new Hashtable();
factory env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContext");
Context contxt = new InitialContext(env);
INITIAL_CONTEXT_FACTORY 指定了JNDI服務提供者中工廠類(factory class)的名稱。Factory負責為其服務創建適當的InitialContext對象。在上 面的代碼片斷中,為文件系統服務提供者指定了工廠類。
為了用名稱從命名服務或目錄中取得或解析對象,使用Context的lookup方法:Object obj=contxt.lookup(name)。Lookup方法返回一個對象,這個對象表示的是你想要找的上下文的兒子。