RMI,是Remote Method Invocation(遠程方法調用)的縮寫,即在一個JVM中java程序調用在另外一個遠程JVM中運行的java程序,這個遠程JVM既能夠在同一臺實體機上,也能夠在不一樣的實體機上,二者之間經過網絡進行通訊。java RMI封裝了遠程調用的實現細節,進行簡單的配置以後,就能夠如同調用本地方法同樣,比較透明地調用遠端方法。java
RMI包括如下三個部分:網絡
一個interface,這個interface中沒有聲明任何方法。只有定義在「remote interface",即繼承了Remote
的接口中的方法,才能夠被遠程調用。線程
RemoteException是全部在遠程調用中所拋出異常的超類,全部可以被遠程調用的方法聲明,都須要拋出此異常code
提供向註冊中心保存遠程對象引用或者從註冊中心獲取遠程對象引用的方法。這個類中的方法都是靜態方法,每個方法都包含了一個類型爲String的name參數, 這個參數是URL格式,形如://host:port/name
orm
一個interface, 其功能和Naming
相似,每一個方法都有一個String類型的name參數,可是這個name不是URL格式,是遠程對象的一個命名。Registry的實例能夠經過方法LocateRegistry.getRegistry()
得到server
用於獲取到註冊中心的一個鏈接,這個鏈接能夠用於獲取一個遠程對象的引用。也能夠建立一個註冊中心。對象
從新覆寫了Object
對象中的equals,hashCode,toString方法,從而能夠用於遠程調用繼承
用於RMI Server中導出一個遠程對象並得到一個stub。這個stub封裝了底層細節,用於和遠程對象進行通訊。接口
一個interface, 聲明瞭方法:void unreferenced()
若是一個遠程隊形實現了此接口,則這個遠程對象在沒有任何客戶端引用的時候,這個方法會被調用。開發
在這一節,咱們將從頭開始寫一個簡單的RMI示例,實現輸入名字,返回「Hello, XXX"的工程。建立一個完整的遠程調用,咱們分爲如下幾步:
Remote
,而且接口中的每個方法都須要拋出RemoteException
異常package com.luckyqiao.rmi; import java.rmi.Remote; import java.rmi.RemoteException; public interface RemoteHello extends Remote { String sayHello(String name) throws RemoteException; }
package com.luckyqiao.rmi; import java.rmi.RemoteException; public class RemoteHelloImpl implements RemoteHello { public String sayHello(String name) throws RemoteException { return String.format("Hello, %s!", name); } }
package com.luckyqiao.rmi; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.util.concurrent.CountDownLatch; public class RegistryServer { public static void main(String[] args) throws InterruptedException{ try { LocateRegistry.createRegistry(8000); //Registry使用8000端口 } catch (RemoteException e) { e.printStackTrace(); } CountDownLatch latch=new CountDownLatch(1); latch.await(); //掛起主線程,不然應用會退出 } }
package com.luckyqiao.rmi; import java.io.IOException; import java.rmi.AlreadyBoundException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; public class RMIServer { public static void main(String[] args) { RemoteHello remoteHello = new RemoteHelloImpl(); try { RemoteHello stub = (RemoteHello) UnicastRemoteObject.exportObject(remoteHello, 4000); //導出服務,使用4000端口 Registry registry = LocateRegistry.getRegistry("127.0.0.1", 8000); //獲取Registry registry.bind("hello", stub); //使用名字hello,將服務註冊到Registry } catch (AlreadyBoundException | IOException e) { e.printStackTrace(); } } }
package com.luckyqiao.study.rmi; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; public class RMIClient { public static void main(String[] args) { try { Registry registry = LocateRegistry.getRegistry("127.0.0.1", 8000); //獲取註冊中心引用 RemoteHello remoteHello = (RemoteHello) registry.lookup("hello"); //獲取RemoteHello服務 System.out.println(remoteHello.sayHello("World")); //調用遠程方法 } catch (RemoteException | NotBoundException e) { e.printStackTrace(); } } }
未完待續