基于JNDI的應(yīng)用開(kāi)發(fā)
JNDI(The Java Naming and Directory Interface,Java命名和目錄接口)是一組在Java應(yīng)用中訪問(wèn)命名和目錄服務(wù)的API.命名服務(wù)將名稱和對(duì)象聯(lián)系起來(lái),使得我們可以用名稱訪問(wèn)對(duì)象。目錄服務(wù)是一種命名服務(wù),在這種服務(wù)里,對(duì)象不但有名稱,還有屬性。
命名或目錄服務(wù)使你可以集中存儲(chǔ)共有信息,這一點(diǎn)在網(wǎng)絡(luò)應(yīng)用中是重要的,因?yàn)檫@使得這樣的應(yīng)用更協(xié)調(diào)、更容易管理。例如,可以將打印機(jī)設(shè)置存儲(chǔ)在目錄服務(wù)中,以便被與打印機(jī)有關(guān)的應(yīng)用使用。
JNDI概述
我們大家每天都不知不覺(jué)地使用了命名服務(wù)。例如,當(dāng)你在web瀏覽器輸入U(xiǎn)RL,http://java.sun.com時(shí),DNS(Domain Name System,域名系統(tǒng))將這個(gè)符號(hào)URL名轉(zhuǎn)換成通訊標(biāo)識(shí)(IP地址)。命名系統(tǒng)中的對(duì)象可以是DNS記錄中的名稱、應(yīng)用服務(wù)器中的EJB組件(Enterprise JavaBeans Component)、LDAP(Lightweight Directory Access Protocol)中的用戶Profile.
目錄服務(wù)是命名服務(wù)的自然擴(kuò)展。兩者之間的關(guān)鍵差別是目錄服務(wù)中對(duì)象可以有屬性(例如,用戶有email地址),而命名服務(wù)中對(duì)象沒(méi)有屬性。因此,在目錄服務(wù)中,你可以根據(jù)屬性搜索對(duì)象。JNDI允許你訪問(wèn)文件系統(tǒng)中的文件,定位遠(yuǎn)程RMI注冊(cè)的對(duì)象,訪問(wèn)象LDAP這樣的目錄服務(wù),定位網(wǎng)絡(luò)上的EJB組件。
對(duì)于象LDAP 客戶端、應(yīng)用launcher、類瀏覽器、網(wǎng)絡(luò)管理實(shí)用程序,甚至地址薄這樣的應(yīng)用來(lái)說(shuō),JNDI是一個(gè)很好的選擇。
JNDI架構(gòu)
JNDI架構(gòu)提供了一組標(biāo)準(zhǔn)的獨(dú)立于命名系統(tǒng)的API,這些API構(gòu)建在與命名系統(tǒng)有關(guān)的驅(qū)動(dòng)之上。這一層有助于將應(yīng)用與實(shí)際數(shù)據(jù)源分離,因此不管應(yīng)用訪問(wèn)的是LDAP、RMI、DNS、還是其他的目錄服務(wù)。換句話說(shuō),JNDI獨(dú)立于目錄服務(wù)的具體實(shí)現(xiàn),只要你有目錄的服務(wù)提供接口(或驅(qū)動(dòng)),你就可以使用目錄。如圖1所示。 圖1:JNDI架構(gòu)
關(guān)于JNDI要注意的重要一點(diǎn)是,它提供了應(yīng)用編程接口(application programming interface,API)和服務(wù)提供者接口(service provider interface,SPI)。這一點(diǎn)的真正含義是,要讓你的應(yīng)用與命名服務(wù)或目錄服務(wù)交互,必須有這個(gè)服務(wù)的JNDI服務(wù)提供者,這正是JNDI SPI發(fā)揮作用的地方。服務(wù)提供者基本上是一組類,這些類為各種具體的命名和目錄服務(wù)實(shí)現(xiàn)了JNDI接口?很象JDBC驅(qū)動(dòng)為各種具體的數(shù)據(jù)庫(kù)系統(tǒng)實(shí)現(xiàn)了JDBC接口一樣。作為一個(gè)應(yīng)用開(kāi)發(fā)者,你不必操心JNDI SPI.你只需要確認(rèn)你要使用的每一個(gè)命名或目錄服務(wù)都有服務(wù)提供者。
J2SE和JNDI
Java 2 SDK 1.3及以上的版本包含了JNDI.對(duì)于JDK 1.1和1.2也有一個(gè)標(biāo)準(zhǔn)的擴(kuò)展。Java 2 SDK 1.4.x的最新版本包括了幾個(gè)增強(qiáng)和下面的命名/目錄服務(wù)提供者:
l LDAP(Lightweight Directory Access Protocol)服務(wù)提供者 l CORBA COS(Common Object Request Broker Architecture Common Object Services)命名服務(wù)提供者 l RMI(Java Remote Method Invocation)注冊(cè)服務(wù)提供者 l DNS(Domain Name System)服務(wù)提供者
更多的服務(wù)提供者
可以在如下網(wǎng)址找到可以下載的服務(wù)提供者列表:
http://java.sun.com/products/jndi/serviceproviders.html 特別有意思的或許是如下網(wǎng)址提供的Windows 注冊(cè)表JNDI服務(wù)提供者:http://cogentlogic.com/cocoon/CogentLogicCorporation/JNDI.xml 這個(gè)服務(wù)提供者使你可以訪問(wèn)Windows XP/2000/NT/Me/9x的windows注冊(cè)表。
也可以在如下網(wǎng)址下載JNDI/LDAP Booster Pack:http://java.sun.com/products/jndi/ 這個(gè)Booster Pack包含了對(duì)流行的LDAP控制的支持和擴(kuò)展。它代替了與LDAP 1.2.1服務(wù)提供者捆綁在一起的booster pack.關(guān)于控制和擴(kuò)展的更多信息可以在如下網(wǎng)站看到: http://java.sun.com/products/jndi/tutorial/ldap/ext/index.html 另一個(gè)有趣的服務(wù)提供者是Sun的支持DSML v2.0(Directory Service Markup Language,目錄服務(wù)標(biāo)記語(yǔ)言)的服務(wù)提供者。DSML的目的是在目錄服務(wù)和XML之間架起一座橋梁。
JNDI API
JNDI API由5個(gè)包組成:
l Javax.naming:包含了訪問(wèn)命名服務(wù)的類和接口。例如,它定義了Context接口,這是命名服務(wù)執(zhí)行查詢的入口。 l Javax.naming.directory:對(duì)命名包的擴(kuò)充,提供了訪問(wèn)目錄服務(wù)的類和接口。例如,它為屬性增加了新的類,提供了表示目錄上下文的DirContext接口,定義了檢查和更新目錄對(duì)象的屬性的方法。 l Javax.naming.event:提供了對(duì)訪問(wèn)命名和目錄服務(wù)時(shí)的時(shí)間通知的支持。例如,定義了NamingEvent類,這個(gè)類用來(lái)表示命名/目錄服務(wù)產(chǎn)生的事件,定義了偵聽(tīng)NamingEvents的NamingListener接口。 l Javax.naming.ldap:這個(gè)包提供了對(duì)LDAP 版本3擴(kuò)充的操作和控制的支持,通用包javax.naming.directory沒(méi)有包含這些操作和控制。 l Javax.naming.spi:這個(gè)包提供了一個(gè)方法,通過(guò)javax.naming和有關(guān)包動(dòng)態(tài)增加對(duì)訪問(wèn)命名和目錄服務(wù)的支持。這個(gè)包是為有興趣創(chuàng)建服務(wù)提供者的開(kāi)發(fā)者提供的。
JNDI 上下文
正如在前面提到的,命名服務(wù)將名稱和對(duì)象聯(lián)系起來(lái)。這種聯(lián)系稱之為綁定(binding)。一組這樣的綁定稱之為上下文(context),上下文提供了解析(即返回對(duì)象的查找操作)。其他操作包括:名稱的綁定和取消綁定,列出綁定的名稱。注意到一個(gè)上下文對(duì)象的名稱可以綁定到有同樣的命名約定的另一個(gè)上下文對(duì)象。這稱之為子上下文。例如,如果UNIX中目錄/home是一個(gè)上下文,那么相對(duì)于這個(gè)目錄的子目錄就是子上下文?例如,/home/guests中g(shù)uests就是home的子上下文。在JNDI中,上下文用接口javax.naming.Context表示,這個(gè)接口是與命名服務(wù)交互的關(guān)鍵接口。在Context(或稍后討論的DirContext)接口中的每一個(gè)命名方法都有兩種重載形式:
Lookup(String name):接受串名 l
Lookup(javax.naming.Name):接受結(jié)構(gòu)名,
例如,CompositeName(跨越了多個(gè)命名系統(tǒng)的名稱)或CompondName(單個(gè)命名系統(tǒng)中的名稱);它們都實(shí)現(xiàn)了Name接口。Compound name的一個(gè)例子是:cn=mydir,cn=Q Mahmoud,ou=People,composite name的一個(gè)例子是:cn=mydir,cn=Q Mahmoud,ou=People/myfiles/max.txt(這里,myfiles/max.txt是表示第二部分的文件名)
Javax.naming.InitialContext是實(shí)現(xiàn)了Context接口的類。用這個(gè)類作為命名服務(wù)的入口。為了創(chuàng)建InitialContext對(duì)象,構(gòu)造器以java.util.Hashtable或者是其子類(例如,Properties)的形式設(shè)置一組屬性。下面給出了一個(gè)例子:
Hashtable env = new Hashtable(); // select a service provider factory env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContext"); // create the initial context Context contxt = new InitialContext(env);
INITIAL_CONTEXT_FACTORY指定了JNDI服務(wù)提供者中工廠類(factory class)的名稱。Factory負(fù)責(zé)為其服務(wù)創(chuàng)建適當(dāng)?shù)腎nitialContext對(duì)象。在上面的代碼片斷中,為文件系統(tǒng)服務(wù)提供者指定了工廠類。表1給出了所支持的服務(wù)提供者的工廠類。要注意的是文件系統(tǒng)服務(wù)提供者的工廠類需要從Sun公司單獨(dú)下載,J2SE 1.4.x沒(méi)有包含這些類。
表1:上下文INITIAL_CONTEXT_FACTORY的值 Name Service Provider Factory
File System com.sun.jndi.fscontext.RefFSContextFactory
LDAP com.sun.jndi.ldap.LdapCtxFactory
RMI com.sun.jndi.rmi.registry.RegistryContextFactory
CORBA com.sun.jndi.cosnaming.CNCtxFactory
DNS com.sun.jndi.dns.DnsContextFactory
為了用名稱從命名服務(wù)或目錄中取得或解析對(duì)象,使用Context的lookup方法:Object obj=contxt.lookup(name)。Lookup方法返回一個(gè)對(duì)象,這個(gè)對(duì)象表示的是你想要找的上下文的兒子。
----------------------------------------------------------------------------------------------------------------------------
對(duì)jndi總體的理解: jndi(java naming and directory Interface)它提供了一套使用命名和目錄服務(wù)的接口。用戶可以通過(guò)它來(lái)使用命名和目錄服務(wù)。就像jdbc一樣。jndi包括
命名服務(wù)和
目錄服務(wù)兩部分,其中目錄服務(wù)包含目錄對(duì)象directory object,它包含若干屬性對(duì)象。提供了對(duì)屬性的很多操作。
命名和目錄服務(wù): 命名和目錄服務(wù)我們一直在使用,如操作系統(tǒng)的文件系統(tǒng),它給我們提供對(duì)文件的操作,查詢,添加刪除等功能。DNS服務(wù)將url同ip地址綁定在了一起。命名和目錄系統(tǒng)的最主要的功能是將name和對(duì)象綁定。在它的基礎(chǔ)之上還提供更多的功能如lookup,search.而且存儲(chǔ)的對(duì)象是有一定層次結(jié)構(gòu)的。使用這樣的服務(wù)我們可以對(duì)對(duì)象更加有效的管理和操作。
命名服務(wù)將一個(gè)名稱映射到一個(gè)對(duì)象。RMI Registry和CORBA Naming Service都是命名服務(wù)。
目錄服務(wù)也存放對(duì)象,但目錄服務(wù)識(shí)別這些對(duì)象的相關(guān)屬性。可以用項(xiàng)目屬性來(lái)搜索目錄。
在20世紀(jì)90年代早期,輕量級(jí)的目錄訪問(wèn)協(xié)議(LightWeightDiretoryAccessProtocol,LDAP)被作為一種標(biāo)準(zhǔn)的目錄協(xié)議被開(kāi)發(fā)出來(lái),JNDI能夠訪問(wèn)LDAP。

