1、RMI是远程方法调用的简称,像其名称暗示的那样,它能够帮助我们查找并执行远程对象,通俗的说,远程调用就像一个class放在A机器上,然后在B机器中调用这个class的方法。
2、EMI术语
在研究代码之前,我们来看看必须编写哪些代码:
远程对象:这个接口只定义了一个方法,我们应当明白的是,这个接口可以既包含方法的代码也包含方法的定义。远程对象包含要导出的每个方法的定义,并且实现Java.RMI中的远程接口。
远程对象实现:这是一个实现远程对象的类。如果实现了远程对象,就能够覆盖该对象中的所有方法,因此,远程对象的实现类将真正包含我们希望=导出的方法代码。
远程服务器:这是一个作为服务器使用的类,它是相对要远程访问方法的客户端而言的。它储存着绑定的字符串和对象。
远程客户端:这是一个帮助我们访问远程方法提供帮助的类,它也是最终用户。
Stub(存根)和Skeleton(骨架)
Stub和Skeleton是经过RMIC命令生成的,我们的程序要通过远程调用,底层一定是套接字的字节传输,传输到服务器或者客户端的对端后,再把该对象反序列化为对应的对象,这些网络传输的过程要求安全、稳定等等非常麻烦的操作,Stub驻留客户端,承担着代理远程对象的实现者的角色,Skeleton类帮助远程对象与Stub在RMI连接上进行通信。RMI的客户与STUB进行交换,STUB与SKELETON通信,SKELETON负责与服务器进行交互,因此有了STUB和SKELETON之后我们就不要需要实现底层通信的细节,我们进行的远程调用,只需要通过接口对方法进行操作即可,使分布式调用实现了位置上的透明,即:远程调用就像本地调用一样。
服务器端实现
1.服务接口
/** *服务接口 *定义了行为集 */ import java.rmi.Remote; import java.rmi.RemoteException; public interface IHello extends Remote { /** * 在服务器打印客户端发过来的message 并返回“Hello World”字符串 */ public String sayHello(String message) throws RemoteException; }
2.服务实现
/** *服务实现 *继承UnicastRemoteObject */ import java.rmi.server.UnicastRemoteObject; import java.rmi.RemoteException; public class HelloImpl extends UnicastRemoteObject implements IHello { //必须的 public HelloImpl() throws RemoteException { super(); } @Override public String sayHello(String message) { System.out.println("================client message" + message); return "Hello World!"; } }
3.启动RMI服务器并暴露服务
/** *RMI服务器 *1、创建一个服务 *2、启动服务器 *3、注册服务 */ import java.rmi.registry.*; import java.rmi.*; import java.rmi.server.*; public class HelloServer { public static void main(String[] args) throws Exception { //1 IHello hello = new HelloImpl(); //2启动服务器 启动一个注册表并把注册表绑定到一个端口(默认端口1099) LocateRegistry.createRegistry(8888); //3将服务注册到注册表 绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的) Naming.bind("rmi://localhost:8888/hello", hello); System.out.println("========服务器启动了"); } }
客户端实现
1.服务接口
/** *服务接口 *定义了行为集 */ import java.rmi.Remote; import java.rmi.RemoteException; public interface IHello extends Remote { /** * 在服务器打印客户端发过来的message 并返回“Hello World”字符串 */ public String sayHello(String message) throws RemoteException; }
2.客户端实现
/** * 1、服务实现者是谁? 服务器 * 2、如何获取服务 查找 * 3、如何调用服务接口 */ import java.rmi.*; public class HelloClient { public static void main(String[] args) throws Exception { //1、查找服务 IHello hello = (IHello)Naming.lookup("rmi://localhost:8888/hello"); System.out.println(Naming.lookup("rmi://localhost:8888/hello")); //2、调用 System.out.println(hello.sayHello("haha")); } }