JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API。命名服务将名称和对象联系起来,使得我们可以用名称访问对象。目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性。
命名或目录服务使你可以集中存储共有信息,这一点在网络应用中是重要的,因为这使得这样的应用更协调、更容易管理。例如,可以将打印机设置存储在目录服务中,以便被与打印机有关的应用使用。
JNDI概述
我们大家每天都不知不觉地使用了命名服务。例如,当你在web浏览器输入URL,http://java.sun.com时, DNS(Domain Name System,域名系统)将这个符号URL名转换成通讯标识(IP地址)。命名系统中的对象可以是DNS记录中的名称、 应用服务器中的EJB组件(Enterprise JavaBeans Component)、LDAP (Lightweight Directory Access Protocol)中的用户Profile。
目录服务是命名服务的自然 扩展。两者之间的关键差别是目录服务中对象可以有属性(例如,用户有email地址),而命名服务中对象没有属性。因此,在目录服务中,你可以根据属性搜 索对象。JNDI允许你访问文件系统中的文件,定位远程RMI注册的对象,访问象LDAP这样的目录服务,定位网络上的EJB组件。
对于象LDAP 客户端、应用launcher、类浏览器、网络管理实用程序,甚至地址薄这样的应用来说,JNDI是一个很好的选择。
JNDI架构
JNDI 架构提供了一组标准的独立于命名系统的API,这些API构建在与命名系统有关的驱动之上。这一层有助于将应用与实际数据源分离,因此不管应用访问的是 LDAP、RMI、DNS、还是其他的目录服务。换句话说,JNDI独立于目录服务的具体实现,只要你有目录的服务提供接口(或驱动),你就可以使用目录。
J2SE和JNDI
Java 2 SDK 1.3及以上的版本包含了JNDI。对于JDK 1.1和1.2也有一个标准的扩展。Java 2 SDK 1.4.x的最新版本包括了几个增强和下面的命名/目录服务提供者:
LDAP (Lightweight Directory Access Protocol)服务提供者CORBA COS (Common Object Request Broker Architecture Common Object Services)命名服务提供者RMI(Java Remote Method Invocation)注册服务提供者 l DNS(Domain Name System)服务提供者。
JNDI API
JNDI API由5个包组成:
Javax.naming: 包含了访问命名服务的类和接口。例如,它定义了Context接口,这是命名服务执行查询的入口。 Javax.naming.directory: 对命名包的扩充,提供了访问目录服务的类和接口。例如,它为属性增加了新的类,提供了表示目录上下文的DirContext接口,定义了检查和更新目录对 象的属性的方法。Javax.naming.event:提供了对访问命名和目录服务时的时间通知的支持。例如,定义了NamingEvent类, 这个类用来表示命名/目录服务产生的事件,定义了侦听NamingEvents的NamingListener接口。 Javax.naming.ldap:这个包提供了对LDAP 版本3扩充的操作和控制的支持,通用包 javax.naming.directory没有包含这些操作和控制。Javax.naming.spi:这个包提供了一个方法,通过 javax.naming和有关包动态增加对访问命名和目录服务的支持。这个包是为有兴趣创建服务提供者的开发者提供的。
JNDI 上下文
正如在前面提到的,命名服务将名称和对象联系起来。这种联系称之为绑定(binding)。一组这样的绑定称之为上下文(context),上下文提供了解 析(即返回对象的查找操作)。其他操作包括:名称的绑定和取消绑定,列出绑定的名称。注意到一个上下文对象的名称可以绑定到有同样的命名约定的另一个上下 文对象。这称之为子上下文。例如,如果UNIX中目录/home是一个上下文,那么相对于这个目录的子目录就是子上下文?例如,/home/guests 中guests就是home的子上下文。在JNDI中,上下文用接口javax.naming.Context表示,这个接口是与命名服务交互的关键接 口。在Context(或稍后讨论的DirContext)接口中的每一个命名方法都有两种重载形式:
Lookup (String name):接受串名 l Lookup(javax.naming.Name):接受结构名,例如,CompositeName(跨越 了多个命名系统的名称)或CompondName(单个命名系统中的名称);它们都实现了Name接口。Compound name的一个例子是:cn= mydir,cn=Q Mahmoud,ou=People,composite name的一个例子是:cn=mydir,cn=Q Mahmoud, ou=People/myfiles/max.txt(这里,myfiles/max.txt是表示第二部分的文件名) Javax.naming.InitialContext是实现了Context接口的类。用这个类作为命名服务的入口。为了创建 InitialContext对象,构造器以java.util.Hashtable或者是其子类(例如,Properties)的形式设置一组属性。下面给出了一个例子:
Hashtable env = new Hashtable();
factory env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContext");
Context contxt = new InitialContext(env);
INITIAL_CONTEXT_FACTORY 指定了JNDI服务提供者中工厂类(factory class)的名称。Factory负责为其服务创建适当的InitialContext对象。在上 面的代码片断中,为文件系统服务提供者指定了工厂类。
为了用名称从命名服务或目录中取得或解析对象,使用Context的lookup方法:Object obj=contxt.lookup(name)。Lookup方法返回一个对象,这个对象表示的是你想要找的上下文的儿子。