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