📜  如何运行Java RMI 应用程序

📅  最后修改于: 2022-05-13 01:54:20.563000             🧑  作者: Mango

如何运行Java RMI 应用程序

先决条件: RMI

RMI(远程方法调用)用于分布式对象引用系统。分布式对象是在其他机器上发布其接口的对象。远程对象是其状态被封装的分布式对象。 Stub 和 Skeleton 是用于与远程对象通信的两个对象。

存根:存根是客户端程序的网关,用于与骨架对象进行通信,通过在它们之间建立连接。

骨架:驻留在服务器程序上,用于将请求从存根传递到远程接口。

RMI 中如何进行通信和处理:

在控制台中运行Java RMI 应用程序的步骤

  1. 为问题陈述创建类和接口:其中涉及的步骤如下:
    • 创建一个扩展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);
              }
          }
      }
      
  2. 所有程序的编译

    使用 javac 编译所有四个程序并使用 rmic (RMI Compiler) 创建存根和骨架类文件。

  3. 运行系统:

    在编译阶段之后,系统现在可以运行了。要运行系统,请打开三个控制台屏幕(移动到程序所在的路径)。一个用于客户端,一个用于服务器,一个用于 RMI 注册表。

    • 从注册表开始,使用rmiregistry ,如果没有错误注册表将开始运行,现在移动到第二个屏幕。

    • 在第二个控制台中运行服务器程序并托管 FactorialService。它将启动并等待客户端连接,并将实现加载到内存中。

    • 在第三个控制台中,运行客户端程序。

这样,RMI 可以在 localhost 的三个控制台中运行。 RMI 使用网络堆栈和 TCP/IP 堆栈来实现三个不同 JVM 的通信。