Java RMI (Remote Method Invocation 远程方法调用)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。(从网上copy的,呵呵)
它与WEBSERVICE有什么区别。
rmi的客户端和服务端都必须是java,webservice没有这个限制
webservice是在http协议上传递xml文本文件,与语言和平台无关
rmi是在tcp协议上传递可序列化的java对象,只能用在java虚拟机上,绑定语言
RMI是EJB远程调用的基础,仅用RMI技术就可以实现远程调用,使用EJB是为了实现组件,事物,资源池,集群等功能。
WebService是通过XML来传输数据,可用http等协议因此可在异构系统间传递,并且可以穿过防火墙,可在公网上远程调用。
一张图解释远程方法调用的过程。RMI将客户辅助对象称为stub,服务辅助对象成为skeleton。
下面是一个RMI的入门实例。
目录结构:
1. 被调用的远程对象必须实现java.rmi.Remote接口,该接口是一个空接口,只是用来标志实现它的对象可以被远程访问。开发中一般根据业务需要自己创建接口来继承该接口,并封装可以被远程调用的方法。
package edu.rob.rmi.remote; import java.rmi.Remote; import java.rmi.RemoteException; public interface MyRemote extends Remote { public String getHello() throws RemoteException; }
远程调用依赖网络与IO,因此接口中的方法必须抛出RemoteException,否则会报错误 - java.rmi.server.ExportException: remote object implements illegal remote interface
2. 然后创建该接口的实现类,一般继承自UnicastRemoteObject:
package edu.rob.rmi.remote; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote { private static final long serialVersionUID = 1579125597612791522L; public MyRemoteImpl() throws RemoteException {} @Override public String getHello() { System.out.println("Sever: hello"); return "hello"; } }
3. 在server端的rmi registry中注册该服务。在client访问远程方法之前,必须完成server端的绑定。
package edu.rob.rmi.server; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import edu.rob.rmi.remote.MyRemoteImpl; import edu.rob.rmi.remote.MyRemote; public class HelloRMIServer { public static void main(String[] args) { try { MyRemote h = new MyRemoteImpl(); LocateRegistry.createRegistry(1099); Naming.rebind("rmi://192.168.1.101:1099/hello", h); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
4. 编写client访问远程方法。需要注意的是,client同样需要一份远程方法的接口。直接将server端的接口拷贝至客户端就可以(注意包名、类名必须相同)。
package edu.rob.rmi.client; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import edu.rob.rmi.remote.MyRemote; public class HelloRMIClient { public static void main(String[] args) { try { MyRemote h = (MyRemote) Naming.lookup("rmi://192.168.1.101:1099/hello"); System.out.println("Client: " + h.getHello()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
先运行HelloRMIServer,再运行HelloRMIClient,我们能再控制台看到如下输出
Sever: hello Client: hello