基于JNDI的应用开发
JNDI(The Java Naming and Directory InterfaceJava命名和目录接口)是一组在Java应用中访问命名和目录服务的API命名服务将名称和对象联系起来使得我们可以用名称访问对象目录服务是一种命名服务在这种服务里对象不但有名称还有属性
命名或目录服务使你可以集中存储共有信息这一点在网络应用中是重要的因为这使得这样的应用更协调更容易管理例如可以将打印机设置存储在目录服务中以便被与打印机有关的应用使用
本文用代码示例的方式给出了一个快速教程使你可以开始使用JNDI它
l 提供了JNDI概述 l 描述了JNDI的特点 l 体验了一下用JNDI开发应用 l 表明了如何利用JNDI访问LDAP服务器例如Sun ONE 目录服务器 l 表明了如何利用JNDI访问JEE服务 l 提供了示例代码你可以将其改编为自己的应用
JNDI概述
我们大家每天都不知不觉地使用了命名服务例如当你在web浏览器输入URL时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构建在与命名系统有关的驱动之上这一层有助于将应用与实际数据源分离因此不管应用访问的是LDAPRMIDNS还是其他的目录服务换句话说JNDI独立于目录服务的具体实现只要你有目录的服务提供接口(或驱动)你就可以使用目录如图所示 图JNDI架构
关于JNDI要注意的重要一点是它提供了应用编程接口(application programming interfaceAPI)和服务提供者接口(service provider interfaceSPI)这一点的真正含义是要让你的应用与命名服务或目录服务交互必须有这个服务的JNDI服务提供者这正是JNDI SPI发挥作用的地方服务提供者基本上是一组类这些类为各种具体的命名和目录服务实现了JNDI接口?很象JDBC驱动为各种具体的数据库系统实现了JDBC接口一样作为一个应用开发者你不必操心JNDI SPI你只需要确认你要使用的每一个命名或目录服务都有服务提供者
JSE和JNDI
Java SDK 及以上的版本包含了JNDI对于JDK 和也有一个标准的扩展Java SDK x的最新版本包括了几个增强和下面的命名/目录服务提供者
l LDAP(Lightweight Directory Access Protocol)服务提供者 l CORBA COS(Common Object Request Broker Architecture Common Object Services)命名服务提供者 l RMI(Java Remote Method Invocation)注册服务提供者 l DNS(Domain Name System)服务提供者
更多的服务提供者
可以在如下网址找到可以下载的服务提供者列表
特别有意思的或许是如下网址提供的Windows 注册表JNDI服务提供者 这个服务提供者使你可以访问Windows XP//NT/Me/x的windows注册表
也可以在如下网址下载JNDI/LDAP Booster Pack 这个Booster Pack包含了对流行的LDAP控制的支持和扩展它代替了与LDAP 服务提供者捆绑在一起的booster pack关于控制和扩展的更多信息可以在如下网站看到 另一个有趣的服务提供者是Sun的支持DSML v(Directory Service Markup Language目录服务标记语言)的服务提供者DSML的目的是在目录服务和XML之间架起一座桥梁
JNDI API
JNDI API由个包组成
l Javaxnaming包含了访问命名服务的类和接口例如它定义了Context接口这是命名服务执行查询的入口 l Javaxnamingdirectory对命名包的扩充提供了访问目录服务的类和接口例如它为属性增加了新的类提供了表示目录上下文的DirContext接口定义了检查和更新目录对象的属性的方法 l Javaxnamingevent提供了对访问命名和目录服务时的时间通知的支持例如定义了NamingEvent类这个类用来表示命名/目录服务产生的事件定义了侦听NamingEvents的NamingListener接口 l Javaxnamingldap这个包提供了对LDAP 版本扩充的操作和控制的支持通用包javaxnamingdirectory没有包含这些操作和控制 l Javaxnamingspi这个包提供了一个方法通过javaxnaming和有关包动态增加对访问命名和目录服务的支持这个包是为有兴趣创建服务提供者的开发者提供的
JNDI 上下文
正如在前面提到的命名服务将名称和对象联系起来这种联系称之为绑定(binding)一组这样的绑定称之为上下文(context)上下文提供了解析(即返回对象的查找操作)其他操作包括名称的绑定和取消绑定列出绑定的名称注意到一个上下文对象的名称可以绑定到有同样的命名约定的另一个上下文对象这称之为子上下文例如如果UNIX中目录/home是一个上下文那么相对于这个目录的子目录就是子上下文?例如/home/guests中guests就是home的子上下文在JNDI中上下文用接口javaxnamingContext表示这个接口是与命名服务交互的关键接口在Context(或稍后讨论的
DirContext)接口中的每一个命名方法都有两种重载形式
l Lookup(String name)接受串名 l Lookup(javaxnamingName)接受结构名例如CompositeName(跨越了多个命名系统的名称)或CompondName(单个命名系统中的名称)它们都实现了Name接口Compound name的一个例子是cn=mydircn=Q Mahmoudou=Peoplecomposite name的一个例子是cn=mydircn=Q Mahmoudou=People/myfiles/maxtxt(这里myfiles/maxtxt是表示第二部分的文件名) JavaxnamingInitialContext是实现了Context接口的类用这个类作为命名服务的入口为了创建InitialContext对象构造器以javautilHashtable或者是其子类(例如Properties)的形式设置一组属性下面给出了一个例子
Hashtable env = new Hashtable() // select a service provider factory envput(ContextINITIAL_CONTEXT_FACTORY comsunjndifscontextRefFSContext) // create the initial context Context contxt = new InitialContext(env)
INITIAL_CONTEXT_FACTORY指定了JNDI服务提供者中工厂类(factory class)的名称Factory负责为其服务创建适当的InitialContext对象在上面的代码片断中为文件系统服务提供者指定了工厂类表给出了所支持的服务提供者的工厂类要注意的是文件系统服务提供者的工厂类需要从Sun公司单独下载JSE x没有包含这些类
表上下文INITIAL_CONTEXT_FACTORY的值 Name Service Provider Factory File System comsunjndifscontextRefFSContextFactory LDAP comsunjndildapLdapCtxFactory RMI comsunjndirmiregistryRegistryContextFactory CORBA snamingCNCtxFactory DNS comsunjndidnsDnsContextFactory
为了用名称从命名服务或目录中取得或解析对象使用Context的lookup方法Object obj=contxtlookup(name)Lookup方法返回一个对象这个对象表示的是你想要找的上下文的儿子