posts - 97,  comments - 93,  trackbacks - 0
今天浏览网页,看见篇写JNDI比较基础,也比较详细的文章,又自己整理了一下,post到新手区了,。。。。:)

JNDIjava访问名字和目录服务的接口,与JDBC一样,它仅仅只定义了一套服务接口,实现由具体厂商提供。作为j2ee核心组件之一,它为应用程序查找其他程序组件和资源提供了统一的接口,其中最常见的用途就是数据源的配置、EJB名字查找、JMS相关配置等。JNDI的架构如下图。在JDK1.3中,已经包含了JNDI,它分成五个包。每个包提供的功能:

-          javax.naming,包含访问命名服务的类和接口定义。

-          javax.naming.directory,包含访问目录服务的类和接口定义。

-          javax.naming.ldap,为ldapv3提供的扩展操作提供支持。

-          javax.naming.event,为访问命名和目录服务时的事件通知提供支持。

-          javax.naming.spi,为服务提供商提供的接口,一般用户不会涉及。

基本概念

 

       了解名字服务和目录服务的相关概念,有助于更好的使用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映射的类,用于NameClassPairReferences

-          java.naming.factory.state,用来创建jndi state的类

对于目录服务,由于一般需要安全设置,还通常使用:

-          java.naming.security.authentication,安全类型,三个值:nonesimplestrong

-          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。它们分别实现了ContextDirContext,这两个接口分别对应名字服务和目录服务的接口,也是JNDI中最重要的两个接口。

-          连接名字服务:

                    

1System.setProperty(Context.INITIAL_CONTEXT_FACTORY," 
2   com.sun.jndi.fscontext.FSContextFactory"); 
3InitialContext ctx = new InitialContext(); 
4
5

-          连接目录服务:

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"); 
9InitialDirContext ctx = new InitialDirContext(env); 


-          多服务提供者:如果应用包含多个服务提供者,在连接时略有不同。以名字服务为例:

 

1Hashtable 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  //使用不同的构造函数 
6InitialContext ctx = new InitialContext(env); 

²        查找对象

不论名字服务还是目录服务,都是使用lookup来查找对象的。除了可以使用String作为参数之外,lookup还可使用Name接口作为参数。

1Greeter greeter = (Greeter)ctx.lookup("SayHello"); 

如果想要获得上下文中所有的对象名字,就使用lis返回NameClassPair列表。NameClassPair包含对象名字和对象类名。如果想要获得实际的对象实例列表,就使用listBindings,它返回Binding列表。BindingNameClassPair的子类,它包含对象的实例。
-          list

1NamingEnumeration list = ctx.list("awt"); 
2while (list.hasMore()) 
3    NameClassPair nc = (NameClassPair)list.next(); 
4    System.out.println(nc); 
5}
 


-          listBindings

1NamingEnumeration bindings = ctx.listBindings("awt"); 
2while (bindings.hasMore()) 
3    Binding bd = (Binding)bindings.next(); 
4    System.out.println(bd.getName() + "" + bd.getObject()); 
5}
 

 

²        对象绑定

      -          使用bind添加绑定

1Fruit fruit = new Fruit("orange");
2ctx.bind("favorite", fruit); 

     -          使用rebind修改绑定

1Fruit fruit = new Fruit("lemon");
2ctx.rebind("favorite", fruit); 

-          使用unbind去除绑定。

 

1ctx.unbind("favorite"); 

²        对象改名

使用rename可以给一个在上下文中的对象改名

1ctx.rename("report.txt""old_report.txt"); 

²        获取属性

属性相关的接口是AttributeAttributes,它们都在javax.naming.directory包内。通过DirContextgetAttributes方法就可以获得对象的属性集合,然后使用Attributesget方法获得对应的属性,最后通过Attributeget方法就可以获得属性值。

1String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp"
2Context user = (Context)ctx.lookup(dn); 
3//获得所有属性 
4Attributes attrs = user.getAttributes(""); 
5Attribute test= attrs .get("test"); 
6Object testValue= test.get(); 

上例中获得的是user的所有属性,在实际使用过程中,考虑网络带宽的影响,可以设置获取要获取的属性列表:

1String reqd_attrs = new String[] "surname""initials","title""rfc822mailalias"}
2Attributes attrs = user.getAttributes("", reqd_attrs); 

 

²        查找和过滤

使用search方法完成。

 

 1   public DirContext[] findUser(String initials,String surname,String country,String phone) 
 2        //构造条件 
 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接口主要过滤方式:

1.使用过滤字符串

 

1String reqd_attrs = new String[] "cn""uid","rfc822mailalias" }
2NamingEnumeration results = initial_ctx.search("ou=Customer, o=ExampleApp",search_attrs,reqd_attrs); 

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

 

1SearchControls ctrls = new SearchControls(); 
2ctrls.setCountLimit(20); 
3ctrls.setTimeLimit(5000); 
4ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); 
5NamingEnumeration results = initial_ctx.search("cat=books,ou=Products, 
6o=ExampleApp","title=*Java*",ctrls); 

²        修改属性

使用DirContextInitialDirContextmodifyAttributes方法完成。所谓的修改过程,实际就是先构造要修改的属性列表,然后使用上述方法提交。对于属性包含多个值时,需要把属性的不修改的值也要包含,否则服务器会认为那些值不再需要而删除它们。

 1public 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,也可一次进行多个不同的修改操作:

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方法完成。

 

 1BasicAttributes attrs = new BasicAttributes(); 
 2attrs.put("initials", initials); 
 3attrs.put("sn", surname); 
 4attrs.put("rfc822mailalias", email); 
 5if(address != null
 6    attrs.put("address", address); 
 7if(country != null
 8    attrs.put("c", country); 
 9if(phone != null
10    attrs.put("phonenumber", phone); 
11initial_ctx.createSubcontext(dn, attrs); 

²        删除上下文

使用destroySubcontext方法完成。

1initial_ctx.destroySubcontext(dn); 

 


 


posted on 2007-05-14 23:33 wqwqwqwqwq 阅读(812) 评论(0)  编辑  收藏 所属分类: Simple Java

只有注册用户登录后才能发表评论。


网站导航:
 
<2007年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789




常用链接

留言簿(10)

随笔分类(95)

随笔档案(97)

文章档案(10)

相册

J2ME技术网站

java技术相关

mess

搜索

  •  

最新评论

阅读排行榜

校园梦网网络电话,中国最优秀的网络电话