Java中的远程方法调用
远程方法调用 (RMI) 是一种 API,它允许对象调用存在于另一个地址空间中的对象的方法,该地址空间可以在同一台机器上,也可以在远程机器上。通过 RMI,在计算机(客户端)上的 JVM 中运行的对象可以调用另一个 JVM(服务器端)中的对象上的方法。 RMI 创建一个公共远程服务器对象,该对象通过对服务器对象的简单方法调用实现客户端和服务器端通信。
存根对象:客户端机器上的存根对象构建一个信息块并将此信息发送到服务器。
该块包括
- 要使用的远程对象的标识符
- 要调用的方法名
- 远程 JVM 的参数
骨架对象:骨架对象将来自存根对象的请求传递给远程对象。它执行以下任务
- 它在服务器上存在的真实对象上调用所需的方法。
- 它将从存根对象接收到的参数转发给方法。
RMI的工作
客户端和服务器之间的通信是通过使用两个中间对象来处理的:存根对象(在客户端)和骨架对象(在服务器端),也可以从下面的媒体中描述如下:
这些是按顺序执行的步骤,以实现如下定义的接口:
- 定义远程接口
- 实现远程接口
- 使用 rmic(RMI 编译器)从实现类创建 Stub 和 Skeleton 对象
- 启动 rmiregistry
- 创建并执行服务器应用程序
- 创建并执行客户端应用程序。
第 1 步:定义远程接口
首先要做的是创建一个接口,该接口将提供远程客户端可以调用的方法的描述。该接口应该扩展 Remote 接口,并且接口内的方法原型应该抛出 RemoteException。
例子:
Java
// Creating a Search interface
import java.rmi.*;
public interface Search extends Remote
{
// Declaring the method prototype
public String query(String search) throws RemoteException;
}
Java
// Java program to implement the Search interface
import java.rmi.*;
import java.rmi.server.*;
public class SearchQuery extends UnicastRemoteObject
implements Search
{
// Default constructor to throw RemoteException
// from its parent constructor
SearchQuery() throws RemoteException
{
super();
}
// Implementation of the query interface
public String query(String search)
throws RemoteException
{
String result;
if (search.equals("Reflection in Java"))
result = "Found";
else
result = "Not Found";
return result;
}
}
Java
// Java program for server application
import java.rmi.*;
import java.rmi.registry.*;
public class SearchServer
{
public static void main(String args[])
{
try
{
// Create an object of the interface
// implementation class
Search obj = new SearchQuery();
// rmiregistry within the server JVM with
// port number 1900
LocateRegistry.createRegistry(1900);
// Binds the remote object by the name
// geeksforgeeks
Naming.rebind("rmi://localhost:1900"+
"/geeksforgeeks",obj);
}
catch(Exception ae)
{
System.out.println(ae);
}
}
}
Java
// Java program for client application
import java.rmi.*;
public class ClientRequest
{
public static void main(String args[])
{
String answer,value="Reflection in Java";
try
{
// lookup method to find reference of remote object
Search access =
(Search)Naming.lookup("rmi://localhost:1900"+
"/geeksforgeeks");
answer = access.query(value);
System.out.println("Article on " + value +
" " + answer+" at GeeksforGeeks");
}
catch(Exception ae)
{
System.out.println(ae);
}
}
}
第 2 步:实现远程接口
下一步是实现远程接口。要实现远程接口,该类应扩展为Java.rmi 包的 UnicastRemoteObject 类。此外,需要创建一个默认构造函数来从类中的父构造函数中抛出Java.rmi.RemoteException。
Java
// Java program to implement the Search interface
import java.rmi.*;
import java.rmi.server.*;
public class SearchQuery extends UnicastRemoteObject
implements Search
{
// Default constructor to throw RemoteException
// from its parent constructor
SearchQuery() throws RemoteException
{
super();
}
// Implementation of the query interface
public String query(String search)
throws RemoteException
{
String result;
if (search.equals("Reflection in Java"))
result = "Found";
else
result = "Not Found";
return result;
}
}
第 3 步:使用 rmic 从实现类创建 Stub 和 Skeleton 对象
rmic 工具用于调用创建 Stub 和 Skeleton 对象的 rmi 编译器。它的原型是 rmic 类名。对于上述程序,需要在命令提示符下执行以下命令
rmic 搜索查询。
第 4 步:启动 rmiregistry
通过在命令提示符处发出以下命令启动注册表服务 start rmiregistry
第五步:创建并执行服务器应用程序
下一步是创建服务器应用程序并在单独的命令提示符下执行它。
- 服务器程序使用 LocateRegistry 类的 createRegistry 方法在服务器 JVM 中创建 rmiregistry,并将端口号作为参数传递。
- Naming 类的 rebind 方法用于将远程对象绑定到新名称。
Java
// Java program for server application
import java.rmi.*;
import java.rmi.registry.*;
public class SearchServer
{
public static void main(String args[])
{
try
{
// Create an object of the interface
// implementation class
Search obj = new SearchQuery();
// rmiregistry within the server JVM with
// port number 1900
LocateRegistry.createRegistry(1900);
// Binds the remote object by the name
// geeksforgeeks
Naming.rebind("rmi://localhost:1900"+
"/geeksforgeeks",obj);
}
catch(Exception ae)
{
System.out.println(ae);
}
}
}
第六步:创建并执行客户端应用程序
最后一步是创建客户端应用程序并在单独的命令提示符下执行它。 Naming 类的查找方法用于获取 Stub 对象的引用。
Java
// Java program for client application
import java.rmi.*;
public class ClientRequest
{
public static void main(String args[])
{
String answer,value="Reflection in Java";
try
{
// lookup method to find reference of remote object
Search access =
(Search)Naming.lookup("rmi://localhost:1900"+
"/geeksforgeeks");
answer = access.query(value);
System.out.println("Article on " + value +
" " + answer+" at GeeksforGeeks");
}
catch(Exception ae)
{
System.out.println(ae);
}
}
}
注意:上面的客户端和服务器程序在同一台机器上执行,所以使用 localhost。为了从另一台机器访问远程对象,localhost 将被替换为远程对象所在的 IP 地址。
将文件分别按类名保存为
搜索。 Java , 搜索查询。 Java , 搜索服务器。 Java & 客户端请求。Java
重要观察:
- RMI 是远程过程调用 (RPC) 的纯Java解决方案,用于在Java中创建分布式应用程序。
- Stub 和 Skeleton 对象用于客户端和服务器端之间的通信。