Java远程方法调用(Remote Method Invocation,RMI)

Java RMI简介:

它是Java的一个核心API和类库,允许一个Java虚拟机上运行的Java程序调用不同虚拟机上运行的对象中的方法,即使这两个虚拟机运行于物理隔离的不同主机上。

Java RMI在JDK1.1版本已经存在,是非常重要的底层技术。

下面通过一个简单的例子来测试:

 1 package com.tc.remote;
 2 
 3 import java.rmi.Remote;
 4 import java.rmi.RemoteException;
 5 
 6 /**
 7  * 一个远程调用接口RMIQueryStatus
 8  * 远程接口必须声明为public
 9  * 远程接口必须继承自java.rmi.Remote
10  */
11 public interface RMIQueryStatus extends Remote{
12 
13     // 远程调用中的方法必须抛出RemoteException异常 
14     RMIFileStatus getFileStatus(String filename) throws RemoteException;
15 
16 }
 1 package com.tc.remote;
 2 
 3 import java.io.Serializable;
 4 
 5 /**
 6  * RMI文件状态类,远程调用方法返回的对象
 7  */
 8 public class RMIFileStatus implements Serializable{
 9 
10     private String filename;
11 
12     public RMIFileStatus() {
13     }
14 
15     public RMIFileStatus(String filename) {
16         this.filename = filename;
17     }
18 
19     @Override
20     public String toString() {
21         return "RMIFileStatus{" +
22                 "filename='" + filename + '\'' +
23                 '}';
24     }
25 
26 }
 1 package com.tc.remote;
 2 
 3 import java.rmi.RemoteException;
 4 import java.rmi.server.UnicastRemoteObject;
 5 
 6 /**
 7  * 远程接口的实现 .
 8  */
 9 public class RMIQueryStatusImpl extends UnicastRemoteObject implements RMIQueryStatus {
10 
11     /**
12      * 因为UnicastRemoteObject的构造函数抛出了RemoteException异常
13      * 这里默认构造方法必须写
14      * @throws RemoteException
15      */
16     public RMIQueryStatusImpl() throws RemoteException {
17     }
18 
19     @Override
20     public RMIFileStatus getFileStatus(String filename) throws RemoteException {
21         RMIFileStatus status = new RMIFileStatus(filename);
22         // ...进行处理
23         return status;
24     }
25 
26 }
 1 package com.tc.remote;
 2 
 3 import java.net.MalformedURLException;
 4 import java.rmi.Naming;
 5 import java.rmi.RemoteException;
 6 import java.rmi.registry.LocateRegistry;
 7 
 8 /**
 9  * 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。
10  */
11 public class RMIQueryStatusServer {
12 
13     public static String RMI_URL = "rmi://localhost:8888/RHello";
14 
15     public static void main(String[] args) {
16         try {
17             RMIQueryStatusImpl queryStatus = new RMIQueryStatusImpl();
18             // 注册表创建
19             LocateRegistry.createRegistry(8888);
20             // 绑定远端对象到名字
21             Naming.rebind(RMI_URL,queryStatus);
22 //            Naming.bind(RMI_URL,queryStatus);
23 //            bind方法在已经为一个名字绑定一个对象,再向此名称绑定对象,会抛出异常
24 //            而使用rebind方法不会
25             System.out.println(">>>>>INFO:远程RMIQueryStatus对象绑定成功!");
26         } catch (RemoteException e) {
27             e.printStackTrace();
28         } catch (MalformedURLException e) {
29             e.printStackTrace();
30         }
31     }
32 
33 }
 1 package com.tc.remote;
 2 
 3 import java.net.MalformedURLException;
 4 import java.rmi.Naming;
 5 import java.rmi.NotBoundException;
 6 import java.rmi.RemoteException;
 7 
 8 /**
 9  * 客户端测试,在客户端调用远程对象上的远程方法,并返回结果。
10  */
11 public class RMIQueryStatusClient {
12 
13     public static void main(String[] args) {
14         try {
15             RMIQueryStatus queryStatus = (RMIQueryStatus) Naming.lookup(RMIQueryStatusServer.RMI_URL);
16             // 调用远程方法,该调用如同调用本地方法
17             RMIFileStatus status = queryStatus.getFileStatus("爆炸");
18             System.out.println(status);
19         } catch (NotBoundException e) {
20             e.printStackTrace();
21         } catch (MalformedURLException e) {
22             e.printStackTrace();
23         } catch (RemoteException e) {
24             e.printStackTrace();
25         }
26     }
27 
28 }

先运行RMIQueryStatusServer 的main方法:

注意:虽然main方法的执行很快,但是服务器还是会继续运行的,红色的方块表示了运行。

再运行RMIQueryStatusClient 的main方法:

这里只是简单的进行了测试,感觉Client需要拿到Server的RMI_URL,还是有比较强的依赖性。

希望实际项目中用到以后能够有更深刻的理解。

 

http://docs.oracle.com/javase/8/docs/technotes/guides/rmi/index.html

 

posted @ 2016-09-21 15:52  鐵手  阅读(7242)  评论(0编辑  收藏  举报