RMI 通过 JNDI
此示例显示 JNDI 如何在 RMI 中工作。它有两个角色:
- 向服务器提供绑定/取消绑定/重新绑定 API 到 RMI 注册表
- 向客户端提供 RMI 注册表的查找/列表 API。
RMI Registry 是 RMI 的一部分,而不是 JNDI。
为简单起见,我们将使用 java.rmi.registry.CreateRegistry()
创建 RMI 注册表。
-
Server.java(JNDI 服务器)
package com.neohope.jndi.test; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import java.io.IOException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.util.Hashtable; /** * JNDI Server * 1.create a registry on port 1234 * 2.bind JNDI * 3.wait for connection * 4.clean up and end */ public class Server { private static Registry registry; private static InitialContext ctx; public static void initJNDI() { try { registry = LocateRegistry.createRegistry(1234); final Hashtable jndiProperties = new Hashtable(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); jndiProperties.put(Context.PROVIDER_URL, "rmi://localhost:1234"); ctx = new InitialContext(jndiProperties); } catch (NamingException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } public static void bindJNDI(String name, Object obj) throws NamingException { ctx.bind(name, obj); } public static void unbindJNDI(String name) throws NamingException { ctx.unbind(name); } public static void unInitJNDI() throws NamingException { ctx.close(); } public static void main(String[] args) throws NamingException, IOException { initJNDI(); NMessage msg = new NMessage("Just A Message"); bindJNDI("/neohope/jndi/test01", msg); System.in.read(); unbindJNDI("/neohope/jndi/test01"); unInitJNDI(); } }
-
Client.java(JNDI 客户端)
package com.neohope.jndi.test; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import java.util.Hashtable; /** * 1.init context * 2.lookup registry for the service * 3.use the service * 4.end */ public class Client { public static void main(String[] args) throws NamingException { final Hashtable jndiProperties = new Hashtable(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); jndiProperties.put(Context.PROVIDER_URL, "rmi://localhost:1234"); InitialContext ctx = new InitialContext(jndiProperties); NMessage msg = (NeoMessage) ctx.lookup("/neohope/jndi/test01"); System.out.println(msg.message); ctx.close(); } }
-
NMessage.java(RMI 服务器类)
package com.neohope.jndi.test; import java.io.Serializable; import java.rmi.Remote; /** * NMessage * RMI server class * must implements Remote and Serializable */ public class NMessage implements Remote, Serializable { public String message = ""; public NMessage(String message) { this.message = message; } }
如何运行 eaxmple:
- 构建并启动服务器
- 构建并启动客户端
介绍
http://i.stack.imgur.com/pGG8z.jpg
在 Java 命名和目录接口(JNDI) 是一个目录服务,允许 Java 软件客户端发现,并通过名称来查找数据和对象的 Java API。它旨在独立于任何特定的命名或目录服务实现。
JNDI 体系结构由 API (应用程序编程接口)和 SPI (服务提供者接口)组成。Java 应用程序使用此 API 来访问各种命名和目录服务。SPI 允许透明地插入各种命名和目录服务,允许使用 JNDI 技术 API 的 Java 应用程序访问其服务。
从上面的图片可以看出,JNDI 支持 LDAP,DNS,NIS,NDS,RMI 和 CORBA。当然,你可以扩展它。
这个怎么运作
在此示例中,Java RMI 使用 JNDI API 查找网络中的对象。如果要查找对象,则至少需要两条信息:
- 在哪里找到对象
RMI 注册表管理名称绑定,它告诉你在哪里找到对象。
- 对象的名称
什么是对象的名字?它通常是一个字符串,它也可以是一个实现 Name 接口的对象。
一步步
-
首先,你需要一个管理名称绑定的注册表。在这个例子中,我们使用
java.rmi.registry.LocateRegistry
。//This will start a registry on localhost, port 1234 registry = LocateRegistry.createRegistry(1234);
-
客户端和服务器都需要 Context。服务器使用 Context 来绑定名称和对象。客户端使用 Context 查找名称并获取对象。
//We use com.sun.jndi.rmi.registry.RegistryContextFactory as the InitialContextFactory final Hashtable jndiProperties = new Hashtable(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); //the registry usrl is "rmi://localhost:1234" jndiProperties.put(Context.PROVIDER_URL, "rmi://localhost:1234"); InitialContext ctx = new InitialContext(jndiProperties);
-
服务器绑定名称和对象
//The jndi name is "/neohope/jndi/test01" bindJNDI("/neohope/jndi/test01", msg);
-
客户端通过名称“/ neohope / jndi / test01”查找对象
//look up the object by name "java:com/neohope/jndi/test01" NeoMessage msg = (NeoMessage) ctx.lookup("/neohope/jndi/test01");
-
现在客户端可以使用该对象
-
当服务器结束时,需要清理。
ctx.unbind("/neohope/jndi/test01"); ctx.close();