JNDI(The Java Naming and Directory Interface,Java命名和目录接口),是一组在Java应用中访问命名和目录服务的API。包括两部分,命名服务和目录服务,其中:
1.命名服务将名称和对象联系起来,使得我们可以用名称访问对象,命名系统中的对象可以是DNS记录中的名称、应用服务器中的EJB组件、LDAP(Lightweight Directory Access Protocol)中的用户Profile.
2.目录服务是命名服务的自然扩展。两者之间的关键差别是目录服务中对象可以有属性(例如,用户有email地址),而命名服务中对象没有属性。因此,在目录服务中,你可以根据属性搜索对象。
JNDI服务可以:访问文件系统中的文件、定位远程RMI注册的对象,访问象LDAP这样的目录服务,定位网络上的EJB组件等等。
对于象LDAP 客户端、应用launcher、类浏览器、网络管理实用程序,甚至地址薄这样的应用来说,JNDI是一个很好的选择。
JNDI架构
JNDI提供了API(编程接口)和SPI(服务实现接口),要让应用与命名服务或目录服务交互,必须有这个服务的JNDI服务提供者,这正是JNDI 将服务的使用和服务的注册解偶的思想,通常服务提供者都是一组类,这些类为各种具体的命名和目录服务实现了JNDI指定的SPI接口。
JNDI包结构大致如下:
Javax.naming:包含了访问命名服务的类和接口。例如,它定义了Context接口,这是命名服务执行查询的入口。
Javax.naming.directory:对命名包的扩充,提供了访问目录服务的类和接口,提供了DirContext接口,定义了检查和更新目录对象的属性的方法。
Javax.naming.event:提供了对访问命名和目录服务时的时间通知的支持。例如,定义了NamingEvent类,定义了侦听接口。
Javax.naming.ldap:这个包提供了对LDAP 版本3扩充的操作和控制的支持,通用包javax.naming.directory没有包含这些操作和控制。
Javax.naming.spi:这个包提供了一个方法,通过javax.naming和有关包动态增加对访问命名和目录服务的支持。这个包是为有兴趣创建服务提供者的开发者提供的。
所支持的服务提供者的工厂类如下,其中文件系统服务提供者的工厂类需要从Sun公司单独下载,J2SE 1.4.x没有包含这些类。
上下问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
在使用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文件来完成注册。
使用方式:对于名字服务由InitialContext开始,目录服务则使用InitialDirContext。它们分别实现了Context和DirContext,这两个接口分别对应名字服务和目录服务的接口,也是JNDI中最重要的两个接口。
包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务;可以同时连接到多个命名或目录服务上;建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必指导对象或资源的物理ID。
利用JNDI的命名与服务功能来满足企业级API对命名与服务的访问,诸如EJB、JMS、JDBC 以及IIOP上的RMI通过JNDI来使用CORBA的命名服务。
JNDI编程示例
JNDI与JDBC:
Context cntxt = new InitialContext(); DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
JNDI与JMS:
Properties env = new Properties();
InitialContext inictxt = new InitialContext(env);
TopicConnectionFactory connFactory = (TopicConnectionFactory) inictxt.lookup("TTopicConnectionFactory");
访问特定目录:例如,人是个对象,他有好几个属性,诸如这个人的姓名、电话号码、电子邮件地址、邮政编码等属性。通过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());
}
常用的JNDI操作
void bind(String sName,Object object);――绑定:把名称同对象关联的过程
void rebind(String sName,Object object);――重新绑定:用来把对象同一个已经存在的名称重新绑定
void unbind(String sName);――释放:用来把对象从目录中释放出来
lookup(String name);――查找:返回目录总的一个对象
void rename(String sOldName,String sNewName);――重命名:用来修改对象名称绑定的名称
NamingEnumeration listBinding(String sName);――清单:返回绑定在特定上下文中对象的清单列表
NamingEnumeration list(String sName);――清单:返回绑定在特定上下文中对象的清单列表