j2se為jndi提供了5個(gè)擴(kuò)展包:
javax.naming;為訪問(wèn)命名服務(wù)提供的api
javax.naming.directory;為訪問(wèn)目錄服務(wù)提供了基本的接口
javax.naming.event;支持命名和目錄服務(wù)中的事件通知
javax.naming.ldap; 支持ldap的包,
javax.naming.spi;提供了不同命名和目錄服務(wù)可以掛接他們的實(shí)現(xiàn)的方法。
context: context是一套name-to-object的綁定(bindings),可以理解為層次或目錄,它還可已包括下一層subContext。在使用命名和目錄服務(wù)時(shí)獲得initial context是對(duì)整個(gè)名字空間操作的入口。在目錄服務(wù)中是DirContext.
-------------------------------
JNDI(Java Naming and Directory Interface)是一個(gè)應(yīng)用程序設(shè)計(jì)的API,為開(kāi)發(fā)人員提供了查找和訪問(wèn)各種命名和目錄服務(wù)的通用、統(tǒng)一的接口,類似JDBC都是構(gòu)建在抽象層上。
JNDI可訪問(wèn)的現(xiàn)有的目錄及服務(wù)有:
DNS、XNam 、Novell目錄服務(wù)、LDAP(Lightweight Directory Access Protocol 輕型目錄訪問(wèn)協(xié)議)、 CORBA對(duì)象服務(wù)、文件系統(tǒng)、Windows XP/2000/NT/Me/9x的注冊(cè)表、RMI、DSML v1&v2、NIS。
JNDI優(yōu)點(diǎn):
包含了大量的命名和目錄服務(wù),使用通用接口來(lái)訪問(wèn)不同種類的服務(wù);可以同時(shí)連接到多個(gè)命名或目錄服務(wù)上;建立起邏輯關(guān)聯(lián),允許把名稱同Java對(duì)象或資源關(guān)聯(lián)起來(lái),而不必指導(dǎo)對(duì)象或資源的物理ID。
JNDI程序包:
javax.naming:命名操作;
javax.naming.directory:目錄操作;
javax.naming.event:在命名目錄服務(wù)器中請(qǐng)求事件通知;
javax.naming.ldap:提供LDAP支持;
javax.naming.spi:允許動(dòng)態(tài)插入不同實(shí)現(xiàn)。
利用JNDI的命名與服務(wù)功能來(lái)滿足企業(yè)級(jí)APIs對(duì)命名與服務(wù)的訪問(wèn),諸如EJBs、JMS、JDBC 2.0以及IIOP上的RMI通過(guò)JNDI來(lái)使用CORBA的命名服務(wù)。
JNDI與JDBC:
JNDI提供了一種統(tǒng)一的方式,可以用在網(wǎng)絡(luò)上查找和訪問(wèn)服務(wù)。通過(guò)指定一個(gè)資源名稱,該名稱對(duì)應(yīng)于數(shù)據(jù)庫(kù)或命名服務(wù)中的一個(gè)紀(jì)錄,同時(shí)返回?cái)?shù)據(jù)庫(kù)連接建立所必須的信息。
代碼示例:
try{
Context cntxt = new InitialContext();
DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
}
catch(NamingException ne){
...
}
JNDI與JMS:
消息通信是軟件組件或應(yīng)用程序用來(lái)通信的一種方法。JMS就是一種允許應(yīng)用程序創(chuàng)建、發(fā)送、接收、和讀取消息的JAVA技術(shù)。
代碼示例:
try{
Properties env = new Properties();
InitialContext inictxt = new InitialContext(env);
TopicConnectionFactory connFactory = (TopicConnectionFactory) inictxt.lookup("TTopicConnectionFactory");
...
}
catch(NamingException ne){
...
}
訪問(wèn)特定目錄:舉個(gè)例子,人是個(gè)對(duì)象,他有好幾個(gè)屬性,諸如這個(gè)人的姓名、電話號(hào)碼、電子郵件地址、郵政編碼等屬性。通過(guò)getAttributes()方法
Attribute attr = directory.getAttributes(personName).get("email");
String email = (String)attr.get();
通過(guò)使用JNDI讓客戶使用對(duì)象的名稱或?qū)傩詠?lái)查找對(duì)象:
foxes = directory.search("o=Wiz,c=US", "sn=Fox", controls);
通過(guò)使用JNDI來(lái)查找諸如打印機(jī)、數(shù)據(jù)庫(kù)這樣的對(duì)象,查找打印機(jī)的例子:
Printer printer = (Printer)namespace.lookup(printerName);
printer.print(document);
瀏覽命名空間:
NamingEnumeration list = namespace.list("o=Widget, c=US");
while (list.hasMore()) {
NameClassPair entry = (NameClassPair)list.next();
display(entry.getName(), entry.getClassName());
}
參考資料:
http://java.sun.com/products/jndi/examples.html
http://java.sun.com/products/jndi/serviceproviders.html
常用的JNDI操作:
void bind(String sName,Object object);――綁定:把名稱同對(duì)象關(guān)聯(lián)的過(guò)程
void rebind(String sName,Object object);――重新綁定:用來(lái)把對(duì)象同一個(gè)已經(jīng)存在的名稱重新綁定
void unbind(String sName);――釋放:用來(lái)把對(duì)象從目錄中釋放出來(lái)
void lookup(String sName,Object object);――查找:返回目錄總的一個(gè)對(duì)象
void rename(String sOldName,String sNewName);――重命名:用來(lái)修改對(duì)象名稱綁定的名稱
NamingEnumeration listBinding(String sName);――清單:返回綁定在特定上下文中對(duì)象的清單列表
NamingEnumeration list(String sName);
代碼示例:重新得到了名稱、類名和綁定對(duì)象。
NamingEnumeration namEnumList = ctxt.listBinding("cntxtName");
...
while ( namEnumList.hasMore() ) {
Binding bnd = (Binding) namEnumList.next();
String sObjName = bnd.getName();
String sClassName = bnd.getClassName();
SomeObject objLocal = (SomeObject) bnd.getObject();
}
--------------------------------------------------------------------------------------------------------------------------------------------------------
了解名字服務(wù)和目錄服務(wù)的相關(guān)概念,有助于更好的使用JNDI。
Naming service
名字服務(wù)定義了如何將名字與對(duì)象關(guān)聯(lián),并通過(guò)名字如何找到對(duì)象的方法。典型的例子如:DNS將域名與IP關(guān)聯(lián),文件系統(tǒng)將文件名與文件相關(guān)聯(lián)。在名字服務(wù)中,主要的概念:
- 名字(Names),在名字系統(tǒng)中實(shí)際對(duì)象的代號(hào),如文件名,域名等,它會(huì)被用來(lái)查找關(guān)聯(lián)的對(duì)象。不同的系統(tǒng)中會(huì)有不同的命名規(guī)范,如文件系統(tǒng)采用“\”來(lái)表示層級(jí),而DNS則使用“.”。
- 綁定(Bindings),名字和實(shí)際對(duì)象的關(guān)聯(lián)。
- 引用和地址(References and Addresses),當(dāng)對(duì)象不能直接被存儲(chǔ)在名字系統(tǒng)時(shí),就必須使用引用,通過(guò)引用找到實(shí)際的對(duì)象。在系統(tǒng)中,保存的引用的內(nèi)容被稱為地址。引用還有另一個(gè)用處:在名字系統(tǒng)中,缺少象關(guān)系數(shù)據(jù)庫(kù)中外鍵的概念。通過(guò)使用引用,可以作為外鍵的一個(gè)取代辦法。
- 上下文(Context),它是一個(gè)名字-對(duì)象集合,提供了與名字系統(tǒng)交互的主要操作,如查找、綁定、去綁定。子上下文(subcontext)與它的關(guān)系類似文件系統(tǒng)中目錄和子目錄的關(guān)系,子上下文被包含在一個(gè)上下文中,通過(guò)父上下文中的一個(gè)名字與子上下文關(guān)聯(lián)。
- 名字系統(tǒng)和名字空間(Naming Systems and Namespaces),名字系統(tǒng)是相同類型的上下文的集合,它提供名字服務(wù);名字空間,是名字系統(tǒng)中的名字集合,如文件系統(tǒng)的文件名和目錄。
Directory service
目錄服務(wù)是名字服務(wù)的擴(kuò)展,它除了關(guān)聯(lián)名字和對(duì)象,還允許對(duì)象包含屬性。目錄系統(tǒng)通常以層次結(jié)構(gòu)組織數(shù)據(jù)。在目錄服務(wù)中的主要概念:
- 屬性(Attributes),它屬于目錄對(duì)象,它是(名字,值)對(duì),屬性可以有多個(gè)值。
- 目錄和目錄服務(wù)(Directories and Directory Services),目錄是目錄對(duì)象的集合;目錄服務(wù)則提供與目錄相關(guān)的服務(wù),創(chuàng)建、刪除和修改存放在目錄中的對(duì)象的屬性。
- 查找和查找過(guò)濾器(Searches and Search Filters),獲取目錄對(duì)象的操作就是查找;過(guò)濾器是類似查找條件的對(duì)象。
基本使用
² 注冊(cè)JNDI提供者
在使用JNDI之前,需要先獲取JNDI的提供者,并在系統(tǒng)注冊(cè)它。與JNDI相關(guān)的系統(tǒng)屬性在javax.naming.Context中定義,常用的屬性:
- java.naming.factory.initial,服務(wù)提供者用來(lái)創(chuàng)建InitialContext的類名。
- java.naming.provider.url,用來(lái)配置InitialContext的初始url
- java.naming.factory.object,用來(lái)創(chuàng)建name-to-object映射的類,用于NameClassPair和References。
- java.naming.factory.state,用來(lái)創(chuàng)建jndi state的類
對(duì)于目錄服務(wù),由于一般需要安全設(shè)置,還通常使用:
- java.naming.security.authentication,安全類型,三個(gè)值:none,simple或strong。
- java.naming.security.principal,認(rèn)證信息。
- java.naming.security.credentials,證書(shū)信息。
- java.naming.security.protocol,安全協(xié)議名。
使用System.setProperty注冊(cè),如果程序不顯示說(shuō)明,那么java會(huì)在classpath內(nèi)查找jdni.properties文件來(lái)完成注冊(cè)。jdni.properties例子:
java.naming.factory.initial=com.codeline.db.MockInitialContextFactory
² 連接服務(wù)
注冊(cè)之后,就可以實(shí)施服務(wù)連接了。對(duì)于名字服務(wù)由InitialContext開(kāi)始,目錄服務(wù)則使用InitialDirContext。它們分別實(shí)現(xiàn)了Context和DirContext,這兩個(gè)接口分別對(duì)應(yīng)名字服務(wù)和目錄服務(wù)的接口,也是JNDI中最重要的兩個(gè)接口。
- 連接名字服務(wù):
1
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"
2
com.sun.jndi.fscontext.FSContextFactory");
3
InitialContext ctx = new InitialContext();
4
5
- 連接目錄服務(wù):
1
Hashtable env = new Hashtable();
2
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
3
env.put(Context.PROVIDER_URL, "ldap://myserver.com/");
4
env.put(Context.SECURITY_AUTHENTICATION, "simple");
5
//登錄ldap server需要的用戶名
6
env.put(Context.SECURITY_PRINCIPAL, "ldapuser");
7
//登錄ldap server需要的密碼
8
env.put(Context.SECURITY_CREDENTIALS, "mypassword");
9
InitialDirContext ctx = new InitialDirContext(env);
- 多服務(wù)提供者:如果應(yīng)用包含多個(gè)服務(wù)提供者,在連接時(shí)略有不同。以名字服務(wù)為例:
1
Hashtable env = new Hashtable();
2
env.put(Context.INITIAL_CONTEXT_FACTORY,
3
"com.sun.jndi.rmi.registry.RegistryContextFactory");
4
env.put(Context.PROVIDER_URL, "rmi://myserver.com:1099");
5
//使用不同的構(gòu)造函數(shù)
6
InitialContext ctx = new InitialContext(env);
² 查找對(duì)象
不論名字服務(wù)還是目錄服務(wù),都是使用lookup來(lái)查找對(duì)象的。除了可以使用String作為參數(shù)之外,lookup還可使用Name接口作為參數(shù)。
1
Greeter greeter = (Greeter)ctx.lookup("SayHello");
如果想要獲得上下文中所有的對(duì)象名字,就使用lis返回NameClassPair列表。NameClassPair包含對(duì)象名字和對(duì)象類名。如果想要獲得實(shí)際的對(duì)象實(shí)例列表,就使用listBindings,它返回Binding列表。Binding是NameClassPair的子類,它包含對(duì)象的實(shí)例。
- list
1
NamingEnumeration list = ctx.list("awt");
2
while (list.hasMore()) {
3
NameClassPair nc = (NameClassPair)list.next();
4
System.out.println(nc);
5
}
- listBindings
1
NamingEnumeration bindings = ctx.listBindings("awt");
2
while (bindings.hasMore()) {
3
Binding bd = (Binding)bindings.next();
4
System.out.println(bd.getName() + ": " + bd.getObject());
5
}
² 對(duì)象綁定
- 使用bind添加綁定
1
Fruit fruit = new Fruit("orange");
2
ctx.bind("favorite", fruit);
- 使用rebind修改綁定
1
Fruit fruit = new Fruit("lemon");
2
ctx.rebind("favorite", fruit);
- 使用unbind去除綁定。
1
ctx.unbind("favorite");
² 對(duì)象改名
使用rename可以給一個(gè)在上下文中的對(duì)象改名
1
ctx.rename("report.txt", "old_report.txt");
² 獲取屬性
屬性相關(guān)的接口是Attribute和Attributes,它們都在javax.naming.directory包內(nèi)。通過(guò)DirContext的getAttributes方法就可以獲得對(duì)象的屬性集合,然后使用Attributes的get方法獲得對(duì)應(yīng)的屬性,最后通過(guò)Attribute的get方法就可以獲得屬性值。
1
String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp";
2
Context user = (Context)ctx.lookup(dn);
3
//獲得所有屬性
4
Attributes attrs = user.getAttributes("");
5
Attribute test= attrs .get("test");
6
Object testValue= test.get();
上例中獲得的是user的所有屬性,在實(shí)際使用過(guò)程中,考慮網(wǎng)絡(luò)帶寬的影響,可以設(shè)置獲取要獲取的屬性列表:
1
String reqd_attrs = new String[] { "surname", "initials","title", "rfc822mailalias"};
2
Attributes attrs = user.getAttributes("", reqd_attrs);
² 查找和過(guò)濾
使用search方法完成。
1
public DirContext[] findUser(String initials,String surname,String country,String phone) {
2
//構(gòu)造條件
3
BasicAttributes search_attrs = new BasicAttributes();
4
search_attrs.put("initials", initials);
5
search_attrs.put("sn", surname);
6
search_attrs.put("c", country);
7
if(phone != null)
8
search_attrs.put("phonenumber", phone);
9
NamingEnumeration results = initial_ctx.search("ou=Customer,o=ExampleApp", search_attrs);
10
LinkedList found = new LinkedList();
11
while(results.hasMore()) {
12
SearchResults sr = (SearchResults)results.next();
13
String name = sr.getName();
14
Object ctx = sr.getObject();
15
if((ctx == null) || !(ctx instanceof DirContext))
16
found.add(initial_ctx.lookup(name));
17
else
18
found.add(ctx);
19
}
20
DirContext[] ret_val = new DirContext[found.size()];
21
found.toArray(ret_val);
22
return ret_val;
23
}
DirContext接口主要過(guò)濾方式:
1.使用過(guò)濾字符串
1
String reqd_attrs = new String[]
{ "cn", "uid","rfc822mailalias" };
2
NamingEnumeration results = initial_ctx.search("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs);
2.使用SearchControls,獲得更多的控制
1
SearchControls ctrls = new SearchControls();
2
ctrls.setCountLimit(20);
3
ctrls.setTimeLimit(5000);
4
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
5
NamingEnumeration results = initial_ctx.search("cat=books,ou=Products,
6
o=ExampleApp","title=*Java*",ctrls);
² 修改屬性
使用DirContext和InitialDirContext的modifyAttributes方法完成。所謂的修改過(guò)程,實(shí)際就是先構(gòu)造要修改的屬性列表,然后使用上述方法提交。對(duì)于屬性包含多個(gè)值時(shí),需要把屬性的不修改的值也要包含,否則服務(wù)器會(huì)認(rèn)為那些值不再需要而刪除它們。
1
public void updateAddress(String dn,String address, String country, String phone)
{
2
BasicAttributes mod_attrs = new BasicAttributes();
3
if(address != null)
4
mod_attrs.put("address", address);
5
if(country != null)
6
mod_attrs.put("c", country);
7
if(phone != null)
8
mod_attrs.put("phonenumber", phone);
9
if(mod_attrs.size() != 0)
10
initial_ctx.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, mod_attrs);
11
}
使用ModificationItem,也可一次進(jìn)行多個(gè)不同的修改操作:
ModificationItem[] mod_items = new ModificationItems[2];
Attribute email = new BasicAttribute("rfc822mailalias", new_email);
ModificationItem email_mod = new ModificationItem(DirContext.ADD_ATTRIBUTE, email);
Attribute addr = new BasicAttribute("address", address);
ModificationItem addr_mod = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, addr);
mod_items[0] = email_mod;
mod_items[1] = addr_mod;
initial_ctx.modifyAttributes(dn, mod_items);
² 創(chuàng)建上下文
使用createSubcontext方法完成。
1
BasicAttributes attrs = new BasicAttributes();
2
attrs.put("initials", initials);
3
attrs.put("sn", surname);
4
attrs.put("rfc822mailalias", email);
5
if(address != null)
6
attrs.put("address", address);
7
if(country != null)
8
attrs.put("c", country);
9
if(phone != null)
10
attrs.put("phonenumber", phone);
11
initial_ctx.createSubcontext(dn, attrs);
² 刪除上下文
使用destroySubcontext方法完成。
1
initial_ctx.destroySubcontext(dn);
資料:
jndi學(xué)習(xí)筆記 http://hankun.blogbus.com/logs/2005/12/1774694.html
[精華] JNDI http://www.chinaunix.net/jh/26/30421.html
Author: orangelizq
email: orangelizq@163.com

歡迎大家訪問(wèn)我的個(gè)人網(wǎng)站
萌萌的IT人
posted on 2007-07-16 16:18
桔子汁 閱讀(4888)
評(píng)論(1) 編輯 收藏 所屬分類:
J2EE