FRFAM.COM >> Famille >> Technologie &Innovation >> Informatique

Tout sur le registre Java RMI et comment l'utiliser

IRM signifie invocation de méthode distante et, comme son nom l'indique, est un protocole permettant à un programme Java d'invoquer une méthode d'un objet s'exécutant sur un autre ordinateur. Il fournit une API (Application Programming Interface) pour exporter un objet à partir d'un programme (appelé le serveur) et invoquer les méthodes de cet objet à partir d'un autre programme (appelé le client), éventuellement exécuté sur un autre ordinateur.

Le registre RMI Java est un composant clé du système Java RMI et fournit un répertoire centralisé permettant aux serveurs d'enregistrer les services et aux clients de rechercher ces services. Dans cet article, nous apprenons à implémenter un serveur pour exposer un objet et un client pour invoquer une méthode sur le serveur, ainsi qu'enregistrer et rechercher le service dans le registre RMI.

Tout sur le registre Java RMI et comment l utiliser

Déclaration de l'interface serveur

Pour apprendre les subtilités du fonctionnement du système Java RMI, implémentons un objet serveur simple fournissant une méthode pour accepter un nom et renvoyer un message d'accueil. Voici la définition de l'interface de l'objet :

importer java.rmi.Remote ; 
import java.rmi.RemoteException ;
interface publique Le message d'accueil s'étend à distance
{
public String greet(String name) lève RemoteException ;
}

Le nom de l'interface s'appelle Message d'accueil . Il fournit une seule méthode appelée greet() qui accepte un nom et renvoie une salutation appropriée.

Pour marquer cette interface comme exportable, elle doit étendre le java.rmi.Remote interface. De plus, la méthode doit déclarer un throws liste de clauses java.rmi.RemoteException en plus de toute exception spécifique à l'application. C'est ainsi que le code client peut gérer (ou propager) les erreurs d'invocation de méthode distante telles que host-not-found , échec-de-connexion , etc.

Implémentation de l'objet serveur

Après avoir déclaré l'interface (qui est utilisée par les clients), nous implémentons l'objet côté serveur et fournissons le greet() méthode comme indiqué. Il utilise une chaîne de format simple pour formater le message d'accueil.

classe publique GreetingObject implémente Greeting 
{
chaîne privée fmtString ="Bonjour, %s" ;
public String greet (nom de la chaîne)
{
return String.format(this.fmtString, name);
}
}

La méthode principale du serveur

Assemblons maintenant tous ces éléments et implémentons le main() méthode du serveur. Passons en revue chacune des étapes pertinentes.

  • La première étape consiste à créer l'implémentation de l'objet serveur.
    Greeting greeting =new GreetingObject(); 
  • Ensuite, nous obtenons un stub pour l'objet serveur à partir du runtime RMI. Le stub implémente la même interface que l'objet serveur. Cependant, le procédé implémente la communication requise avec l'objet serveur distant. Ce stub est utilisé par le client pour invoquer de manière transparente la méthode sur l'objet serveur.
    Greeting stub =(Greeting)UnicastRemoteObject.exportObject(greeting, 0); 
  • Une fois le stub obtenu, nous transmettons ce stub au registre RMI pour le lier à un service nommé spécifié. Lorsque le client demande une implémentation de ce service, il reçoit le stub qui sait comment communiquer avec l'objet serveur. Dans ce qui suit, la méthode statique LocateRegistry.getRegistry() est utilisé pour obtenir la référence du registre local. Le relier() est ensuite utilisée pour lier le nom au stub.
    String name ="Greeting" ; 
    Registre du registre =LocateRegistry.getRegistry(port);
    register.rebind(nom, stub);

La méthode principale complète.

importer java.rmi.registry.LocateRegistry ; 
import java.rmi.registry.Registry ;
importer java.rmi.server.UnicastRemoteObject ;
classe publique principale
{
static public void main(String[] args) lance une exception
{
si ( args.length ==0 ) {
System.err.println("utilisation :port principal java#");
System.exit(1);
}
index entier =0 ;
int port =Integer.parseInt(args[index++]);
Nom de chaîne ="Salutation" ;
Salutation salutation =new GreetingObject();
Stub de salutation =(Greeting)UnicastRemoteObject.exportObject(salutation, 0);
Registre du registre =LocateRegistry.getRegistry(port);
register.rebind(nom, stub);
System.out.println("Salut lié à \"" + nom + "\"");
}
}

Construire le serveur

Penchons-nous maintenant sur la construction du serveur. Pour garder les choses simples, nous construisons en utilisant la ligne de commande sous Linux plutôt qu'en utilisant un outil de construction tel que Maven.

Ce qui suit compile les fichiers source en fichiers de classe dans un répertoire cible.

