我们需要了解如何利用RMI进行远程方法调用。
1.了解RMI
首先,RMI提供了客户辅助对象和服务辅助对象,为客户辅助对象创建和服务对象相同的方法。RMI的好处在于,我们不必自己写任何网络或I/O的代码。
客户程序调用远程方法就和运行在客户自己的本地JVM上对对象进行正常方法调用一样。
RMI提供了所有运行时的基础设施,好让这一切正常工作,包括查找服务(lookup service),这个服务用来寻找和访问远程对象。
关于RMI调用和本地的方法调用,有一个不同点,虽然调用远程方法就如同调用本地方法一样,但是客户辅助对象会通过网络发送方法调用,所以网络和I/O的确是存在的。
我们知道网络和I/O是有风险的,容易失败的,所以存在随时都有可能发生异常的情况,因此,客户必须意识到风险的存在。
RMI将客户辅助对象称为:stub,服务辅助对象称为:skeleton 这两个辅助对象在使用rmi时是自动生成的。
2.动手实践
这里有用来制作远程服务的五个步骤的概要:
这些步骤将一个普通的对象变成可以被远程客户调用的远程对象。
步骤1:制作远程接口 MyRemote.java
远程接口定义出可以让客户远程调用的方法,客户将用它作为服务的类类型,Stub和实际的服务都实现此接口。
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface MyRemote extends Remote {
String sayHello() throws RemoteException;
}
步骤2:制作远程的实现 MyRemoteImpl.java和注册类
服务对象,这个是做实际工作的类,为远程接口中定义的远程方法提供了真正的实现,这就是客户真正想要调用方法的对象。
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{
protected MyRemoteImpl() throws RemoteException {
}
@Override
public String sayHello() throws RemoteException {
return "Server says, 'hello!!'";
}
}
import java.rmi.Naming;
public class ServerTest {
public static void main(String[] args) {
try{
MyRemote server = new MyRemoteImpl();
Naming.rebind("RemoteHello",server);
}catch (Exception e){
e.printStackTrace();
}
}
}
步骤3:利用rmic产生的stub和skeleton
这个就是客户和服务的辅助类,你不需要自己创建这些类,甚至连生产它们的代码都不用看,因为当你运行rmic工具时,这些都会自动处理,我们可以在JDK中找到rmic
步骤4:启动RMI registry(rmiregistry)
rmiregistry就像是电话薄,客户可以从中查询到代理的位置(就是客户的辅助对象)
步骤5:开始远程服务
我们必须让服务对象开始运行,我们的服务实现类会去实例化一个服务的实例,并将这个服务注册到RMI registry,注册之后,这个服务就可以供客户调用了。
import java.rmi.Naming;
public class ClientTest {
public static void main(String[] args) {
new ClientTest().go();
}
public void go(){
try{
MyRemote service = (MyRemote) Naming.lookup("rmi://localhost/RemoteHello");
System.out.println("远程调用结果:"+service.sayHello());
}catch(Exception e){
e.printStackTrace();
}
}
}
成功!!
3. 纯程序控制实现
第二节的实现我们用到了命令行工具进行的,那么有没有一种方式直接在程序中完成所有的呢?
当然有,下面就是只需运行相应的客户端,服务端即可进行相应的远程方法调用:
设计模式/src/main/java/ProxyPattern/first · 严家豆/设计模式 - 码云 - 开源中国 (gitee.com)
服务端
客户端