在之前的公司的项目中用到了阿里的Dubbo,是一个远程调用框架,听到这个第一反应就是RPC或RMI,当然这不是我的第一反应,因为我当时都不知道那是什么,那么什么是RMI?它是用来干什么的?它和RPC有怎样的千丝万缕的联系呢?以下是一段复制粘贴内容…
RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机上的对象可以调用另外一台计算机上的对象来获取远程数据。RMI是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。在过去,TCP/IP套接字通讯是远程通讯的主要手段,但此开发方式没有使用面向对象的方式实现开发,在开发一个如此的通讯机制时往往令程序员感觉到乏味,对此RPC(Remote Procedure Call)应运而生,它使程序员更容易地调用远程程序,但在面对复杂的信息传讯时,RPC依然未能很好的支持,而且RPC未能做到面向对象调用的开发模式。针对RPC服务遗留的问题,RMI出现在世人面前,它被设计成一种面向对象的通讯方式,允许程序员使用远程对象来实现通信,并且支持多线程的服务,这是一次远程通讯的革命,为远程通信开辟新的里程碑。
所以呢…还是不知道怎么用,果然不如实现一下来的实在,那么下面是干货。
与使用Dubbo一样,我们需要一个用来远程调用的接口,以及它的实现类:
package com.aurora.rmi.server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RmiServiceApi extends Remote {
public String testFunction(String param) throws RemoteException;
}
package com.aurora.rmi.server;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RmiServiceApiImpl extends UnicastRemoteObject implements RmiServiceApi{
private static final long serialVersionUID = 1L;
protected RmiServiceApiImpl() throws RemoteException {
super();
}
@Override
public String testFunction(String param) {
System.out.println("远程方法被调用");
return "返回结果"+param;
}
}
接口要继承自java.rmi.Remote接口,同时方法要抛出java.rmi.RemoteException异常,有些人是这样解释的,因为网络传输是随时会出现异常的,所以这样做是告诉使用者调用该方法是不安全的,当然,我不知道这样解释是否合理,但又不知道更合理的解释,暂且这么理解吧。接口的实现类要继承java.rmi.server.UnicastRemoteObject类,如果继续查找其相关的父类会发现RemoteObject类实现了Serializable接口,所以实现类自然也是可序列化的,所以我们不必再自己去实现该接口。
跟序列化传输其他对象一样,客户端也需要在同样的包中有同样的接口,注意包名也要是一样的,否则会抛异常。
那么接下来就是服务器和客户端的实现了;
服务器:
package com.aurora.rmi.server;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class RmiServer {
public static void main(String[] args) {
RmiServiceApi service;
try {
LocateRegistry.createRegistry(9999);
service = new RmiServiceApiImpl();
Naming.rebind("rmi://192.168.1.139:9999/service", service);
System.out.println("Server Start...");
} catch (RemoteException e) {
e.printStackTrace();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
注意要调用LocateRegistry.createRegistry()方法注册端口,否则是不行的。
客户端:
package com.aurora.rmi.client;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import com.aurora.rmi.server.RmiServiceApi;
public class RmiClient {
public static void main(String[] args) {
try {
RmiServiceApi service = (RmiServiceApi) Naming.lookup("rmi://192.168.1.139:9999/service");
System.out.println(service.testFunction("ok"));
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
这样在客户端所在的电脑上调用另一台电脑上的服务器中RmiServiceApi中的接口就如同调用本地的接口是一样的,当然,如果网络有问题当我没说……
以上就是一个最简单的JAVA RMI的例子。