rm -rf cible 
cible mkdir
javac -d cible src/serveur/*.java

Rassemblez les fichiers de classe dans un fichier JAR pour l'exécution.

jar cvf cible/rmi-server.jar -C cible serveur 

Nous collectons également les fichiers d'interface nécessaires à la compilation du client dans une bibliothèque JAR.

jar cvf cible/rmi-lib.jar -C cible serveur/Greeting.class 

Implémentation du client

Voyons maintenant comment implémenter le client utilisé pour invoquer les méthodes de l'objet serveur.

  • Comme pour le serveur, obtenez une référence au registre, en spécifiant le nom d'hôte sur lequel le registre s'exécute et le numéro de port.
    Registry Registry =LocateRegistry.getRegistry(host, port ); 
  • Ensuite, recherchez le service dans le registre. La recherche() renvoie un stub qui peut être utilisé pour appeler des services.
    Greeting greeting =(Greeting) register.lookup(name); 
  • Et invoquez la méthode en passant les arguments requis. Ici, nous obtenons le message d'accueil en passant le nom et en l'imprimant.

Le code client complet :

client de package ; 
importer java.rmi.registry.LocateRegistry ;
import java.rmi.registry.Registry ;
serveur d'importation.
Client de classe publique
{
static public void main(String[] args) lance une exception
{
si ( args.longueur !=3 ) {
System.err.println("utilisation :port hôte client java monNom");
System.exit(1);
}
index entier =0 ;
Chaîne host =args[index++] ;
int port =Integer.parseInt(args[index++]);
String myName =args[index++] ;
Nom de chaîne ="Salutation" ;
Registre du registre =LocateRegistry.getRegistry (hôte, port);
Salutation salutation =(salutation)registre.lookup(nom);
System.out.println(name + " signalé :" + greeting.greet(myName));
}
}

Le registre RMI

Exécutons maintenant le programme serveur afin qu'il puisse commencer à traiter les requêtes.

java -cp cible/rmi-server.jar server.Main 1099 
# lancers
Exception dans le thread "main" java.rmi.ConnectException :Connexion refusée à l'hôte :xxx ; l'exception imbriquée est :
java.net.ConnectException :connexion refusée

Quelle est cette dérogation ? Connexion refusée .

La raison pour laquelle vous obtenez cette exception est la suivante :notez dans le code du serveur qu'il tente de se connecter au registre local sur le port 1099. Si cela échoue, vous vous retrouvez avec cette exception.

La solution consiste à exécuter le registre RMI. Le registre RMI est un programme fourni avec la machine virtuelle Java et s'appelle rmiregistry . Il devrait être situé dans le bin répertoire d'installation de la machine virtuelle Java. L'exécuter est aussi simple que :

/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 

Par défaut, le registre écoute sur le port 1099. Pour qu'il écoute sur un autre port, spécifiez le numéro de port comme suit :

/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100 

Vérifiez qu'il y a bien un listener sur le port spécifié avec la commande netstat :

netstat -an -t tcp -p | grep ECOUTER 
...
tcp6 0 0 :::1100 :::* ÉCOUTEZ 23450/rmiregistry

Exécuter le serveur

Essayons maintenant de relancer le serveur.

java -cp cible/rmi-server.jar server.Main 1100 
# lancers
java.rmi.UnmarshalException :erreur lors du désassemblage des arguments
...
Causé par :java.lang.ClassNotFoundException : server.Greeting
...

Une exception encore ! Qu'y a-t-il cette fois ?

Le serveur ne parvient pas à charger la classe d'interface server.Greeting . Cela se produit car le registre RMI n'est pas en mesure de charger la classe requise. Vous devez donc spécifier l'emplacement des classes requises. Une façon de le faire est de spécifier la variable d'environnement CLASSPATH :

CLASSPATH=../../junk/target/rmi-lib.jar /usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100 

Essayer de relancer le serveur donne :

java -cp cible/rmi-server.jar server.Main 1100 
# impressions
Message d'accueil lié à "Message d'accueil"

Maintenant, le serveur est en cours d'exécution.

Exécuter le client

Une fois toutes les pièces assemblées et exécutées, l'exécution du client est simple. Il a besoin des fichiers JAR appropriés pour l'exécution. Ceux-ci incluent la classe contenant le main() méthode et la classe d'interface. Il accepte des arguments indiquant où le registre RMI s'exécute et un nom pour le message d'accueil.

java -cp target/rmi-client.jar:target/rmi-lib.jar client.Client localhost 1100 Pierre 
# impressions
Message d'accueil signalé :Bonjour, Pierre

Résumé

Java RMI fournit une API et des outils pour faciliter l'exécution de code à distance. Vous pouvez implémenter un serveur qui enregistre un objet de service auprès du registre Java RMI. Les clients peuvent interroger le registre et obtenir un stub d'objet de service pour appeler les méthodes de service. Comme cet exemple l'illustre, tout est assez simple.

Utilisez-vous Java RMI dans votre projet ? Quelle a été votre expérience? Y a-t-il des alternatives que vous avez étudiées? Veuillez nous en informer dans les commentaires ci-dessous.


[]