Zdalne wywołanie metody Java
RMI ( Java Remote Method Invocation ) to mechanizm oferowany przez Javę do zdalnego wywoływania metody . Jest częścią standardowego środowiska uruchomieniowego Java i zapewnia prosty mechanizm komunikacji z serwerem w rozproszonych aplikacjach tylko w języku Java. Jeśli wymagana jest komunikacja między innymi technologiami, należy użyć CORBA lub SOAP zamiast RMI.
RMI charakteryzuje się łatwością użycia w programowaniu, ponieważ został zaprojektowany specjalnie dla Javy; zapewnia przekazywanie obiektów przez odwołanie (niedozwolone przez SOAP), rozproszone wyrzucanie elementów bezużytecznych (Distributed Garbage Collector) i przekazywanie dowolnego typu (funkcja nie zapewniana przez CORBA).
Poprzez RMI program Java może wyeksportować obiekt , udostępniając obiekt przez sieć i program oczekujący na żądania na porcie TCP . Następnie klient może połączyć się i wywołać metody udostępniane przez obiekt.
Wywołanie składa się z następujących kroków:
- Marshalling parametrów (przy użyciu funkcji serializacji Java ).
- Wywołanie metody (klienta na serwerze). Dzwoniący czeka na odpowiedź.
- Po zakończeniu wykonywania serwer serializuje wartość zwracaną (jeśli istnieje) i wysyła ją do klienta.
- Kod klienta odbiera odpowiedź i kontynuuje, tak jakby wywołanie było lokalne.
Kontekst
Od wersji 1.1 JDK, Java posiada własny ORB : RMI (Remote Method Invocation). Chociaż RMI jest ORB w ogólnym znaczeniu, nie jest to model zgodny z CORBA. RMI jest natywny dla Javy, to znaczy jest rozszerzeniem podstawowego języka. RMI opiera się całkowicie na rdzeniu Java Object Serialization, a także implementacji zarówno przenośności, jak i mechanizmów ładowania i rozładowywania obiektów w innych systemach itp.
Korzystanie z RMI jest bardzo naturalne dla każdego programisty Java, ponieważ nie musi on uczyć się nowej technologii zupełnie innej niż ta, za pomocą której będzie się rozwijał. Jednak RMI ma pewne ograniczenia ze względu na ścisłą integrację z Javą, z których głównym jest to, że technologia ta nie pozwala na interakcję z aplikacjami napisanymi w innym języku.
RMI, jako rozszerzenie Javy, to technologia programistyczna zaprojektowana do rozwiązywania problemów poprzez pisanie i organizowanie kodu wykonywalnego. Tym samym RMI wraz z C, C++, Smalltalk itp. stanowi specyficzny punkt w przestrzeni technologii programistycznych.
Główna różnica między używaniem RPC i RMI polega na tym, że RMI jest mechanizmem zdalnego wywoływania procedur opartym na języku programowania Java, który obsługuje interakcję między obiektami, podczas gdy RPC nie obsługuje tej funkcji.
Architektura
Architekturę RMI można postrzegać jako model czterowarstwowy.
Pierwsza warstwa
Pierwsza warstwa to warstwa aplikacji i odpowiada faktycznej implementacji aplikacji klienckiej i serwerowej. W tym miejscu odbywają się wywołania wysokiego poziomu w celu uzyskania dostępu do zdalnych obiektów i ich eksportu. Każda aplikacja, która chce, aby jej metody były dostępne dla klientów zdalnych, musi zadeklarować te metody w interfejsie rozszerzającym java.rmi.Remote. Taki interfejs służy w zasadzie do „oznaczenia” obiektu jako dostępnego zdalnie. Po zaimplementowaniu metod obiekt należy wyeksportować. Można to zrobić niejawnie, jeśli obiekt rozszerza klasę UnicastRemoteObject (pakiet java.rmi.server) lub jawnie, wywołując metodę exportObject() tego samego pakietu.
Druga warstwa
Warstwa 2 to warstwa pośrednicząca lub warstwa szkieletowa. Ta warstwa jest tą, która bezpośrednio wchodzi w interakcję z warstwą aplikacji. Wszystkie wywołania zdalnych obiektów i akcji wraz z ich parametrami i zwracanymi obiektami mają miejsce w tej warstwie.
Trzecia warstwa
Warstwa 3 jest zdalną warstwą odniesienia i odpowiada za obsługę semantycznej części wywołań zdalnych. Odpowiada również za zarządzanie replikacją obiektów i wykonywanie zadań specyficznych dla implementacji z obiektami zdalnymi, takich jak ustanawianie trwałości semantycznej i odpowiednie strategie odzyskiwania utraconych połączeń. W tej warstwie od warstwy transportowej oczekuje się połączenia zorientowanego strumieniowo.
Czwarta warstwa
Warstwa 4 to warstwa transportowa. Odpowiada za wykonanie niezbędnych połączeń i zarządzanie transportem danych z jednej maszyny do drugiej. Podstawowym protokołem transportowym dla RMI jest Java Remote Method Protocol (JRMP), który jest "rozumiany" tylko przez programy Java.
Elementy
Każda aplikacja RMI zwykle dzieli się na 2 części:
- Serwer, który tworzy niektóre obiekty zdalne, tworzy referencje, aby były dostępne, i czeka na ich wywołanie przez klienta.
- Klient, który uzyskuje odniesienie do zdalnych obiektów na serwerze i wywołuje je.
Przykład
Serwer RMI polega na zdefiniowaniu zdalnego obiektu, który będzie używany przez klientów. Aby utworzyć zdalny obiekt, definiowany jest interfejs , a zdalnym obiektem będzie klasa, która implementuje ten interfejs. Zobaczmy jak stworzyć przykładowy serwer w 3 krokach:
- Zdefiniuj zdalny interfejs. Po utworzeniu zdalnego interfejsu:
- Interfejs musi być publiczny.
- Musi dziedziczyć z interfejsu java.rmi.Remote, aby wskazać, że można go wywołać z dowolnej wirtualnej maszyny Java.
- Każda metoda zdalna musi zgłosić wyjątek java.rmi.RemoteException w swojej klauzuli throws, oprócz wszelkich wyjątków, które może obsłużyć.
publiczny interfejs MyRemoteInterface rozszerza java . rmi . Remote
{
public void myMethod1 () wyrzuca java . rmi . Wyjątek zdalny ;
public int myMethod2 () wyrzuca java . rmi . Wyjątek zdalny ;
}
- Zaimplementuj zdalny interfejs
public class MyRemoteClass
rozszerza java . rmi . serwer . UnicastRemoteObject
implementuje MyRemoteInterface
{
public MyRemoteClass () wyrzuca java . rmi . Wyjątek zdalny
{
super (); //Wywołanie konstruktora klasy bazowej (UnicastRemoteObject)
// Kod konstruktora
}
public void myMethod1 () wyrzuca java . rmi . RemoteException
{
// Tutaj umieszczamy kod, który chcemy
System . się . println ( "Jestem w mojejMetodzie1()" );
}
public int myMethod2 () wyrzuca java . rmi . RemoteException
{
return 5 ; // Tutaj umieszczamy kod, który chcemy
}
public void otherMethod ()
{
// Jeśli zdefiniujemy inną metodę, nie można jej wywołać
// zdalnie, ponieważ nie jest ona z interfejsu zdalnego
}
public static void main ( String [] args )
{
spróbuj
{
MyRemoteInterface mir = new MyRemoteClass ();
java . rmi . Nazewnictwo . rebind ( " rmi ://" + java .net .InetAddress .getLocalHost ( ). getHostAddress ( ) + ":" + args [ 0 ] + "/TestRMI" , mir ); } catch ( Wyjątek e ) { e . printStackTrace (); } } }
- Jak widać, klasa MyRemoteClass implementuje interfejs MyRemoteInterface, który wcześniej zdefiniowaliśmy. Dziedziczy również z klasy UnicastRemoteObject, która jest klasą Javy, której możemy użyć jako nadklasy do implementacji zdalnych obiektów.
- Następnie wewnątrz klasy definiujemy konstruktor (który zgłasza wyjątek RemoteException, ponieważ jest on również zgłaszany przez nadklasę UnicastRemoteObject) oraz metody interfejsów, które implementuje.
- Na koniec w głównej metodzie definiujemy kod, aby utworzyć zdalny obiekt, który chcemy udostępnić i udostępnić zdalny obiekt klientom, używając klasy Naming i jej metody rebind(...).
Uwaga: dla wygody umieściliśmy metodę main() wewnątrz tej samej klasy. Można by zdefiniować oddzielną klasę odpowiedzialną za rejestrację zdalnego obiektu.
- Skompiluj i uruchom serwer
Mamy już zdefiniowany serwer. Teraz musimy skompilować twoje klasy, wykonując następujące kroki:
- Kompilujemy zdalny interfejs. Dodatkowo grupujemy go w pliku JAR, aby był obecny zarówno na kliencie, jak i na serwerze:
javac MyRemoteInterface.java jar cvf objRemotes.jar MyRemoteInterface.class
- Następnie kompilujemy klasy, które implementują interfejsy. I dla każdego z nich generujemy pliki Stub i Skeleton, aby zachować odniesienie do zdalnego obiektu, używając polecenia rmic:
ustaw CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;. javac MyRemoteClass.java rmic -d . MojaRemoteClass
Widzimy w naszym katalogu roboczym, że dwa pliki .class zostały wygenerowane automatycznie (MiClaseRemota_Skel.class i MiClaseRemota_Stub.class) odpowiadające warstwie szkieletowej architektury RMI.
- Aby uruchomić serwer, wykonujemy następujące kroki:
- Rejestrowanie RMI jest uruchamiane, aby umożliwić rejestrowanie i wyszukiwanie zdalnych obiektów. Rejestr odpowiada za zarządzanie zbiorem udostępnianych obiektów zdalnych i wyszukiwanie ich na żądanie klientów. Działa z aplikacją rmiregistry dystrybuowaną z Javą, do której możemy opcjonalnie przekazać port do połączenia (domyślnie 1099).
W przypadku Windows należy to wykonać:
rozpocznij rejestr rmi 1234
A w przypadku Linuksa:
rejestr rmi i
- Wreszcie uruchamiany jest serwer:
java -Djava.rmi.server.hostname=127.0.0.1 MyRemoteClass 1234
- Utwórz klienta RMI
Zdefiniujemy teraz klienta, który będzie miał dostęp do tworzonych przez nas obiektów zdalnych. W tym celu wykonujemy następujące kroki:
- Zdefiniuj klasę, aby uzyskać wymagane obiekty zdalne
Poniższa klasa pobiera obiekt typu MyRemoteInterface, zaimplementowany na naszym serwerze:
public class MyRMIClient
{
prywatny MyRMIClient (){};
public static void main ( String [] args )
{
spróbuj
{
MyRemoteInterface mir = ( MyRemoteInterface ) java . rmi . Nazewnictwo . lookup ( "rmi://" +
args [ 0 ] + ":" + args [ 1 ] + "/RMITest" );
// Wydrukuj mojaMetoda1() tyle razy, ile zwraca mojaMetoda2()
for ( int i = 1 ; i <= myr . mojaMetoda2 (; i ++ )
myr . mojaMetoda1 ();
}
catch ( Wyjątek e )
{
e . printStackTrace ();
}
}
}
Jak widać, polega to po prostu na szukaniu zdalnego obiektu w rejestrze RMI zdalnej maszyny. W tym celu wykorzystujemy klasę Naming i jej metodę lookup(...).
- Skompiluj i uruchom klienta
Po zdefiniowaniu klienta, aby go skompilować, wykonujemy:
ustaw CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;. javac MyRMIClient.java
Następnie, aby uruchomić klienta wykonujemy:
java MójKlientRMI 127.0.0.1 1234
Plik pośredniczący klasy zdalnej musi być dostępny. Aby to zrobić, albo kopiujemy go do klienta i umieszczamy w jego CLASSPATH, albo usuwamy go z CLASSPATH serwera i dołączamy jego ścieżkę do java.rmi.codebase serwera (jeśli nie została usunięta z CLASSPATH serwera, opcja java. rmi.codebase, a klient nie będzie mógł uzyskać dostępu do Stub).Jeśli spojrzymy na okno, w którym działa serwer RMI, zobaczymy, jak zdalny obiekt został znaleziony i jego metody zostały wykonane:
Zobacz także
Linki zewnętrzne
- Prosty przykład RMI
- Samouczek Java RMI Tutorial firmy Sun Microsystems (w języku angielskim)
- Ścieżka: Oficjalna dokumentacja RMI Java RMI
- Przegląd aplikacji RMI Oficjalne wprowadzenie do aplikacji Java RMI