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);