close

Zdalne wywołanie metody Java

Przejdź do nawigacji Przejdź do wyszukiwania

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