初识JNDI
JNDI是J2EE的核心技术之一,JNDI的功能简单说就是可以简单的方式去查找某种资源。比如在Tomcat中配置了一个JNDI数据源,那么在程序中之需要用Java标准的API就可以查找到这个数据源,以后数据源配置发生变化了,等等,程序都不需要改动,之需要改改JNDI的配置就行。增加了程序的灵活性,也给系统解耦了。
JNDI的非常重要,我们时不时都在用它,可是很多程序员对它都很陌生,包括本人在内,下面从最根本的概念入手,认识下JNDI,也为以后深入研究JNDI做个铺垫。
JNDI的概念不是一两句话能说清楚的,网上对JNDI的概念解释很多,基本上都是对官方文档的翻译的copy。在此也不废话了,摘抄SUN官方的一些权威解释出来,
下面来自java.sun.com:
Java命名和目录接口(Java Naming and Directory Interface ,JNDI)是用于从Java应用程序中访问名称和目录服务的一组API。命名服务即将名称与对象相关联,以便能通过相应名称访问这些对象。而目录服务即其对象具有属性及名称的命名服务。
命名或目录服务允许您集中管理共享信息的存储,这在网络应用程序中很重要,因为它可以使这类应用程序更加一致和易于管理。例如,可以将打印机配置存储在目录服务中,这样所有与打印机相关的应用程序都能够使用它。
命名或目录服务允许您集中管理共享信息的存储,这在网络应用程序中很重要,因为它可以使这类应用程序更加一致和易于管理。例如,可以将打印机配置存储在目录服务中,这样所有与打印机相关的应用程序都能够使用它。
JNDI综述
我们所有人每天都在不自知的情况下使用命名服务。例如,当您在浏览器中输入URL http://java.sun.com 时,域名系统(Domain Name System ,DNS)将这个以符号表示的URL转换为一个通信标识符(IP地址)。在命名系统中,对象的范围可以从位于DNS记录中的名称变动到应用程序服务器中的企业JavaBeans组件(Enterprise JavaBeans Components ,EJBs),还可以到轻量级目录访问协议(Lightweight Directory Access Protocol ,LDAP)中的用户配置文件。
目录服务是命名服务的自然扩展。二者的关键区别在于,目录服务允许属性(比如用户的电子邮件地址)与对象相关联,而命名服务则不然。这样,使用目录服务时,您可以基于对象的属性来搜索它们。JNDI允许您访问文件系统中的文件,定位远程RMI注册表中的对象,访问诸如LDAP这样的目录服务,并定位网络上的EJB。
很多应用程序选择使用JNDI都可以收到良好的效果,比如LDAP客户端、应用程序启动器、类浏览器、网络管理实用工具,或者甚至是地址簿。
目录服务是命名服务的自然扩展。二者的关键区别在于,目录服务允许属性(比如用户的电子邮件地址)与对象相关联,而命名服务则不然。这样,使用目录服务时,您可以基于对象的属性来搜索它们。JNDI允许您访问文件系统中的文件,定位远程RMI注册表中的对象,访问诸如LDAP这样的目录服务,并定位网络上的EJB。
很多应用程序选择使用JNDI都可以收到良好的效果,比如LDAP客户端、应用程序启动器、类浏览器、网络管理实用工具,或者甚至是地址簿。
JNDI架构
JNDI架构提供了一个标准的、与命名系统无关的API,这个API构建在特定于命名系统的驱动程序之上。这一层帮助把应用程序和实际的数据源隔离开来,因此无论应用程序是访问LDAP、RMI、DNS还是其他的目录服务,这都没有关系。换句话说,JNDI与任何特定的目录服务实现无关,您可以使用任何目录,只要您拥有相应的服务提供程序接口(或驱动程序)即可,如图下图所示。
注意,关于JNDI有一点很重要,即它同时提供应用程序编程接口(Application Programming Interface ,API)和服务提供程序接口(Service Provider Interface ,SPI)。这样做的实际意义在于,对于您的与命名或目录服务交互的应用程序来说,必须存在用于该服务的一个JNDI服务提供程序,这便是JNDI SPI发挥作用的舞台。一个服务提供程序基本上就是一组类,这些类针对特定的命名和目录服务实现了各种JNDI接口——这与JDBC驱动程序针对特定的数据系统实现各种JDBC接口极为相似。作为一名应用程序开发人员,您不需要担心JNDI SPI.。您只需确保,您为每个想使用的命名或目录服务提供了一个服务提供程序。
J2SE和JNDI
JNDI被包含在Java 2 SDK 1.3 及其更新版本中。它还可以用作JDK 1.1和1.2的一个标准扩展。 Java 2 SDK 1.4.x的最新版本进行了改进,将以下命名/目录服务提供程序包括进来:
轻量级目录访问协议(Lightweight Directory Access Protocol,LDAP) 服务提供程序。
公共对象请求代理架构(Common Object Request Broker Architecture ,CORBA)公共对象服务(Common Object Services ,COS)命名服务提供程序。
Java远程方法调用( Remote Method Invocation ,RMI)注册表服务提供程序。
域名系统( Domain Name System ,DNS) 服务提供程序。
轻量级目录访问协议(Lightweight Directory Access Protocol,LDAP) 服务提供程序。
公共对象请求代理架构(Common Object Request Broker Architecture ,CORBA)公共对象服务(Common Object Services ,COS)命名服务提供程序。
Java远程方法调用( Remote Method Invocation ,RMI)注册表服务提供程序。
域名系统( Domain Name System ,DNS) 服务提供程序。
以上对JNDI概念内涵和外延最权威的解释,遗憾的是,J2EE的文档做得太差了,这点应该像微软学习学习。
JNDI的范例程序也很少,在网上广泛流传的是一些与应用服务器结合的实例,如在Tomcat、JBoss、WebLogic中配置了JNDI的数据源,然后在程序中去发现使用。这些例子大家都会,没意思。
能否在没有应用服务器的程序中使用JNDI技术呢?经过验证,答案是:可以!
下面给个例子:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
public class TestFileSystemJNDI {
public static void main(String[] args) throws NamingException {
Hashtable env = new Hashtable();
String name = "F:\\fscontext-1_2-beta3.zip";
//文件系统服务的提供者
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
Context ctx = new InitialContext(env);
//通过上下文查找名称对应的对象
Object obj = ctx.lookup(name);
System.out.println( "名称:[" + name + "]绑定的对象是:" + obj);
}
}
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
public class TestFileSystemJNDI {
public static void main(String[] args) throws NamingException {
Hashtable env = new Hashtable();
String name = "F:\\fscontext-1_2-beta3.zip";
//文件系统服务的提供者
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
Context ctx = new InitialContext(env);
//通过上下文查找名称对应的对象
Object obj = ctx.lookup(name);
System.out.println( "名称:[" + name + "]绑定的对象是:" + obj);
}
}
运行结果:
名称:[F:\fscontext-1_2-beta3.zip]绑定的对象是:F:\fscontext-1_2-beta3.zip
Process finished with exit code 0
Process finished with exit code 0
抓个图看看:
注意,JNDI的概念说的明白,你需要有这个服务,才可以用JNDI API来获取。
因此还需要安装文件系统服务。这个例子我不用安装什么服务,下载个文件服务包就行了。其中的两个jar文件就包中的。
JNDI技术的实现很复杂,如果要深入研究,需要花费很大的精力,这个例子也许没什么价值,但对认识JNDI的概念,以及更好的去使用JNDI是很有帮助的。如果要讲解JNDI技术,足足够写一本厚厚的书。
J2EE就是这样,把接口留给程序员,把细节实现留给提供商。
我做过的项目实例:
MpsConstants.IUMURL 得到的值 : iwr.srs.ium.url = t3://10.12.60.200:7001
MpsConstants.IUMSESSION : IUMSESSION = "CPFBIntranet-IUM-IUMSession#com.cpf.ejb.ium.session.IUMSession";
我做过的项目实例:
private static Context getInitialContext() throws NamingException,
IOException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x connection details
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,
MpsUtility.getProp(MpsConstants.CONFIGFILE,
MpsConstants.IUMURL));
return new InitialContext(env);
}
//get iumSession
public static IUMSession getSession() throws NamingException, IOException {
String integratedFlag =
MpsUtility.getProp(MpsConstants.CONFIGFILE, MpsConstants.INTERGRATED_WITH_WEBCENTER);
if ("true".endsWith(integratedFlag)) {
return IUMSessionFactory.getSession();
} else {
//TODO: only for local testing.
final Context context = getInitialContext();
return (IUMSession)context.lookup(MpsConstants.IUMSESSION);
}
}
MpsConstants.IUMURL 得到的值 : iwr.srs.ium.url = t3://10.12.60.200:7001
MpsConstants.IUMSESSION : IUMSESSION = "CPFBIntranet-IUM-IUMSession#com.cpf.ejb.ium.session.IUMSession";