Java Remote Method Invocation
RMI ( Java Remote Method Invocation ) er en mekanisme, der tilbydes af Java til at påkalde en metode eksternt. Det er en del af standard Java runtime-miljøet og giver en simpel mekanisme til serverkommunikation i distribuerede Java-only-applikationer. Hvis kommunikation mellem andre teknologier er påkrævet, bør CORBA eller SOAP bruges i stedet for RMI.
RMI er kendetegnet ved sin brugervenlighed i programmering, da den er specielt designet til Java; leverer objektoverførsel ved reference (ikke tilladt af SOAP), distribueret affaldsindsamling (Distributed Garbage Collector) og vilkårlig typeoverførsel (funktionalitet leveres ikke af CORBA).
Gennem RMI kan et Java-program eksportere et objekt , hvilket gør objektet tilgængeligt over netværket, og programmet venter på anmodninger på en TCP-port . Derefter kan en klient forbinde og påberåbe de metoder, som objektet leverer.
Indkaldelsen består af følgende trin:
- Parameter rangering (ved hjælp af Javas serialiseringsfunktionalitet ).
- Påkaldelse af metoden (af klienten på serveren). Den, der ringer, venter på svar.
- Når eksekveringen er fuldført, serialiserer serveren returværdien (hvis nogen) og sender den til klienten.
- Klientkoden modtager svaret og fortsætter, som om påkaldelsen havde været lokal.
Kontekst
Siden JDK version 1.1 har Java sin egen ORB : RMI (Remote Method Invocation). Selvom RMI er en ORB i generel forstand, er det ikke en CORBA-kompatibel model. RMI er native til Java, det vil sige, det er en udvidelse til kernesproget. RMI er helt afhængig af kernen i Java Object Serialization, samt implementering af både portabilitet og mekanismer til ind- og udlæsning af objekter på andre systemer mv.
Brugen af RMI er meget naturlig for enhver Java-programmør, da han ikke behøver at lære en ny teknologi, der er helt anderledes end den, han vil udvikle med. RMI har dog nogle begrænsninger på grund af dens tætte integration med Java, den vigtigste er, at denne teknologi ikke tillader interaktion med applikationer skrevet på et andet sprog.
RMI, som en udvidelse af Java, er en programmeringsteknologi designet til at løse problemer ved at skrive og organisere eksekverbar kode. RMI udgør således et specifikt punkt i programmeringsteknologiernes rum sammen med C, C++, Smalltalk osv.
Den største forskel mellem at bruge RPC og RMI er, at RMI er en mekanisme til fjernprocedurekaldelse baseret på Java-programmeringssproget, der understøtter interaktion mellem objekter, mens RPC ikke understøtter denne funktion.
Arkitektur
RMI-arkitekturen kan ses som en fire-tiers model.
Første lag
Det første lag er applikationslaget og svarer til den faktiske implementering af klient- og serverapplikationerne. Opkald på højt niveau for at få adgang til og eksportere fjernobjekter finder sted her. Ethvert program, der ønsker, at dets metoder skal være tilgængelige for adgang for eksterne klienter, skal deklarere disse metoder i en grænseflade , der udvider java.rmi.Remote. En sådan grænseflade bruges grundlæggende til at "markere" et objekt som fjerntilgængeligt. Når metoderne er implementeret, skal objektet eksporteres. Dette kan gøres implicit, hvis objektet udvider UnicastRemoteObject-klassen (java.rmi.server-pakken), eller det kan gøres eksplicit ved at kalde exportObject()-metoden i den samme pakke.
Andet lag
Lag 2 er proxy-laget, eller stub-skelet-laget. Dette lag er det, der interagerer direkte med applikationslaget. Alle kald til eksterne objekter og handlinger sammen med deres parametre og returobjekter finder sted i dette lag.
Tredje lag
Lag 3 er fjernreferencelaget og er ansvarligt for at håndtere den semantiske del af fjernankaldelser. Det er også ansvarligt for at styre objektreplikering og udføre implementeringsspecifikke opgaver med fjernobjekter, såsom etablering af semantisk persistens og korrekte strategier til at gendanne efter tabte forbindelser. I dette lag forventes en vandløbsorienteret forbindelse fra transportlaget.
Fjerde lag
Lag 4 er transportlaget. Den er ansvarlig for at lave de nødvendige forbindelser og styre transporten af data fra en maskine til en anden. Den underliggende transportprotokol for RMI er Java Remote Method Protocol (JRMP), som kun "forstås" af Java-programmer.
Elementer
Hver RMI-applikation opdeles normalt i 2 dele:
- En server, som opretter nogle eksterne objekter, opretter referencer for at gøre dem tilgængelige og venter på, at klienten kalder dem.
- En klient, som henter en reference til eksterne objekter på serveren og kalder dem.
Eksempel
En RMI-server består af at definere et eksternt objekt, der skal bruges af klienter. For at oprette et eksternt objekt defineres en grænseflade , og fjernobjektet vil være en klasse, der implementerer denne grænseflade. Lad os se, hvordan du opretter en eksempelserver i 3 trin:
- Definer fjerngrænsefladen. Når der oprettes en fjerngrænseflade:
- Grænsefladen skal være offentlig.
- Den skal arve fra java.rmi.Remote-grænsefladen for at indikere, at den kan kaldes fra enhver virtuel Java-maskine.
- Hver fjernmetode skal kaste java.rmi.RemoteException-undtagelsen i sin throws-klausul, ud over eventuelle undtagelser, den kan håndtere.
offentlig grænseflade MyRemoteInterface udvider java . rmi . Remote
{
public void myMethod1 () kaster java . rmi . RemoteException ;
public int myMethod2 () kaster java . rmi . RemoteException ;
}
- Implementer fjerngrænsefladen
public class MyRemoteClass
udvider java . rmi . server . UnicastRemoteObject
implementerer MyRemoteInterface
{
public MyRemoteClass () kaster java . rmi . RemoteException
{
super (); //Kald konstruktøren af basisklassen (UnicastRemoteObject)
// Konstruktørkode
}
public void myMethod1 () kaster java . rmi . RemoteException
{
// Her sætter vi den kode vi ønsker
System . ud . println ( "Jeg er i min Metode1()" );
}
public int myMethod2 () kaster java . rmi . RemoteException
{
return 5 ; // Her sætter vi den kode vi ønsker
}
public void otherMethod ()
{
// Hvis vi definerer en anden metode, kunne den ikke kaldes
// eksternt, da den ikke er fra fjerngrænsefladen
}
public static void main ( String [] args )
{
try
{
MyRemoteInterface mir = new MyRemoteClass ();
java . rmi . Navngivning . rebind ( "rmi://" + java . net . InetAddress . getLocalHost (). getHostAddress () +
":" + args [ 0 ] + "/TestRMI" , mir );
}
catch ( Undtagelse e )
{
e . printStackTrace ();
}
}
}
- Som du kan se, implementerer MyRemoteClass-klassen MyRemoteInterface-grænsefladen, som vi tidligere har defineret. Det arver også fra UnicastRemoteObject, som er en Java-klasse, som vi kan bruge som en superklasse til at implementere fjernobjekter.
- Derefter definerer vi inde i klassen en konstruktør (som kaster RemoteException-undtagelsen, fordi den også kastes af UnicastRemoteObject-superklassen), og metoderne for den eller de grænseflader, den implementerer.
- Til sidst, i hovedmetoden, definerer vi koden for at skabe det eksterne objekt, som vi ønsker at dele, og gøre fjernobjektet synligt for klienter ved at bruge klassen Navngivning og dens rebind(...) metode.
Bemærk: Vi har placeret main()-metoden i samme klasse for nemheds skyld. En separat klasse kunne defineres til at være ansvarlig for registrering af fjernobjektet.
- Kompiler og kør serveren
Vi har allerede defineret serveren. Nu skal vi kompilere dine klasser ved at bruge følgende trin:
- Vi kompilerer fjerngrænsefladen. Derudover grupperer vi den i en JAR-fil for at holde den til stede både på klienten og på serveren:
javac MyRemoteInterface.java jar cvf objRemotes.jar MyRemoteInterface.class
- Dernæst kompilerer vi klasserne, der implementerer grænsefladerne. Og for hver af dem genererer vi Stub- og Skeleton-filerne for at vedligeholde referencen til det eksterne objekt ved hjælp af rmic-kommandoen:
sæt CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;. javac MyRemoteClass.java rmic -d. MyRemoteClass
Vi kan se i vores arbejdsmappe, at to .class-filer er blevet automatisk genereret (MiClaseRemota_Skel.class og MiClaseRemota_Stub.class) svarende til stub-skelet-laget i RMI-arkitekturen.
- For at køre serveren følger vi disse trin:
- RMI-logning startes for at tillade logning og søgning af eksterne objekter. Registret er ansvarlig for at administrere et sæt fjernobjekter, der skal deles, og lede efter dem, når kunderne anmoder om det. Det kører med rmiregistry-applikationen distribueret med Java, som vi eventuelt kan sende porten til at oprette forbindelse til (som standard, 1099).
I tilfælde af Windows skal det udføres:
start rmiregistry 1234
Og i tilfælde af Linux:
rmiregistry &
- Til sidst startes serveren:
java -Djava.rmi.server.hostname=127.0.0.1 MyRemoteClass 1234
- Opret en RMI-klient
Vi skal nu definere en klient, der vil få adgang til det eller de fjernobjekter, vi opretter. Til dette følger vi følgende trin:
- Definer klassen for at få de nødvendige fjernobjekter
Følgende klasse får et objekt af typen MyRemoteInterface, implementeret på vores server:
offentlig klasse MyRMIClient
{
privat MyRMIClient (){};
public static void main ( String [] args )
{
prøv
{
MyRemoteInterface mir = ( MyRemoteInterface ) java . rmi . Navngivning . opslag ( "rmi://" +
args [ 0 ] + ":" + args [ 1 ] + "/RMITest" );
// Udskriv myMethod1() så mange gange som myMethod2() returnerer
for ( int i = 1 ; i <= myr . myMethod2 (); i ++ )
myr . minmetode1 ();
}
catch ( Undtagelse e )
{
e . printStackTrace ();
}
}
}
Som du kan se, består det blot i at lede efter det eksterne objekt i RMI-registret på den eksterne maskine. For at gøre dette bruger vi klassen Navngivning og dens opslag(...) metode.
- Kompiler og kør klienten
Når vi allerede har defineret klienten, gør vi for at kompilere den:
sæt CLASSPATH=%CLASSPATH%;.\Remoteobj.jar;. javac MyRMIClient.java
Så for at køre klienten gør vi:
java MyClientRMI 127.0.0.1 1234
Fjernklassens stubfil skal være tilgængelig. For at gøre dette kopierer vi den enten til klienten og inkluderer den i dens CLASSPATH, eller fjerner den fra serverens CLASSPATH og inkluderer dens sti i serverens java.rmi.codebase (hvis den ikke er fjernet fra serverens CLASSPATH, valgmuligheden java. rmi.codebase, og klienten vil ikke være i stand til at få adgang til stubben). Hvis vi kigger på vinduet, hvor RMI-serveren kører, vil vi se, hvordan fjernobjektet er blevet fundet, og dets metoder er blevet udført:
Se også
Eksterne links
- Enkelt RMI eksempel
- Java RMI tutorial Tutorial fra Sun Microsystems (på engelsk)
- Trail: RMI Java RMI officiel dokumentation
- En oversigt over RMI-applikationer Officiel introduktion til Java RMI-applikationer