介绍
RMI全称是Remote Method Invocation,远程方法调⽤。RMI 应用程序通常包括两个独立的程序,一个服务端和一个客户端。服务端创建对象供客户端连接使用。
RMI-registry
RMI-registry
在RMI
的实现流程中扮演的是一个类似于数据库的角色,Server
端会将name
与remote object
的对应关系存储在RMI-registry
中,Client
在连接服务端时,先在RMI-registry
中依据name
查找对应的remote object
,如果查找到则会将对应的信息返回给客户端,客户端在获取到信息后,会根据信息中的地址,再与服务端建立连接,执行remote object
中的方法。根据自己的理解画了一个RMI的执行过程图:
RMI协议的格式为
rmi://ip:port/name 这里的name在Server中定义,将name与remote object进行绑定。 使客户端在连接服务端时可根据name查找到对应的remote object
Server端编写
Server
规定由三部分组成- 一个继承了
java.rmi.Remote
的接口,其中定义了远程调用的函数
- 一个实现了接口的类
- 一个主类,用来创建Registry(),并绑定了一个name与类的实例化对象。
Client端
Client端只要实现远程调用Server端的代码即可。需要注意的是Client需要和Server共享一个接口文件。无论服务端是在同一台机器还是在不同的机器,客户端的都要存在一个和服务端同样的接口文件。
以服务端与客户端不在同一台主机为例,
完整的包结构
客户端的包结构如下,如果没有接口文件,则无法正常连接使用
├── IRemoteHello.java ├── RMIClient.java ├── RMIServer.java └── RemoteHello.java
├── IRemoteHello.java ├── RMIClient.java
实例
包结构
├── IRemoteHello.java ├── RMIClient.java ├── RMIServer.java └── RemoteHello.java
在上面这种包结构中,无需在RMIClient中导入接口
IRemoteHello
,因为idea会自动导入。直接在idea中运行Server和client,即可看到结果如下图:如果将Server与client分别放在不同的目录下,包结构如下
└── com ├── Client │ └── RMIClient.java └── Server ├── IRemoteHello.java ├── RMIServer.java └── RemoteHello.java
在需要在RMIClient中导入接口文件,代码如下:
示例代码将服务端与客户端部署在不同的主机
需要在Server中指定
hostSystem.setProperty("java.rmi.server.hostname", "159.138.23.173");
代码与上面代码一致,只是需要在RMIServer中添加代码,最终如下
import java.rmi.Naming; import java.rmi.registry.LocateRegistry; public class RMIServer { public static void main(String[] args) throws Exception { System.setProperty("java.rmi.server.hostname", "159.138.23.173"); RemoteHello h = new RemoteHello(); LocateRegistry.createRegistry(1099); Naming.bind("rmi://0.0.0.0:1099/hello", h); } }
剩下的就是将RMIServer进行打包,然后上传到服务器运行即可,Idea打包jar→
问题
1、在根目录可以远程连接Server端,但是在子目录就无法连接。