首页 > 代码库 > 远程方法调用——RMI
远程方法调用——RMI
RMI
RMI (Remote Method Invocation)是Java用于实现透明远程调用的重要机制。在远程调用中,客户端仅有服务器端提供的接口 。通过此接口实现对远程服务器端的调用。其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
Sun JDK 6 .0 以前版本中的R M I 实现均是基于TCP/IP+BIO 方式的,RMI 服务器端通过启动RMI 注册对象在一个端口上监听对外提供的接口,其实现实例以字符串的方式绑定到RMI 注册对象上。RMI客户端通过Proxy的方式代理了对服务器端接口的访问,RMI 客户端将要访问的服务器端对象字符串、方法和参数封装成一个对象,序列化成流后通过TCP/IP + BIO 传输到 RMI 服务器端。RMI 服务器端接收到客户端的请求对象后,解析其中的对象字符串、方法及参数,通过对象字符串从 RMI 注册对象上找到提供业务功能的实例,之后结合要访问的方法来反射获取到方法实例对象,传入参数完成对服务器端对象实例的调用,返回的结果则序列化为流以 TCP/IP + BIO 方式返回给客户端,客户端在接收到此流后反序列化为对象,并返冋给调用者。
简单例子
远程调用接口:
/** * 远程接口<br/> * 定义一个远程接口,必须继承Remote接口 * * @author Joeson * @since 07/2014 */ public interface HelloRMI extends Remote { // 其中需要远程调用的方法必须抛出RemoteException异常 public String hello() throws RemoteException; }
远程调用接口实现:
/** * * 远程调用实现类<br/> * 需要继承UnicastRemoteObject类,同时因为UnicastRemoteObject的构造方法抛出了RemoteException异常, * 因此这里默认的构造方法必须写,必须声明抛出RemoteException异常。 * * @author Joeson * @since 07/2014 * */ public class HelloRMIImpl extends UnicastRemoteObject implements HelloRMI { public HelloRMIImpl() throws RemoteException { super(); // TODO Auto-generated constructor stub } @Override public String hello() throws RemoteException { return "Hello, RMI"; } }
RMI服务器端:
/** * RMI服务器端<br/> * * * @author Joeson * @since 07/2014 * */ public class ServerRMI { public static void main(String[] args) { try { // 创建一个远程对象 HelloRMI hello = new HelloRMIImpl(); // 本地主机上的远程对象注册表Registry的实例,并指定端口为8080,这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 LocateRegistry.createRegistry(8080); // 把远程对象注册到RMI注册服务器上,并命名为Hello, 绑定的URL标准格式为:rmi://host:port/name Naming.bind("rmi://localhost:8080/Hello", hello); System.out.println("RMI服务启动..."); } catch (RemoteException e) { System.out.println("创建远程对象发生异常!"); } catch (AlreadyBoundException e) { System.out.println("发生重复绑定对象异常!"); e.printStackTrace(); } catch (MalformedURLException e) { System.out.println("发生URL畸形异常!"); e.printStackTrace(); } } }
RMI客户端实现:
/** * RMI客户端<br/> * * @author Joeson * @since 07/2014 * */ public class ClientRMI { public static void main(String args[]) { try { // 在RMI服务注册表中查找名称为Hello的对象,并调用其上的方法 HelloRMI hello = (HelloRMI) Naming .lookup("rmi://localhost:8080/Hello"); System.out.println(hello.hello()); } catch (NotBoundException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
运行结果
以上就是一个客户端通过RMI方式调用服务器端的是实现,实现分布式系统调用,而RMI的底层的真正实现就在于反射机制、序列化、反序列化和Socket编程,客户端并不需要提供具体的实现,而是通过接口的方式与服务器端的具体实现进行交互,调用服务器端具体的实现,实现客户端想要的效果,这就是分布式系统的业务处理模型了