如何运行Java RMI 应用程序
先决条件: RMI
RMI(远程方法调用)用于分布式对象引用系统。分布式对象是在其他机器上发布其接口的对象。远程对象是其状态被封装的分布式对象。 Stub 和 Skeleton 是用于与远程对象通信的两个对象。
存根:存根是客户端程序的网关,用于与骨架对象进行通信,通过在它们之间建立连接。
骨架:驻留在服务器程序上,用于将请求从存根传递到远程接口。
RMI 中如何进行通信和处理:
在控制台中运行Java RMI 应用程序的步骤
- 为问题陈述创建类和接口:其中涉及的步骤如下:
- 创建一个扩展Java.rmi.Remote 的远程接口:
远程接口确定客户端可以远程调用的对象。该接口可以与客户端的程序进行通信。此接口必须扩展Java.rmi.Remote接口。
问题陈述:创建一个 RMI 应用程序来查找数字的阶乘
Interface Program
import java.math.BigInteger; // Creating an Interface public interface Factorial extends java.rmi.Remote { // Declaring the method public BigInteger fact(int num) throws java.rmi.RemoteException; }
Implementation of Interface
import java.math.BigInteger; // Extends and Implement the class // and interface respectively public class FactorialImpl extends java.rmi.server.UnicastRemoteObject implements Factorial { // Constructor Declaration public FactorialImpl() throws java.rmi.RemoteException { super(); } // Calculation for the problem statement // Implementing the method fact() // to find factorial of a number public BigInteger fact(int num) throws java.rmi.RemoteException { BigInteger factorial = BigInteger.ONE; for (int i = 1; i <= num; ++i) { factorial = factorial .multiply( BigInteger .valueOf(i)); } return factorial; } }
Server Program
import java.rmi.Naming; public class FactorialServer { // Implement the constructor of the class public FactorialServer() { try { // Create a object reference for the interface Factorial c = new FactorialImpl(); // Bind the localhost with the service Naming.rebind("rmi:// localhost/FactorialService", c); } catch (Exception e) { // If any error occur System.out.println("ERR: " + e); } } public static void main(String[] args) { // Create an object new FactorialServer(); } }
Client Program
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class FactorialClient { public static void main(String[] args) { try { // Create an remote object with the same name // Cast the lookup result to the interface Factorial c = (Factorial); Naming.lookup("rmi:// localhost/FactorialService"); // Call the method for the results System.out.println(c.fact(30)); } // If any error occur catch (MalformedURLException murle) { System.out.println("\nMalformedURLException: " + murle); } catch (RemoteException re) { System.out.println("\nRemoteException: " + re); } catch (NotBoundException nbe) { System.out.println("\nNotBoundException: " + nbe); } catch (java.lang.ArithmeticException ae) { System.out.println("\nArithmeticException: " + ae); } } }
- 创建一个扩展Java.rmi.server.UnicastRemoteObject 并实现前一个接口的类。
这个类将实现远程接口。为问题陈述进行所需的计算。
接口的实现
import java.math.BigInteger; // Extends and Implement the class // and interface respectively public class FactorialImpl extends java.rmi.server.UnicastRemoteObject implements Factorial { // Constructor Declaration public FactorialImpl() throws java.rmi.RemoteException { super(); } // Calculation for the problem statement // Implementing the method fact() // to find factorial of a number public BigInteger fact(int num) throws java.rmi.RemoteException { BigInteger factorial = BigInteger.ONE; for (int i = 1; i <= num; ++i) { factorial = factorial .multiply( BigInteger .valueOf(i)); } return factorial; } }
- 创建一个服务器类(使用 localhost 和服务名称)
为了托管服务,创建服务器程序,从而可以调用Java.rmi.Naming.rebind() 方法,该方法接受两个参数,即对象引用(服务名称)和实例引用。
服务器程序
import java.rmi.Naming; public class FactorialServer { // Implement the constructor of the class public FactorialServer() { try { // Create a object reference for the interface Factorial c = new FactorialImpl(); // Bind the localhost with the service Naming.rebind("rmi:// localhost/FactorialService", c); } catch (Exception e) { // If any error occur System.out.println("ERR: " + e); } } public static void main(String[] args) { // Create an object new FactorialServer(); } }
- 创建一个客户端类(使用 localhost 和服务名称)
客户端程序将为 RMI URL 调用Java.rmi.Naming.lookup() 方法并返回对象类型的实例(因子接口)。所有 RMI 都在这个对象上完成
客户计划
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class FactorialClient { public static void main(String[] args) { try { // Create an remote object with the same name // Cast the lookup result to the interface Factorial c = (Factorial); Naming.lookup("rmi:// localhost/FactorialService"); // Call the method for the results System.out.println(c.fact(30)); } // If any error occur catch (MalformedURLException murle) { System.out.println("\nMalformedURLException: " + murle); } catch (RemoteException re) { System.out.println("\nRemoteException: " + re); } catch (NotBoundException nbe) { System.out.println("\nNotBoundException: " + nbe); } catch (java.lang.ArithmeticException ae) { System.out.println("\nArithmeticException: " + ae); } } }
- 创建一个扩展Java.rmi.Remote 的远程接口:
- 所有程序的编译
使用 javac 编译所有四个程序并使用 rmic (RMI Compiler) 创建存根和骨架类文件。
- 运行系统:
在编译阶段之后,系统现在可以运行了。要运行系统,请打开三个控制台屏幕(移动到程序所在的路径)。一个用于客户端,一个用于服务器,一个用于 RMI 注册表。
- 从注册表开始,使用
rmiregistry
,如果没有错误注册表将开始运行,现在移动到第二个屏幕。 - 在第二个控制台中运行服务器程序并托管 FactorialService。它将启动并等待客户端连接,并将实现加载到内存中。
- 在第三个控制台中,运行客户端程序。
- 从注册表开始,使用
这样,RMI 可以在 localhost 的三个控制台中运行。 RMI 使用网络堆栈和 TCP/IP 堆栈来实现三个不同 JVM 的通信。