JNDI与JDBC很相似,它在三层提供了一些API给我们使用,但需要有具体的SPI,即实现者,一般J2EE服务器都有实现,但我们直接使用的话虽然很方便但是必须编写J2EE程序才能使用,这不适合于普通的Java应用程序,例如下面的代码
InitialContext ctx = new InitialContext();
return ctx.lookup("java:.......");
在服务器环境下的J2EE程序中没有问题,但在普通的应用程序中就会抛出NoInitialContextException,原因很简单因为你没有JNDI的SPI。在应用程序中可以有两种方式来使用JNDI,当然在这其中都需要具体SPI的jar包。
第一种是在创建InitialContext的时候还要传一个Hashtable或者Properties,如下以用weblogic的SPI为例
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,"t3://localhost:7001");
InitialContext ctx = new InitialContext(env);
如果是在jboss下用代码来调用,则factory要用jboss的了。
另一种方式是对System对象setProperty一些JNDI参数,实际上我们用服务器提供的JNDI也是这样,在服务器环境下,服务器启动时就把这些参数放到System.properties中了,于是直接new InitialContext()就搞定了,不要搞env那么麻烦。
在单机环境下,可没有JNDI服务在运行,那就必须手动启动一个JNDI服务。在JDK 5的rt.jar中一共有4种SUN自带的JNDI实现:
LDAP,CORBA,RMI,DNS。
这4种JNDI要正常运行还需要底层的相应服务。一般我们没有LDAP或CORBA服务器,也就无法启动这两种JNDI服务,DNS用于查域名的,以后再研究,唯一可以在main()中启动的就是基于RMI的JNDI服务。
现在我们就在main()中启动基于RMI的JNDI服务并且绑一个Date对象到JNDI上:
LocateRegistry.createRegistry(1099);
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
System.setProperty(Context.PROVIDER_URL, "rmi://localhost:1099");
InitialContext ctx = new InitialContext();
class RemoteDate extends Date implements Remote {};
ctx.bind("java:comp/env/systemStartTime", new RemoteDate());
ctx.close();
注意,我们直接把JNDI的相关参数放入了System.properties中,这样,后面的代码如果要查JNDI,直接new InitialContext()就可以了。
另外我们还可以用File System做为naming service。以下为例子:
String name = "C:/aaa.txt";
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");
Context ctx = new InitialContext(env);
Object obj = ctx.lookup(name);