看到RMI,首先想到了这个问题,什么是RMI
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