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(); } } }
未完待续