2023年6月21日发(作者:)

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个扩展包:;为访问命名服务提供的ory;为访问⽬录服务提供了基本的接⼝;⽀持命名和⽬录服务中的事件通知; ⽀持ldap的包,;提供了不同命名和⽬录服务可以挂接他们的实现的⽅法。context: context是⼀套name-to-object的绑定(bindings),可以理解为层次或⽬录,它还可已包括下⼀层subContext。在使⽤命名和⽬录服务时获得initial context是对整个名字空间操作的⼊⼝。在⽬录服务中是(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程序包::命名操作;ory:⽬录操作;:在命名⽬录服务器中请求事件通知;:提供LDAP⽀持;:允许动态插⼊不同实现。利⽤JNDI的命名与服务功能来满⾜企业级APIs对命名与服务的访问,诸如EJBs、JMS、JDBC 2.0以及IIOP上的RMI通过JNDI来使⽤CORBA的命名服务。JNDI与JDBC:JNDI提供了⼀种统⼀的⽅式,可以⽤在⽹络上查找和访问服务。通过指定⼀个资源名称,该名称对应于数据库或命名服务中的⼀个纪录,同时返回数据库连接建⽴所必须的信息。代码⽰例:try{Context cntxt = new InitialContext();DataSource ds = (DataSource) ("jdbc/dpt");}catch(NamingException ne){...}JNDI与JMS:消息通信是软件组件或应⽤程序⽤来通信的⼀种⽅法。JMS就是⼀种允许应⽤程序创建、发送、接收、和读取消息的JAVA技术。代码⽰例:try{Properties env = new Properties();InitialContext inictxt = new InitialContext(env);TopicConnectionFactory connFactory = (TopicConnectionFactory) ("TTopicConnectionFactory");...}catch(NamingException ne){...}访问特定⽬录:举个例⼦,⼈是个对象,他有好⼏个属性,诸如这个⼈的姓名、电话号码、电⼦邮件地址、邮政编码等属性。通过getAttributes()⽅法Attribute attr = ributes(personName).get("email");String email = (String)();通过使⽤JNDI让客户使⽤对象的名称或属性来查找对象:foxes = ("o=Wiz,c=US", "sn=Fox", controls);通过使⽤JNDI来查找诸如打印机、数据库这样的对象,查找打印机的例⼦:Printer printer = (Printer)(printerName);(document);浏览命名空间:NamingEnumeration list = ("o=Widget, c=US");while (e()) {NameClassPair entry = (NameClassPair)();display(e(), ssName());}常⽤的JNDI操作:void bind(String sName,Object object);――绑定:把名称同对象关联的过程void rebind(String sName,Object object);――重新绑定:⽤来把对象同⼀个已经存在的名称重新绑定void unbind(String sName);――释放:⽤来把对象从⽬录中释放出来void lookup(String sName,Object object);――查找:返回⽬录总的⼀个对象void rename(String sOldName,String sNewName);――重命名:⽤来修改对象名称绑定的名称NamingEnumeration listBinding(String sName);――清单:返回绑定在特定上下⽂中对象的清单列表NamingEnumeration list(String sName);代码⽰例:重新得到了名称、类名和绑定对象。NamingEnumeration namEnumList = nding("cntxtName");...while ( e() ) {Binding bnd = (Binding) ();String sObjName = e();String sClassName = ssName();SomeObject objLocal = (SomeObject) ect();}了解名字服务和⽬录服务的相关概念,有助于更好的使⽤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相关的系统属性在t中定义,常⽤的属性:- l,服务提供者⽤来创建InitialContext的类名。- ,⽤来配置InitialContext的初始url- ,⽤来创建name-to-object映射的类,⽤于NameClassPair和References。- ,⽤来创建jndi state的类对于⽬录服务,由于⼀般需要安全设置,还通常使⽤:- tication,安全类型,三个值:none,simple或strong。- pal,认证信息。- tials,证书信息。- ol,安全协议名。使⽤perty注册,如果程序不显⽰说明,那么java会在classpath内查找ties⽂件来完成注册。ties例⼦:l=itialContextFactory

连接服务注册之后,就可以实施服务连接了。对于名字服务由InitialContext开始,⽬录服务则使⽤InitialDirContext。它们分别实现了Context和DirContext,这两个接⼝分别对应名字服务和⽬录服务的接⼝,也是JNDI中最重要的两个接⼝。连接名字服务:

perty(L_CONTEXT_FACTORY,"

extFactory");

InitialContext ctx = new InitialContext();连接⽬录服务: Hashtable env = new Hashtable();

(L_CONTEXT_FACTORY, "xFactory");

(ER_URL, "ldap:///"); (TY_AUTHENTICATION, "simple");

//登录ldap server需要的⽤户名

(TY_PRINCIPAL, "ldapuser");

//登录ldap server需要的密码

(TY_CREDENTIALS, "mypassword");

InitialDirContext ctx = new InitialDirContext(env);

多服务提供者:如果应⽤包含多个服务提供者,在连接时略有不同。以名字服务为例Hashtable env = new Hashtable();

(L_CONTEXT_FACTORY,

"ryContextFactory");

(ER_URL, "rmi://:1099");

//使⽤不同的构造函数

InitialContext ctx = new InitialContext(env);

查找对象不论名字服务还是⽬录服务,都是使⽤lookup来查找对象的。除了可以使⽤String作为参数之外,lookup还可使⽤Name接⼝作为参数。Greeter greeter = (Greeter)("SayHello");

如果想要获得上下⽂中所有的对象名字,就使⽤lis返回NameClassPair列表。NameClassPair包含对象名字和对象类名。如果想要获得实际的对象实例列表,就使⽤listBindings,它返回Binding列表。Binding是NameClassPair的⼦类,它包含对象的实例。

- listNamingEnumeration list = ("awt");

while (e()) {

NameClassPair nc = (NameClassPair)();

n(nc);

}- listBindingsNamingEnumeration bindings = ndings("awt");

while (e()) {

Binding bd = (Binding)();

n(e() + ": " + ect());

}

对象绑定- 使⽤bind添加绑定Fruit fruit = new Fruit("orange");("favorite", fruit);- 使⽤rebind修改绑定Fruit fruit = new Fruit("lemon");("favorite", fruit);- 使⽤unbind去除绑定。("favorite");

对象改名使⽤rename可以给⼀个在上下⽂中的对象改名("", "old_");- 获取属性属性相关的接⼝是Attribute和Attributes,它们都在ory包内。通过DirContext的getAttributes⽅法就可以获得对象的属性集合,然后使⽤Attributes的get⽅法获得对应的属性,最后通过Attribute的get⽅法就可以获得属性值。String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp";

Context user = (Context)(dn);

//获得所有属性

Attributes attrs = ributes("");

Attribute test= attrs .get("test");

Object testValue= ();

上例中获得的是user的所有属性,在实际使⽤过程中,考虑⽹络带宽的影响,可以设置获取要获取的属性列表:String reqd_attrs = new String[] { "surname", "initials","title", "rfc822mailalias"};

Attributes attrs = ributes("", reqd_attrs);

查找和过滤使⽤search⽅法完成。 public DirContext[] findUser(String initials,String surname,String country,String phone) {

//构造条件

BasicAttributes search_attrs = new BasicAttributes();

search_("initials", initials);

search_("sn", surname);

search_("c", country);

if(phone != null)

search_("phonenumber", phone);

NamingEnumeration results = initial_("ou=Customer,o=ExampleApp", search_attrs);

LinkedList found = new LinkedList();

while(e()) {

SearchResults sr = (SearchResults)();

String name = e();

Object ctx = ect();

if((ctx == null) || !(ctx instanceof DirContext))

(initial_(name));

else

(ctx);

}

DirContext[] ret_val = new DirContext[()];

y(ret_val);

return ret_val;

} DirContext接⼝主要过滤⽅式:

1.使⽤过滤字符串

String reqd_attrs = new String[] { "cn", "uid","rfc822mailalias" };

NamingEnumeration results = initial_("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs);

2.使⽤SearchControls,获得更多的控制

SearchControls ctrls = new SearchControls();

ntLimit(20);

eLimit(5000);

rchScope(E_SCOPE);

NamingEnumeration results = initial_("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_("address", address);

if(country != null)

mod_("c", country);

if(phone != null)

mod_("phonenumber", phone);

if(mod_() != 0)

initial_Attributes(dn, E_ATTRIBUTE, mod_attrs);

}

使⽤ModificationItem,也可⼀次进⾏多个不同的修改操作:

ModificationItem[] mod_items = new ModificationItems[2];

Attribute email = new BasicAttribute("rfc822mailalias", new_email);

ModificationItem email_mod = new ModificationItem(_ATTRIBUTE, email);

Attribute addr = new BasicAttribute("address", address);

ModificationItem addr_mod = new ModificationItem(E_ATTRIBUTE, addr);

mod_items[0] = email_mod;

mod_items[1] = addr_mod;

initial_Attributes(dn, mod_items);创建上下⽂使⽤createSubcontext⽅法完成。 BasicAttributes attrs = new BasicAttributes();

("initials", initials);

("sn", surname);

("rfc822mailalias", email);

if(address != null)

("address", address);

if(country != null)

("c", country);

if(phone != null)

("phonenumber", phone);

initial_Subcontext(dn, attrs);

删除上下⽂使⽤destroySubcontext⽅法完成。initial_ySubcontext(dn);

实例以下再举⼀个实例。在tomcat的conf/中配置:

type=""

factory="ctory"

bar="23"/>

上⾯就在tomcat中声明了⼀个组件,接下来在代码中可以获取这个组件:try

{

Context initContext = new InitialContext();

Context envCtx = (Context) ("java:comp/env");

MyBean bean = (MyBean) ("bean/MyBeanFactory");

n(());

}

catch (Exception e)

{

tackTrace();

}

总结:在tomcat中配置jndi组件,然后在代码中获取已配好的组件。各WEB容器的JNDI实现类是不同的,⽐如在JBOSS中,JNDI提供类是ContextFactory,与tomcat是不同的。这样看来,JNDI的作⽤和spring的依赖注⼊倒是差不多。但是通过JNDI,可以实现跨应⽤,甚⾄跨域获取组件。在服务器A上配置的组件,在另⼀台服务器B上,可以通过JNDI获取到。spring也提供了对jndi的封装,使⽤起来更加⽅便,以下是⼀个例⼦。

ContextFactory

10.137.96.212:18199

aces:

先声明JndiTemplate,配置好⽬标地址、JNDI服务提供类。然后通过JndiObjectFactoryBean,就可以很⽅便地获取JNDI组件,并进⾏类型转换。

2023年6月21日发(作者:)

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个扩展包:;为访问命名服务提供的ory;为访问⽬录服务提供了基本的接⼝;⽀持命名和⽬录服务中的事件通知; ⽀持ldap的包,;提供了不同命名和⽬录服务可以挂接他们的实现的⽅法。context: context是⼀套name-to-object的绑定(bindings),可以理解为层次或⽬录,它还可已包括下⼀层subContext。在使⽤命名和⽬录服务时获得initial context是对整个名字空间操作的⼊⼝。在⽬录服务中是(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程序包::命名操作;ory:⽬录操作;:在命名⽬录服务器中请求事件通知;:提供LDAP⽀持;:允许动态插⼊不同实现。利⽤JNDI的命名与服务功能来满⾜企业级APIs对命名与服务的访问,诸如EJBs、JMS、JDBC 2.0以及IIOP上的RMI通过JNDI来使⽤CORBA的命名服务。JNDI与JDBC:JNDI提供了⼀种统⼀的⽅式,可以⽤在⽹络上查找和访问服务。通过指定⼀个资源名称,该名称对应于数据库或命名服务中的⼀个纪录,同时返回数据库连接建⽴所必须的信息。代码⽰例:try{Context cntxt = new InitialContext();DataSource ds = (DataSource) ("jdbc/dpt");}catch(NamingException ne){...}JNDI与JMS:消息通信是软件组件或应⽤程序⽤来通信的⼀种⽅法。JMS就是⼀种允许应⽤程序创建、发送、接收、和读取消息的JAVA技术。代码⽰例:try{Properties env = new Properties();InitialContext inictxt = new InitialContext(env);TopicConnectionFactory connFactory = (TopicConnectionFactory) ("TTopicConnectionFactory");...}catch(NamingException ne){...}访问特定⽬录:举个例⼦,⼈是个对象,他有好⼏个属性,诸如这个⼈的姓名、电话号码、电⼦邮件地址、邮政编码等属性。通过getAttributes()⽅法Attribute attr = ributes(personName).get("email");String email = (String)();通过使⽤JNDI让客户使⽤对象的名称或属性来查找对象:foxes = ("o=Wiz,c=US", "sn=Fox", controls);通过使⽤JNDI来查找诸如打印机、数据库这样的对象,查找打印机的例⼦:Printer printer = (Printer)(printerName);(document);浏览命名空间:NamingEnumeration list = ("o=Widget, c=US");while (e()) {NameClassPair entry = (NameClassPair)();display(e(), ssName());}常⽤的JNDI操作:void bind(String sName,Object object);――绑定:把名称同对象关联的过程void rebind(String sName,Object object);――重新绑定:⽤来把对象同⼀个已经存在的名称重新绑定void unbind(String sName);――释放:⽤来把对象从⽬录中释放出来void lookup(String sName,Object object);――查找:返回⽬录总的⼀个对象void rename(String sOldName,String sNewName);――重命名:⽤来修改对象名称绑定的名称NamingEnumeration listBinding(String sName);――清单:返回绑定在特定上下⽂中对象的清单列表NamingEnumeration list(String sName);代码⽰例:重新得到了名称、类名和绑定对象。NamingEnumeration namEnumList = nding("cntxtName");...while ( e() ) {Binding bnd = (Binding) ();String sObjName = e();String sClassName = ssName();SomeObject objLocal = (SomeObject) ect();}了解名字服务和⽬录服务的相关概念,有助于更好的使⽤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相关的系统属性在t中定义,常⽤的属性:- l,服务提供者⽤来创建InitialContext的类名。- ,⽤来配置InitialContext的初始url- ,⽤来创建name-to-object映射的类,⽤于NameClassPair和References。- ,⽤来创建jndi state的类对于⽬录服务,由于⼀般需要安全设置,还通常使⽤:- tication,安全类型,三个值:none,simple或strong。- pal,认证信息。- tials,证书信息。- ol,安全协议名。使⽤perty注册,如果程序不显⽰说明,那么java会在classpath内查找ties⽂件来完成注册。ties例⼦:l=itialContextFactory

连接服务注册之后,就可以实施服务连接了。对于名字服务由InitialContext开始,⽬录服务则使⽤InitialDirContext。它们分别实现了Context和DirContext,这两个接⼝分别对应名字服务和⽬录服务的接⼝,也是JNDI中最重要的两个接⼝。连接名字服务:

perty(L_CONTEXT_FACTORY,"

extFactory");

InitialContext ctx = new InitialContext();连接⽬录服务: Hashtable env = new Hashtable();

(L_CONTEXT_FACTORY, "xFactory");

(ER_URL, "ldap:///"); (TY_AUTHENTICATION, "simple");

//登录ldap server需要的⽤户名

(TY_PRINCIPAL, "ldapuser");

//登录ldap server需要的密码

(TY_CREDENTIALS, "mypassword");

InitialDirContext ctx = new InitialDirContext(env);

多服务提供者:如果应⽤包含多个服务提供者,在连接时略有不同。以名字服务为例Hashtable env = new Hashtable();

(L_CONTEXT_FACTORY,

"ryContextFactory");

(ER_URL, "rmi://:1099");

//使⽤不同的构造函数

InitialContext ctx = new InitialContext(env);

查找对象不论名字服务还是⽬录服务,都是使⽤lookup来查找对象的。除了可以使⽤String作为参数之外,lookup还可使⽤Name接⼝作为参数。Greeter greeter = (Greeter)("SayHello");

如果想要获得上下⽂中所有的对象名字,就使⽤lis返回NameClassPair列表。NameClassPair包含对象名字和对象类名。如果想要获得实际的对象实例列表,就使⽤listBindings,它返回Binding列表。Binding是NameClassPair的⼦类,它包含对象的实例。

- listNamingEnumeration list = ("awt");

while (e()) {

NameClassPair nc = (NameClassPair)();

n(nc);

}- listBindingsNamingEnumeration bindings = ndings("awt");

while (e()) {

Binding bd = (Binding)();

n(e() + ": " + ect());

}

对象绑定- 使⽤bind添加绑定Fruit fruit = new Fruit("orange");("favorite", fruit);- 使⽤rebind修改绑定Fruit fruit = new Fruit("lemon");("favorite", fruit);- 使⽤unbind去除绑定。("favorite");

对象改名使⽤rename可以给⼀个在上下⽂中的对象改名("", "old_");- 获取属性属性相关的接⼝是Attribute和Attributes,它们都在ory包内。通过DirContext的getAttributes⽅法就可以获得对象的属性集合,然后使⽤Attributes的get⽅法获得对应的属性,最后通过Attribute的get⽅法就可以获得属性值。String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp";

Context user = (Context)(dn);

//获得所有属性

Attributes attrs = ributes("");

Attribute test= attrs .get("test");

Object testValue= ();

上例中获得的是user的所有属性,在实际使⽤过程中,考虑⽹络带宽的影响,可以设置获取要获取的属性列表:String reqd_attrs = new String[] { "surname", "initials","title", "rfc822mailalias"};

Attributes attrs = ributes("", reqd_attrs);

查找和过滤使⽤search⽅法完成。 public DirContext[] findUser(String initials,String surname,String country,String phone) {

//构造条件

BasicAttributes search_attrs = new BasicAttributes();

search_("initials", initials);

search_("sn", surname);

search_("c", country);

if(phone != null)

search_("phonenumber", phone);

NamingEnumeration results = initial_("ou=Customer,o=ExampleApp", search_attrs);

LinkedList found = new LinkedList();

while(e()) {

SearchResults sr = (SearchResults)();

String name = e();

Object ctx = ect();

if((ctx == null) || !(ctx instanceof DirContext))

(initial_(name));

else

(ctx);

}

DirContext[] ret_val = new DirContext[()];

y(ret_val);

return ret_val;

} DirContext接⼝主要过滤⽅式:

1.使⽤过滤字符串

String reqd_attrs = new String[] { "cn", "uid","rfc822mailalias" };

NamingEnumeration results = initial_("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs);

2.使⽤SearchControls,获得更多的控制

SearchControls ctrls = new SearchControls();

ntLimit(20);

eLimit(5000);

rchScope(E_SCOPE);

NamingEnumeration results = initial_("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_("address", address);

if(country != null)

mod_("c", country);

if(phone != null)

mod_("phonenumber", phone);

if(mod_() != 0)

initial_Attributes(dn, E_ATTRIBUTE, mod_attrs);

}

使⽤ModificationItem,也可⼀次进⾏多个不同的修改操作:

ModificationItem[] mod_items = new ModificationItems[2];

Attribute email = new BasicAttribute("rfc822mailalias", new_email);

ModificationItem email_mod = new ModificationItem(_ATTRIBUTE, email);

Attribute addr = new BasicAttribute("address", address);

ModificationItem addr_mod = new ModificationItem(E_ATTRIBUTE, addr);

mod_items[0] = email_mod;

mod_items[1] = addr_mod;

initial_Attributes(dn, mod_items);创建上下⽂使⽤createSubcontext⽅法完成。 BasicAttributes attrs = new BasicAttributes();

("initials", initials);

("sn", surname);

("rfc822mailalias", email);

if(address != null)

("address", address);

if(country != null)

("c", country);

if(phone != null)

("phonenumber", phone);

initial_Subcontext(dn, attrs);

删除上下⽂使⽤destroySubcontext⽅法完成。initial_ySubcontext(dn);

实例以下再举⼀个实例。在tomcat的conf/中配置:

type=""

factory="ctory"

bar="23"/>

上⾯就在tomcat中声明了⼀个组件,接下来在代码中可以获取这个组件:try

{

Context initContext = new InitialContext();

Context envCtx = (Context) ("java:comp/env");

MyBean bean = (MyBean) ("bean/MyBeanFactory");

n(());

}

catch (Exception e)

{

tackTrace();

}

总结:在tomcat中配置jndi组件,然后在代码中获取已配好的组件。各WEB容器的JNDI实现类是不同的,⽐如在JBOSS中,JNDI提供类是ContextFactory,与tomcat是不同的。这样看来,JNDI的作⽤和spring的依赖注⼊倒是差不多。但是通过JNDI,可以实现跨应⽤,甚⾄跨域获取组件。在服务器A上配置的组件,在另⼀台服务器B上,可以通过JNDI获取到。spring也提供了对jndi的封装,使⽤起来更加⽅便,以下是⼀个例⼦。

ContextFactory

10.137.96.212:18199

aces:

先声明JndiTemplate,配置好⽬标地址、JNDI服务提供类。然后通过JndiObjectFactoryBean,就可以很⽅便地获取JNDI组件,并进⾏类型转换。