Java中的定名與目次接口JNDI根本操作辦法概覽。本站提示廣大學習愛好者:(Java中的定名與目次接口JNDI根本操作辦法概覽)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中的定名與目次接口JNDI根本操作辦法概覽正文
對jndi整體的懂得:
jndi(java naming and directory Interface)它供給了一套應用定名和目次辦事的接口。用戶可以經由過程它來應用定名和目次辦事。就像jdbc一樣。jndi包含定名辦事和目次辦事兩部門,個中目次辦事包括目次對象directory object,它包括若干屬性對象。供給了對屬性的許多操作。
定名和目次辦事:
定名和目次辦事我們一向在應用,如操作體系的文件體系,它給我們供給對文件的操作,查詢,添加刪除等功效。DNS辦事將url同ip地址綁定在了一路。定名和目次體系的最重要的功效是將name和對象綁定。在它的基本之上還供給更多的功效如lookup,search.並且存儲的對象是有必定條理構造的。應用如許的辦事我們可以對對象加倍有用的治理和操作。
定名辦事將一個稱號映照到一個對象。RMI Registry和CORBA Naming Service都是定名辦事。
目次辦事也寄存對象,但目次辦事辨認這些對象的相干屬性。可以用項目屬性來搜刮目次。
在20世紀90年月晚期,輕量級的目次拜訪協定(LightWeightDiretoryAccessProtocol,LDAP)被作為一種尺度的目次協定被開辟出來,JNDI可以或許拜訪LDAP。
j2se為jndi供給了5個擴大包:
context: context是一套name-to-object的綁定(bindings),可以懂得為條理或目次,它還可已包含下一層subContext。在應用定名和目次辦事時取得initial context是對全部名字空間操作的進口。在目次辦事中是DirContext.
JNDI(Java Naming and Directory Interface)是一個運用法式設計的API,為開辟人員供給了查找和拜訪各類定名和目次辦事的通用、同一的接口,相似JDBC都是構建在籠統層上。
JNDI可拜訪的現有的目次及辦事有:
DNS、XNam 、Novell目次辦事、LDAP(Lightweight Directory Access Protocol 輕型目次拜訪協定)、 CORBA對象辦事、文件體系、Windows XP/2000/NT/Me/9x的注冊表、RMI、DSML v1&v2、NIS。
JNDI長處:
包括了年夜量的定名和目次辦事,應用通用接口來拜訪分歧品種的辦事;可以同時銜接到多個定名或目次辦事上;樹立起邏輯聯系關系,許可把稱號同Java對象或資本聯系關系起來,而不用指點對象或資本的物理ID。
JNDI法式包:
JNDI與JDBC:
JNDI供給了一種同一的方法,可以用在收集上查找和拜訪辦事。經由過程指定一個資本稱號,該稱號對應於數據庫或定名辦事中的一個記載,同時前往數據庫銜接樹立所必需的信息。
代碼示例:
try{ Context cntxt = new InitialContext(); DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt"); } catch(NamingException ne){ ... }
JNDI與JMS:
新聞通訊是軟件組件或運用法式用來通訊的一種辦法。JMS就是一種許可運用法式創立、發送、吸收、和讀撤消息的JAVA技巧。
代碼示例:
try{ Properties env = new Properties(); InitialContext inictxt = new InitialContext(env); TopicConnectionFactory connFactory = (TopicConnectionFactory) inictxt.lookup("TTopicConnectionFactory"); ... } catch(NamingException ne){ ... }
拜訪特定目次:舉個例子,人是個對象,他有好幾個屬性,諸如這小我的姓名、德律風號碼、電子郵件地址、郵政編碼等屬性。經由過程getAttributes()辦法
Attribute attr = directory.getAttributes(personName).get("email"); String email = (String)attr.get();
經由過程應用JNDI讓客戶應用對象的稱號或屬性來查找對象:
foxes = directory.search("o=Wiz,c=US", "sn=Fox", controls);
經由過程應用JNDI來查找諸如打印機、數據庫如許的對象,查找打印機的例子:
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()); }
代碼示例:從新獲得了稱號、類名和綁定對象。
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(); }
懂得名字辦事和目次辦事的相干概念,有助於更好的應用JNDI。 Naming service 名字辦事界說了若何將名字與對象聯系關系,並經由過程名字若何找到對象的辦法。典范的例子如:DNS將域名與IP聯系關系,文件體系將文件名與文件相干聯。在名字辦事中,重要的概念:
- 名字(Names),在名字體系中現實對象的代號,如文件名,域名等,它會被用來查找聯系關系的對象。分歧的體系中會有分歧的定名標准,如文件體系采取“\”來表現層級,而DNS則應用“.”。
- 綁定(Bindings),名字和現實對象的聯系關系。
- 援用和地址(References and Addresses),當對象不克不及直接被存儲在名字體系時,就必需應用援用,經由過程援用找到現實的對象。在體系中,保留的援用的內容被稱為地址。援用還有另外一個用途:在名字體系中,缺乏象關系數據庫中外鍵的概念。經由過程應用援用,可以作為外鍵的一個代替方法。
- 高低文(Context),它是一個名字-對象聚集,供給了與名字體系交互的重要操作,如查找、綁定、去綁定。子高低文(subcontext)與它的關系相似文件體系中目次和子目次的關系,子高低文被包括在一個高低文中,經由過程父高低文中的一個名字與子高低文聯系關系。
- 名字體系和名字空間(Naming Systems and Namespaces),名字體系是雷同類型的高低文的聚集,它供給名字辦事;名字空間,是名字體系中的名字聚集,如文件體系的文件名和目次。
Directory service 目次辦事是名字辦事的擴大,它除聯系關系名字和對象,還許可對象包括屬性。目次體系平日以條理構造組織數據。在目次辦事中的重要概念:
- 屬性(Attributes),它屬於目次對象,它是(名字,值)對,屬性可以有多個值。
- 目次和目次辦事(Directories and Directory Services),目次是目次對象的聚集;目次辦事則供給與目次相干的辦事,創立、刪除和修正寄存在目次中的對象的屬性。
- 查找和查找過濾器(Searches and Search Filters),獲得目次對象的操作就是查找;過濾器是相似查找前提的對象。
根本應用
² 注冊JNDI供給者
在應用JNDI之前,須要先獲得JNDI的供給者,並在體系注冊它。與JNDI相干的體系屬性在javax.naming.Context中界說,經常使用的屬性:
- java.naming.factory.initial,辦事供給者用來創立InitialContext的類名。
- java.naming.provider.url,用來設置裝備擺設InitialContext的初始url
- java.naming.factory.object,用來創立name-to-object映照的類,用於NameClassPair和References。
- java.naming.factory.state,用來創立jndi state的類
關於目次辦事,因為普通須要平安設置,還平日應用:
- java.naming.security.authentication,平安類型,三個值:none,simple或strong。
- java.naming.security.principal,認證信息。
- java.naming.security.credentials,證手札息。
- java.naming.security.protocol,平安協定名。
應用System.setProperty注冊,假如法式不顯示解釋,那末java會在classpath外調找jdni.properties文件來完成注冊。jdni.properties例子:
java.naming.factory.initial=com.codeline.db.MockInitialContextFactory
銜接辦事
注冊以後,便可以實行辦事銜接了。關於名字辦事由InitialContext開端,目次辦事則應用InitialDirContext。它們分離完成了Context和DirContext,這兩個接口分離對應名字辦事和目次辦事的接口,也是JNDI中最主要的兩個接口。
銜接名字辦事:
System.setProperty(Context.INITIAL_CONTEXT_FACTORY," com.sun.jndi.fscontext.FSContextFactory"); InitialContext ctx = new InitialContext();
銜接目次辦事:
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://myserver.com/"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); //登錄ldap server須要的用戶名 env.put(Context.SECURITY_PRINCIPAL, "ldapuser"); //登錄ldap server須要的暗碼 env.put(Context.SECURITY_CREDENTIALS, "mypassword"); InitialDirContext ctx = new InitialDirContext(env);
多辦事供給者:假如運用包括多個辦事供給者,在銜接時略有分歧。以名字辦事為例
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); env.put(Context.PROVIDER_URL, "rmi://myserver.com:1099"); //應用分歧的結構函數 InitialContext ctx = new InitialContext(env);
查找對象
豈論名字辦事照樣目次辦事,都是應用lookup來查找對象的。除可使用String作為參數以外,lookup還可以使用Name接口作為參數。
Greeter greeter = (Greeter)ctx.lookup("SayHello");
假如想要取得高低文中一切的對象名字,就應用lis前往NameClassPair列表。NameClassPair包括對象名字和對象類名。假如想要取得現實的對象實例列表,就應用listBindings,它前往Binding列表。Binding是NameClassPair的子類,它包括對象的實例。
- list
NamingEnumeration list = ctx.list("awt"); while (list.hasMore()) { NameClassPair nc = (NameClassPair)list.next(); System.out.println(nc); }
- listBindings
NamingEnumeration bindings = ctx.listBindings("awt"); while (bindings.hasMore()) { Binding bd = (Binding)bindings.next(); System.out.println(bd.getName() + ": " + bd.getObject()); }
對象綁定
- 應用bind添加綁定
Fruit fruit = new Fruit("orange"); ctx.bind("favorite", fruit);
- 應用rebind修正綁定
Fruit fruit = new Fruit("lemon"); ctx.rebind("favorite", fruit);
- 應用unbind去除綁定。
ctx.unbind("favorite");
對象更名
應用rename可以給一個在高低文中的對象更名
ctx.rename("report.txt", "old_report.txt");
- 獲得屬性
屬性相干的接口是Attribute和Attributes,它們都在javax.naming.directory包內。經由過程DirContext的getAttributes辦法便可以取得對象的屬性聚集,然後應用Attributes的get辦法取得對應的屬性,最初經由過程Attribute的get辦法便可以取得屬性值。
String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp"; Context user = (Context)ctx.lookup(dn); //取得一切屬性 Attributes attrs = user.getAttributes(""); Attribute test= attrs .get("test"); Object testValue= test.get();
上例中取得的是user的一切屬性,在現實應用進程中,斟酌收集帶寬的影響,可以設置獲得要獲得的屬性列表:
String reqd_attrs = new String[] { "surname", "initials","title", "rfc822mailalias"}; Attributes attrs = user.getAttributes("", reqd_attrs);
查找和過濾
應用search辦法完成。
public DirContext[] findUser(String initials,String surname,String country,String phone) { //結構前提 BasicAttributes search_attrs = new BasicAttributes(); search_attrs.put("initials", initials); search_attrs.put("sn", surname); search_attrs.put("c", country); if(phone != null) search_attrs.put("phonenumber", phone); NamingEnumeration results = initial_ctx.search("ou=Customer,o=ExampleApp", search_attrs); LinkedList found = new LinkedList(); while(results.hasMore()) { SearchResults sr = (SearchResults)results.next(); String name = sr.getName(); Object ctx = sr.getObject(); if((ctx == null) || !(ctx instanceof DirContext)) found.add(initial_ctx.lookup(name)); else found.add(ctx); } DirContext[] ret_val = new DirContext[found.size()]; found.toArray(ret_val); return ret_val; }
DirContext接口重要過濾方法:
1.應用過濾字符串
String reqd_attrs = new String[] { "cn", "uid","rfc822mailalias" }; NamingEnumeration results = initial_ctx.search("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs);
2.應用SearchControls,取得更多的掌握
SearchControls ctrls = new SearchControls(); ctrls.setCountLimit(20); ctrls.setTimeLimit(5000); ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration results = initial_ctx.search("cat=books,ou=Products, o=ExampleApp","title=*Java*",ctrls);
修正屬性
應用DirContext和InitialDirContext的modifyAttributes辦法完成。所謂的修正進程,現實就是先結構要修正的屬性列表,然後應用上述辦法提交。關於屬性包括多個值時,須要把屬性的不修正的值也要包括,不然辦事器會以為那些值不再須要而刪除它們。
public void updateAddress(String dn,String address, String country, String phone) { BasicAttributes mod_attrs = new BasicAttributes(); if(address != null) mod_attrs.put("address", address); if(country != null) mod_attrs.put("c", country); if(phone != null) mod_attrs.put("phonenumber", phone); if(mod_attrs.size() != 0) initial_ctx.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, mod_attrs); }
應用ModificationItem,也可一次停止多個分歧的修正操作:
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);
創立高低文
應用createSubcontext辦法完成。
BasicAttributes attrs = new BasicAttributes(); attrs.put("initials", initials); attrs.put("sn", surname); attrs.put("rfc822mailalias", email); if(address != null) attrs.put("address", address); if(country != null) attrs.put("c", country); if(phone != null) attrs.put("phonenumber", phone); initial_ctx.createSubcontext(dn, attrs);
刪除高低文
應用destroySubcontext辦法完成。
initial_ctx.destroySubcontext(dn);
實例
以下再舉一個實例。
在tomcat的conf/server.xml中設置裝備擺設:
<Context path="/jndi"> <Resource name="bean/MyBeanFactory" auth="Container" type="com.huawei.jndi.bean.MyBean" factory="org.apache.naming.factory.BeanFactory" bar="23"/> </Context>
下面就在tomcat中聲清楚明了一個組件,接上去在代碼中可以獲得這個組件:
try { Context initContext = new InitialContext(); Context envCtx = (Context) initContext.lookup("java:comp/env"); MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory"); System.out.println(bean.getBar()); } catch (Exception e) { e.printStackTrace(); }
總結:在tomcat中設置裝備擺設jndi組件,然後在代碼中獲得已配好的組件。
各WEB容器的JNDI完成類是分歧的,好比在JBOSS中,JNDI供給類是org.jnp.interfaces.NamingContextFactory,與tomcat是分歧的。
如許看來,JNDI的感化和spring的依附注入卻是差不多。然則經由過程JNDI,可以完成跨運用,乃至跨域獲得組件。在辦事器A上設置裝備擺設的組件,在另外一台辦事器B上,可以經由過程JNDI獲得到。
spring也供給了對jndi的封裝,應用起來加倍便利,以下是一個例子。
<!-- JNDI模板 --> <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> <property name="environment"> <props> <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop> <prop key="java.naming.provider.url">10.137.96.212:18199</prop> <prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop> </props> </property> </bean> <!-- 創立銜接工場 --> <bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate" ref="jndiTemplate" /> <property name="jndiName" value="TopicConnectionFactory" /> </bean>
先聲明JndiTemplate,設置裝備擺設好目的地址、JNDI辦事供給類。然後經由過程JndiObjectFactoryBean,便可以很便利地獲得JNDI組件,並停止類型轉換。