Erste Schritte mit Java RMI

1. Übersicht

Wenn zwei JVMs kommunizieren müssen, ist Java RMI eine Option, um dies zu erreichen. In diesem Artikel werden wir ein einfaches Beispiel für die Java RMI-Technologie booten.

2. Server erstellen

Zum Erstellen eines RMI-Servers sind zwei Schritte erforderlich:

  1. Erstellen Sie eine Schnittstelle, die den Client / Server-Vertrag definiert.
  2. Erstellen Sie eine Implementierung dieser Schnittstelle.

2.1. Vertrag definieren

Lassen Sie uns zunächst die Schnittstelle für das Remote-Objekt erstellen. Diese Schnittstelle erweitert die Markierungsschnittstelle java.rmi.Remote .

Darüber hinaus löst jede in der Schnittstelle deklarierte Methode die Datei java.rmi aus. RemoteException :

public interface MessengerService extends Remote { String sendMessage(String clientMessage) throws RemoteException; }

Beachten Sie jedoch, dass RMI die vollständige Java-Spezifikation für Methodensignaturen unterstützt, solange die Java-Typen java.io.Serializabl e implementieren .

Wir werden in zukünftigen Abschnitten sehen, wie sowohl der Client als auch der Server diese Schnittstelle verwenden.

Für den Server erstellen wir die Implementierung, die häufig als Remote-Objekt bezeichnet wird .

Für den Client erstellt die RMI-Bibliothek dynamisch eine Implementierung namens Stub .

2.2. Implementierung

Lassen Sie uns außerdem die Remote-Schnittstelle implementieren, die wiederum als Remote-Objekt bezeichnet wird :

public class MessengerServiceImpl implements MessengerService { @Override public String sendMessage(String clientMessage) { return "Client Message".equals(clientMessage) ? "Server Message" : null; } public String unexposedMethod() { /* code */ } }

Beachten Sie , dass wir aufgehört haben , die wirft Remote Klausel aus der Methodendefinition.

Es ist ungewöhnlich, dass unser Remote-Objekt eine RemoteException auslöst, da diese Ausnahme normalerweise für die RMI-Bibliothek reserviert ist, um Kommunikationsfehler beim Client auszulösen .

Das Weglassen hat auch den Vorteil, dass unsere Implementierung RMI-unabhängig bleibt.

Darüber hinaus bleiben alle zusätzlichen Methoden, die im Remote-Objekt, jedoch nicht in der Schnittstelle definiert sind, für den Client unsichtbar.

3. Registrieren des Dienstes

Sobald wir die Remote-Implementierung erstellt haben, müssen wir das Remote-Objekt an eine RMI-Registrierung binden.

3.1. Stub erstellen

Zuerst müssen wir einen Stub unseres entfernten Objekts erstellen:

MessengerService server = new MessengerServiceImpl(); MessengerService stub = (MessengerService) UnicastRemoteObject .exportObject((MessengerService) server, 0);

Wir verwenden die statische UnicastRemoteObject.exportObject- Methode, um unsere Stub-Implementierung zu erstellen. Der Stub ist das, was die Magie der Kommunikation mit dem Server über das zugrunde liegende RMI-Protokoll bewirkt.

Das erste Argument für exportObject ist das Remote-Server-Objekt.

Das zweite Argument ist der Port, den exportObject zum Exportieren des Remote-Objekts in die Registrierung verwendet.

Wenn Sie den Wert Null angeben, ist es uns egal, welchen Port exportObject verwendet. Dies ist typisch und wird dynamisch ausgewählt.

Leider ist die exportObject () -Methode ohne Portnummer veraltet.

3.2 Registrierung erstellen

Wir können eine lokale Registrierung auf unserem Server oder als separaten eigenständigen Dienst einrichten.

Der Einfachheit halber erstellen wir eine, die lokal für unseren Server ist:

Registry registry = LocateRegistry.createRegistry(1099);

Dadurch wird eine Registrierung erstellt, an die Stubs von Servern gebunden und von Clients erkannt werden können.

Außerdem haben wir die Methode createRegistry verwendet, da wir die Registrierung lokal auf dem Server erstellen.

Standardmäßig wird eine RMI-Registrierung auf Port 1099 ausgeführt. Stattdessen kann in der Factory-Methode createRegistry auch ein anderer Port angegeben werden.

Im eigenständigen Fall würden wir jedoch getRegistry aufrufen und den Hostnamen und die Portnummer als Parameter übergeben.

3.3 Binden des Stummels

Lassen Sie uns daher unseren Stub an die Registrierung binden. Eine RMI-Registrierung ist eine Namensfunktion wie JNDI usw. Wir können hier einem ähnlichen Muster folgen und unseren Stub an einen eindeutigen Schlüssel binden:

registry.rebind("MessengerService", stub); 

Infolgedessen steht das Remote-Objekt jetzt jedem Client zur Verfügung, der die Registrierung finden kann.

4. Erstellen des Clients

Zum Schluss schreiben wir den Client, um die Remote-Methoden aufzurufen.

Dazu suchen wir zuerst die RMI-Registrierung. Darüber hinaus suchen wir den Remote-Objekt-Stub mit dem begrenzten eindeutigen Schlüssel.

Und schließlich rufen wir die sendMessage- Methode auf:

Registry registry = LocateRegistry.getRegistry(); MessengerService server = (MessengerService) registry .lookup("MessengerService"); String responseMessage = server.sendMessage("Client Message"); String expectedMessage = "Server Message"; assertEquals(expectedMessage, responseMessage);

Da wir die RMI-Registrierung auf dem lokalen Computer und dem Standardport 1099 ausführen , übergeben wir keine Parameter an getRegistry .

In der Tat können wir diese Parameter angeben, wenn sich die Registrierung eher auf einem anderen Host oder einem anderen Port befindet.

Sobald wir das Stub-Objekt mithilfe der Registrierung gesucht haben, können wir die Methoden auf dem Remote-Server aufrufen.

5. Schlussfolgerung

In diesem Tutorial haben wir eine kurze Einführung in Java RMI erhalten und wie es die Grundlage für Client-Server-Anwendungen sein kann. Seien Sie gespannt auf weitere Beiträge zu einigen der einzigartigen Funktionen von RMI!

Den Quellcode dieses Tutorials finden Sie auf GitHub.