JNDI(Java Naming and Directory Interface,Java命名和目錄接口)是SUN公司提供的一種標(biāo)準(zhǔn)的Java命名系統(tǒng)接口,JNDI提供統(tǒng)一的客戶端API,通過不同的訪問提供者接口JNDI服務(wù)供應(yīng)接口(SPI)的實(shí)現(xiàn),由管理者將JNDI API映射為特定的命名服務(wù)和目錄系統(tǒng),使得Java應(yīng)用程序可以和這些命名服務(wù)和目錄服務(wù)之間進(jìn)行交互。目錄服務(wù)是命名服務(wù)的一種自然擴(kuò)展。兩者之間的關(guān)鍵差別是目錄服務(wù)中對(duì)象不但可以有名稱還可以有屬性(例如,用戶有email地址),而命名服務(wù)中對(duì)象沒有屬性。
集群JNDI實(shí)現(xiàn)了高可靠性JNDI,通過服務(wù)器的集群,保證了JNDI的負(fù)載平衡和錯(cuò)誤恢復(fù)。在全局共享的方式下,集群中的一個(gè)應(yīng)用服務(wù)器保證本地JNDI樹的獨(dú)立性,并擁有全局的JNDI樹。每個(gè)應(yīng)用服務(wù)器在把部署的服務(wù)對(duì)象綁定到自己本地的JNDI樹的同時(shí),還綁定到一個(gè)共享的全局JNDI樹,實(shí)現(xiàn)全局JNDI和自身JNDI的聯(lián)系。
JNDI(Java Naming and Directory Interface)是一個(gè)應(yīng)用程序設(shè)計(jì)的API,為開發(fā)人員提供了查找和訪問各種命名和目錄服務(wù)的通用、統(tǒng)一的接口,類似Java數(shù)據(jù)庫(kù)連接都是構(gòu)建在抽象層上。現(xiàn)在JNDI已經(jīng)成為J2EE的標(biāo)準(zhǔn)之一,所有的J2EE容器都必須提供一個(gè)JNDI的服務(wù)。
JNDI可訪問的現(xiàn)有的目錄及服務(wù)有:
DNS、XNam、Novell目錄服務(wù)、LDAP(Lightweight Directory Access Protocol輕型目錄訪問協(xié)議)、CORBA對(duì)象服務(wù)、文件系統(tǒng)、Windows XP/2000/NT/Me/9x的注冊(cè)表、RMI、DSML v1&v2、NIS。
優(yōu)點(diǎn)
包含了大量的命名和目錄服務(wù),使用通用接口來訪問不同種類的服務(wù);
可以同時(shí)連接到多個(gè)命名或目錄服務(wù)上;
建立起邏輯關(guān)聯(lián),允許把名稱同Java對(duì)象或資源關(guān)聯(lián)起來,而不必知道對(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ù)功能來滿足企業(yè)級(jí)API對(duì)命名與服務(wù)的訪問,諸如EJB、JMS、JDBC2.0以及IIOP上的RMI通過JNDI來使用CORBA的命名服務(wù)。
架構(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)用訪問的是LDAP、RMI、DNS、還是其他的目錄服務(wù)。換句話說,JNDI獨(dú)立于目錄服務(wù)的具體實(shí)現(xiàn),只要有目錄的服務(wù)提供接口(或驅(qū)動(dòng)),就可以使用目錄。
關(guān)于JNDI要注意的重要一點(diǎn)是,它提供了應(yīng)用編程接口(applicationprogramminginterface,API)和服務(wù)提供者接口(serviceproviderinterface,SPI)。這一點(diǎn)的真正含義是,要讓應(yīng)用與命名服務(wù)或目錄服務(wù)交互,必須有這個(gè)服務(wù)的JNDI服務(wù)提供者,這正是JNDISPI發(fā)揮作用的地方。服務(wù)提供者基本上是一組類,這些類為各種具體的命名和目錄服務(wù)實(shí)現(xiàn)了JNDI接口—很像Java數(shù)據(jù)庫(kù)連接驅(qū)動(dòng)為各種具體的數(shù)據(jù)庫(kù)系統(tǒng)實(shí)現(xiàn)了JDBC接口一樣。作為一個(gè)應(yīng)用開發(fā)者,不必操心JNDISPI的具體實(shí)現(xiàn)。只需要確認(rèn)要使用的每一個(gè)命名或目錄服務(wù)都有服務(wù)提供者。
組件
1、Javax.naming:包含了訪問命名服務(wù)的類和接口。例如,它定義了Context接口,這是命名服務(wù)執(zhí)行查詢的入口。
2、Javax.naming.directory:對(duì)命名包的擴(kuò)充,提供了訪問目錄服務(wù)的類和接口。例如,它為屬性增加了新的類,提供了表示目錄上下文的DirContext接口,定義了檢查和更新目錄對(duì)象的屬性的方法。
3、Javax.naming.event:提供了對(duì)訪問命名和目錄服務(wù)時(shí)的事件通知的支持。例如,定義了NamingEvent類,這個(gè)類用來表示命名/目錄服務(wù)產(chǎn)生的事件,定義了偵聽NamingEvents的NamingListener接口。
4、Javax.naming.ldap:這個(gè)包提供了對(duì)LDAP版本3擴(kuò)充的操作和控制的支持,通用包javax.naming.directory沒有包含這些操作和控制。
5、Javax.naming.spi:這個(gè)包提供了一個(gè)方法,通過javax.naming和有關(guān)包動(dòng)態(tài)增加對(duì)訪問命名和目錄服務(wù)的支持。這個(gè)包是為有興趣創(chuàng)建服務(wù)提供者的開發(fā)者提供的。
用途
命名或目錄服務(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)用使用。
大家每天都不知不覺地使用了命名服務(wù)。命名系統(tǒng)中的對(duì)象可以是DNS記錄中的名稱、應(yīng)用服務(wù)器中的EJB組件(EnterpriseJavaBeansComponent)、LDAP(LightweightDirectoryAccessProtocol)中的用戶Profile。
目錄服務(wù)是命名服務(wù)的自然擴(kuò)展。兩者之間的關(guān)鍵差別是目錄服務(wù)中對(duì)象可以有屬性(例如,用戶有email地址),而命名服務(wù)中對(duì)象沒有屬性。因此,在目錄服務(wù)中,你可以根據(jù)屬性搜索對(duì)象。JNDI允許你訪問文件系統(tǒng)中的文件,定位遠(yuǎn)程RMI注冊(cè)的對(duì)象,訪問像LDAP這樣的目錄服務(wù),定位網(wǎng)絡(luò)上的EJB組件。
對(duì)于象LDAP客戶端、應(yīng)用launcher、類瀏覽器、網(wǎng)絡(luò)管理實(shí)用程序,甚至地址薄這樣的應(yīng)用來說,JNDI是一個(gè)很好的選擇。
組成部分
JNDI提供了一種統(tǒng)一的方式,可以用在網(wǎng)絡(luò)上查找和訪問服務(wù)。通過指定一個(gè)資源名稱,該名稱對(duì)應(yīng)于數(shù)據(jù)庫(kù)或命名服務(wù)中的一個(gè)記錄,同時(shí)返回?cái)?shù)據(jù)庫(kù)連接建立所必須的信息。
JNDI主要有兩部分組成:應(yīng)用程序編程接口和服務(wù)供應(yīng)商接口。應(yīng)用程序編程接口提供了Java應(yīng)用程序訪問各種命名和目錄服務(wù)的功能,服務(wù)供應(yīng)商接口提供了任意一種服務(wù)的供應(yīng)商使用的功能。
代碼示例:try{Contextcntxt=newInitialContext();DataSourceds=(DataSource)cntxt.lookup("Java數(shù)據(jù)庫(kù)連接/dpt");catch(NamingExceptionne)
技術(shù)應(yīng)用
消息通信是軟件組件或應(yīng)用程序用來通信的一種方法。JMS就是一種允許應(yīng)用程序創(chuàng)建、發(fā)送、接收、和讀取消息的JAVA技術(shù)。
代碼示例:
try
Propertiesenv=newProperties();
InitialContextinictxt=newInitialContext(env);
TopicConnectionFactoryconnFactory=(TopicConnectionFactory)inictxt.lookup("TTopicConnectionFactory");
catch(NamingExceptionne)
訪問特定目錄:舉個(gè)例子,人是個(gè)對(duì)象,他有好幾個(gè)屬性,諸如這個(gè)人的姓名、電話號(hào)碼、電子郵件地址、郵政編碼等屬性。通過getAttributes()方法
Attributeattr=directory.getAttributes(personName).get("email");
Stringemail=(String)attr.get();
通過使用JNDI讓客戶使用對(duì)象的名稱或?qū)傩詠聿檎覍?duì)象:
foxes=directory.search("o=Wiz,c=US","sn=Fox",controls);
通過使用JNDI來查找諸如打印機(jī)、數(shù)據(jù)庫(kù)這樣的對(duì)象,查找打印機(jī)的例子:
Printerprinter=(Printer)namespace.lookup(printerName);
printer.print(document);
瀏覽命名空間:
NamingEnumerationlist=namespace.list("o=Widget,c=US");
while(list.hasMore())
NameClassPairentry=(NameClassPair)list.next();
display(entry.getName(),entry.getClassName());
常用操作
voidbind(StringsName,Objectobject);――綁定:把名稱同對(duì)象關(guān)聯(lián)的過程
voidrebind(StringsName,Objectobject);――重新綁定:用來把對(duì)象同一個(gè)已經(jīng)存在的名稱重新綁定
voidunbind(StringsName);――釋放:用來把對(duì)象從目錄中釋放出來
Objectlookup(StringsName);――查找:返回目錄中的一個(gè)對(duì)象
voidrename(StringsOldName,StringsNewName);――重命名:用來修改對(duì)象名稱綁定的名稱
NamingEnumerationlistBinding(StringsName);――清單:返回綁定在特定上下文中對(duì)象的清單列表
NamingEnumerationlist(StringsName);
代碼示例:重新得到了名稱、類名和綁定對(duì)象。
NamingEnumerationnamEnumList=ctxt.listBinding("cntxtName");
while(namEnumList.hasMore()
Bindingbnd=(Binding)namEnumList.next();
StringsObjName=bnd.getName();
StringsClassName=bnd.getClassName();
SomeObjectobjLocal=(SomeObject)bnd.getObject();
參考資料 >
JNDI 筆記.JNDI 筆記.2021-12-28
JNDI - LittleMoon - 博客園.JNDI - LittleMoon - 博客園.2021-12-28
Log4Shell和JNDI注入的基本常識(shí)和目前進(jìn)展.Log4Shell和JNDI注入的基本常識(shí)和目前進(jìn)展.2021-12-28