JavaRush /Java-Blog /Random-DE /RMI: Anwendungspraxis

RMI: Anwendungspraxis

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute werden wir uns mit einem ziemlich interessanten Thema befassen – RMI . Dies steht für Remote Method Invocation . RMI: Anwendungspraxis - 1Mit RMI können Sie zwei Programmen beibringen, miteinander zu kommunizieren, auch wenn sie sich auf unterschiedlichen Computern befinden. Hört sich cool an? :) Aber es ist gar nicht so schwer! In der heutigen Vorlesung werden wir verstehen, aus welchen Teilen die RMI-Interaktion besteht und wie man sie konfiguriert. Das erste, was wir brauchen, ist ein Client und ein Server . Sie müssen nicht zu tief in die Computerterminologie eintauchen. Im Fall von RMI handelt es sich lediglich um zwei Programme. Einer von ihnen enthält ein Objekt und der zweite ruft Methoden dieses Objekts auf. Methoden eines Objekts in einem Programm aufrufen, das sich in einem anderen Programm befindet – das haben wir noch nie gemacht! Es ist Zeit, es zu versuchen! :) Um nicht in der Wildnis zu ertrinken, sollte unser Programm einfach sein. Im Allgemeinen führen Server Berechnungen durch, die der Client anfordert. Für uns wird es genauso sein. Wir werden ein einfaches Taschenrechnerprogramm als Server haben. Sie wird nur eine Methode haben – multiply(). Es multipliziert die beiden vom Client-Programm an es gesendeten Zahlen und gibt das Ergebnis zurück. Zunächst benötigen wir eine Schnittstelle:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
Warum brauchen wir eine Schnittstelle? Tatsache ist, dass die Arbeit von RMI auf der Erstellung von Proxys basiert, die Sie in einer der vorherigen Vorlesungen studiert haben . Und die Arbeit mit Proxys erfolgt, wie Sie sich wahrscheinlich erinnern, genau auf der Ebene von Schnittstellen und nicht auf Klassenebene. Es gibt 2 wichtige Anforderungen an unsere Schnittstelle!
  1. Es muss die Remote-Token-Schnittstelle erben.
  2. Alle seine Methoden müssen eine RemoteException auslösen (dies geschieht nicht automatisch in der IDE, Sie müssen es manuell schreiben!).
Jetzt müssen wir eine Serverklasse erstellen, die unsere Schnittstelle implementiert Calculator. RMI: Anwendungspraxis - 2Auch hier ist alles ganz einfach:
import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

   @Override
   public int multiply(int x, int y) throws RemoteException {
       return x*y;
   }

}
Hier gibt es nicht einmal viel zu kommentieren :) Jetzt müssen wir ein Serverprogramm schreiben, das unsere Server-Rechnerklasse konfiguriert und startet. Es wird so aussehen:
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;

public class ServerMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, AlreadyBoundException, InterruptedException {

       final RemoteCalculationServer server = new RemoteCalculationServer();

       final Registry registry = LocateRegistry.createRegistry(2732);

       Remote stub = UnicastRemoteObject.exportObject(server, 0);
       registry.bind(UNIQUE_BINDING_NAME, stub);

       Thread.sleep(Integer.MAX_VALUE);

   }
}
Lass es uns herausfinden :) In der ersten Zeile erstellen wir eine Art String-Variable:
public static final String UNIQUE_BINDING_NAME = "server.calculator";
Diese Zeichenfolge ist der eindeutige Name des Remote-Objekts . Unter diesem Namen kann das Client-Programm unseren Server finden: Sie werden dies später sehen. Als nächstes erstellen wir unser Rechnerobjekt:
final RemoteCalculationServer server = new RemoteCalculationServer();
Hier ist alles klar. Interessanter ist folgendes:
final Registry registry = LocateRegistry.createRegistry(2732);
Dieses Ding namens Registry ist eine Registrierung gelöschter Objekte . „Gelöscht“ nicht in dem Sinne, dass wir sie vom Computer gelöscht haben, sondern in der Tatsache, dass auf Objekte aus diesem Register von anderen Programmen aus remote zugegriffen werden kann :) LocateRegistry.createRegistry()Wir haben der Methode die Nummer 2732 übergeben. Dies ist die Portnummer. Wenn Sie nicht wissen, was ein Port ist, können Sie ihn hier nachlesen , aber zunächst müssen Sie sich nur daran erinnern, dass dies eine eindeutige Nummer ist, anhand derer andere Programme unsere Objektregistrierung finden können (Sie werden dies auch unten sehen). Lass uns weitermachen. Mal sehen, was in der nächsten Zeile passiert:
Remote stub = UnicastRemoteObject.exportObject(server, 0);
In dieser Zeile erstellen wir einen Stub . Ein Stub kapselt den gesamten Remote-Aufrufprozess in sich. Man kann sagen, dass dies das wichtigste Element von RMI ist. Was macht Sie?
  1. Empfängt alle Informationen zu einem Remote-Aufruf einer Methode.
  2. Wenn die Methode Parameter hat, deserialisiert der Stub diese. Achten Sie auf diesen Punkt! Die Parameter, die Sie an Methoden für Remote-Aufrufe übergeben, müssen serialisierbar sein (schließlich werden sie über das Netzwerk übertragen). Bei uns gibt es kein solches Problem, wir übermitteln lediglich Nummern. Aber wenn Sie Gegenstände übertragen, vergessen Sie das nicht!
  3. Danach ruft es die gewünschte Methode auf.
