RMI是Java1.1中实现的一种RPC通信机制。使用RMI可以让一个Java虚拟机中的对象调用另外一个虚拟机中对象的方法,它大大增强了Java开发分布式应用的能力。
这篇文章使用RMI实现一个简单的例子。
服务端代码
**1.**声明一个服务接口,提供给远程调用,该接口必须继承自java.rmi.Remote
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package cn.hff.service;
import java.rmi.Remote; import java.rmi.RemoteException;
public interface ICalcService extends Remote {
int add(int a, int b) throws RemoteException;
int minus(int a, int b) throws RemoteException;
}
|
**2.**实现该服务接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package cn.hff.service;
public class CalcServiceImpl implements ICalcService {
public int add(int a, int b) { int result = a + b; System.out.printf("%d + %d = %d %n", a, b, result); return result; }
public int minus(int a, int b) { int result = a - b; System.out.printf("%d - %d = %d %n", a, b, result); return result; }
}
|
**3.**调用RMI的API将服务暴露给客户端调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package cn.hff.server;
import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject;
import cn.hff.service.CalcServiceImpl; import cn.hff.service.ICalcService;
public class Server {
public static final String SERVICE_NAME = "calc";
public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException {
ICalcService service = new CalcServiceImpl();
Remote stub = UnicastRemoteObject.exportObject(service, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(SERVICE_NAME, stub);
System.out.println("ok. calc service binded");
} }
|
上面的绑定服务的方法可以简写成下面这种形式:
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException {
ICalcService service = new CalcServiceImpl();
Naming.rebind("rmi://127.0.0.1:1099/calc", service);
System.out.println("ok. calc service binded"); }
|
客户端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package cn.hff.client;
import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;
import cn.hff.service.ICalcService;
public class Client {
public static final String SERVICE_NAME = "calc";
public static void main(String[] args) throws RemoteException, NotBoundException {
Registry registry = LocateRegistry.getRegistry("127.0.0.1", 0);
Remote stub = registry.lookup(SERVICE_NAME);
ICalcService service = (ICalcService) stub;
int add = service.add(3, 3);
System.out.println(add);
int minus = service.minus(3, 3);
System.out.println(minus);
} }
|
和前面一样,查找服务的步骤也已经封装在Naming中:
1
| Remote stub = Naming.lookup("rmi://127.0.0.1:1099/calc");
|
编译运行
**1.**编译服务端的三个类,并在类路径下执行rmiregistry
命令运行本地注册表,然后再执行Server的main方法。
1 2 3 4 5 6 7 8
| # javac cn/hff/service/ICalcService.java cn/hff/service/CalcServiceImpl.java cn/hff/server/Server.java
# # # # rmiregistry
|
运行Server类的main方法:
1
| java cn.hff.server.Server
|
**2.**编译并运行客户端程序
1 2 3 4
| # javac cn/hff/client/Client.java # java cn.hff.client.Client
|
本作品采用 知识共享署名 4.0 国际许可协议 进行许可。
转载时请注明原文链接:https://blog.hufeifei.cn/2017/12/Java/RMI%E7%AE%80%E5%8D%95%E7%A4%BA%E4%BE%8B/