Erste Schritte mit Java RMI

Erste Schritte mit Java RMI

1. Überblick

Wenn zwei JVMs miteinander kommunizieren müssen, ist Java RMI eine Option, mit der wir dies erreichen können. In diesem Artikel wird ein einfaches Beispiel für die Java RMI-Technologie erstellt.

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

Zunächst erstellen wir die Schnittstelle für das Remote-Objekt. Diese Schnittstelle erweitert die Markierungsschnittstelle vonjava.rmi.Remote.

Zusätzlich löst jede in der Schnittstelle deklarierte Methodejava.rmi.RemoteException aus:

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-Typenjava.io.Serializable implementieren.

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

Für den Server erstellen wir die Implementierung, die häufig alsRemote Objectbezeichnet wird.

Für den Clientthe RMI library will dynamically create an implementation called a Stub.

2.2. Implementierung

Implementieren wir außerdem die Remote-Schnittstelle, die wiederum alsRemote Object 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 diethrowsRemoteException-Klausel aus der Methodendefinition weggelassen haben.

Es ist ungewöhnlich, dass unser Remote-ObjektRemoteException 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.

Auchany additional methods defined in the remote object, but not in the interface, remain invisible for the client.

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 statischeUnicastRemoteObject.exportObject-Methode, um unsere Stub-Implementierung zu erstellen. The stub is what does the magic of communicating with the server over the underlying RMI protocol.

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

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

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

Leider ist die MethodeexportObject() ohne Portnummer veraltet.

3.2 Creating a Registry

Wir können eine lokale Registrierung für unseren Server oder einen 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 MethodecreateRegistryverwendet, da wir die Registrierung lokal auf dem Server erstellen.

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

Im eigenständigen Fall rufen wir jedochgetRegistry auf und übergeben den Hostnamen und die Portnummer als Parameter.

3.3 Binding the Stub

Lassen Sie uns daher unseren Stub an die Registrierung binden. Eine RMI-Registrierung ist eine Benennungseinrichtung 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 nun jedem Client zur Verfügung, der die Registrierung finden kann.

4. Client erstellen

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

Dazu suchen wir zuerst die RMI-Registrierung. Außerdem suchen wir den Remote-Objekt-Stub mit dem begrenzten eindeutigen Schlüssel.

Und schließlich rufen wir die MethodesendMessageauf:

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 angetRegistry.

Befindet sich die Registrierung eher auf einem anderen Host oder einem anderen Port, können wir diese Parameter angeben.

Sobald wir das Stub-Objekt mithilfe der Registrierung suchen, können wir die Methoden auf dem Remoteserver aufrufen.

5. Fazit

In diesem Tutorial erhalten wir eine kurze Einführung in Java RMI 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!

Der Quellcode dieses Tutorials befindet sich überon GitHub.