首页 > 代码库 > 远程方法调用——RMI

远程方法调用——RMI

RMI

RMI  (Remote  Method  Invocation)是Java用于实现透明远程调用的重要机制。在远程调用中,客户端仅有服务器端提供的接口 。通过此接口实现对远程服务器端的调用。威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPCJava版本。但是传统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编程,客户端并不需要提供具体的实现,而是通过接口的方式与服务器端的具体实现进行交互,调用服务器端具体的实现,实现客户端想要的效果,这就是分布式系统的业务处理模型了