Java Remote Method Invocation(Java RMI) 是一个 Java API, 执行远程方法的调用,相当于 Remote Procedure Calls(RPC)。Java RMI 支持直接传输序列化的 Java 类,以及分布式的垃圾回收。
案例概况
实现一个简单的 Java RMI 可通过以下四步骤:
1. 启动 rmiregistry
2. 定义服务接口,实现服务接口,通过 rmic 工具创建存根文件( stub )
3. 实现服务端功能,并启动
4. 实现客户端功能,并调用服务端服务
具体实现
1. 启动 rmiregistry
grs:~ grs$ rmiregistry
2. 定义服务接口,实现服务接口,通过 rmic 工具创建存根文件( stub )
定义服务接口:
package service; import java.rmi.Remote; import java.rmi.RemoteException; public interface GreetService extends Remote { String sayHello(String name) throws RemoteException; }
实现服务接口:
package service; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class GreetServiceImpl extends UnicastRemoteObject implements GreetService { static final long serialVersionUID = 1L; public GreetServiceImpl() throws RemoteException { super(); } @Override public String sayHello(String name) throws RemoteException { return "Hello - " + name; } }
根据编译后的 GreetServiceImpl,使用 rmic 生成存根文件
grs:bin grs$ rmic service.GreetServiceImpl
执行后,目录如下
grs:bin grs$ tree . └── service ├── GreetService.class ├── GreetServiceImpl.class └── GreetServiceImpl_Stub.class 3 directories, 5 files grs:bin grs$
3. 实现服务端功能,并启动
package server; import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import service.GreetServiceImpl; public class Server { public static void main(String[] args){ try { LocateRegistry.createRegistry(1098); Naming.bind("rmi://127.0.0.1:1098/GreetService", new GreetServiceImpl()); } catch (RemoteException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (AlreadyBoundException e) { e.printStackTrace(); } } }
编译后,服务端文件目录结构如下:
grs:bin grs$ tree . ├── server │ └── Server.class └── service ├── GreetService.class └── GreetServiceImpl.class 2 directories, 3 files grs:bin grs$
启动服务端
grs:bin grs$ java -server server.Server
4. 实现客户端功能,并调用服务端服务
package client; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import service.GreetService; public class Client { public static void main(String[] args){ try { String name = "rmi://127.0.0.1:1098/GreetService"; GreetService greetService = (GreetService) Naming.lookup(name); System.out.println(greetService.sayHello(" Thhhhhhh ")); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
编译后文件目录结构如下
grs:bin grs$ tree . ├── client │ └── Client.class └── service ├── GreetService.class └── GreetServiceImpl_Stub.class 2 directories, 3 files grs:bin grs$
客户端调用远程端方法
grs:bin grs$ java -client client.Client Hello - Thhhhhhh grs:bin grs$
参考资料:
[chapter 18] Distributed Computing : remote deployment with RMI, Head First Java