Wir übergeben UnicastRemoteObject.exportObject()unser Server-Rechnerobjekt an die Methode. Auf diese Weise machen wir es möglich, seine Methoden aus der Ferne aufzurufen. Uns bleibt nur noch eines zu tun:
registry.bind(UNIQUE_BINDING_NAME, stub);
Wir „registrieren“ unseren Stub in der Remote-Objekt-Registrierung unter dem Namen, den wir uns ganz am Anfang ausgedacht haben. Jetzt kann der Kunde es finden! Sie haben vielleicht bemerkt, dass wir am Ende den Hauptthread des Programms in den Ruhezustand versetzt haben:
Thread.sleep(Integer.MAX_VALUE);
Wir müssen nur den Server für eine lange Zeit am Laufen halten. Wir werden in IDEa zwei Methoden gleichzeitig ausführen main(): zuerst die Server-Methode (in der Klasse, ServerMaindie wir bereits geschrieben haben) und dann die Client-Methode (in der Klasse, die ClientMainwir unten schreiben werden). Es ist wichtig, dass das Serverprogramm nicht ausfällt, während wir den Client starten, also versetzen wir es einfach für längere Zeit in den Ruhezustand. Es wird immer noch funktionieren :) Jetzt können wir main()unsere Servermethode ausführen. Lassen Sie es laufen und warten Sie, bis das Client-Programm eine Methode aufruft :) Jetzt schreiben wir ein Client-Programm! Es sendet Zahlen zur Multiplikation an unseren Server.
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ClientMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, NotBoundException {

       final Registry registry = LocateRegistry.getRegistry(2732);

       Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);

       int multiplyResult = calculator.multiply(20, 30);

       System.out.println(multiplyResult);
   }
}
Sie sieht unkompliziert aus. Was ist denn hier los? Zunächst muss der Client den eindeutigen Namen des Objekts kennen, dessen Methoden er remote aufruft. Deshalb haben wir im Client-Programm auch eine Variable erstellt. Als nächstes erhalten wir public static final String UNIQUE_BINDING_NAME = "server.calculator"; in der Methode Zugriff auf das Register der Remote-Objekte. main()Dazu müssen wir die Methode aufrufen LocateRegistry.getRegistry()und dort die Portnummer übergeben, auf der unser Register im ServerMain-Programm erstellt wurde – Port 2732 (diese Nummer wurde für das Beispiel gewählt, Sie können es mit einer anderen versuchen):
final Registry registry = LocateRegistry.getRegistry(2732);
Jetzt müssen wir nur noch das gewünschte Objekt aus der Kasse holen! Das ist ganz einfach, denn wir kennen seinen einzigartigen Namen!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
Achten Sie auf den Typguss. Wir wandeln das resultierende Objekt in eine Schnittstelle Calculatorund nicht in eine konkrete Klasse RemoteCalculationServer um . Wie wir zu Beginn der Vorlesung sagten, basiert RMI auf der Verwendung eines Proxys, sodass ein Remote-Aufruf nur für Schnittstellenmethoden und nicht für Klassen verfügbar ist. Am Ende rufen wir remote eine Methode multiply()für unser Objekt auf und geben das Ergebnis auf der Konsole aus.
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
Wir haben die Methode vor langer Zeit main()in der Klasse gestartet, es ist Zeit, die Methode im Client-Programm zu starten ! Konsolenausgabe: 600 Das ist es! Unser Programm (sogar zwei!) hat seine Funktion erfolgreich erfüllt :) Wenn Sie Zeit und Lust haben, können Sie es ein wenig abwechslungsreicher gestalten. Stellen Sie beispielsweise sicher, dass der Rechner alle vier Standardoperationen unterstützt und nicht Zahlen, sondern ein Objekt als Parameter übergeben werden . Als zusätzliches Material können Sie sich Artikel und Beispiele ansehen – hier: ServerMainmain()ClientMainCalculationInstance(int x, int y) Wir sehen uns in den nächsten Kursen! :) :)
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION