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.
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.
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);
}
}
Assemblons maintenant tous ces éléments et implémentons le main() méthode du serveur. Passons en revue chacune des étapes pertinentes.
Greeting greeting =new GreetingObject();
Greeting stub =(Greeting)UnicastRemoteObject.exportObject(greeting, 0);
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 + "\"");
}
}
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
Voyons maintenant comment implémenter le client utilisé pour invoquer les méthodes de l'objet serveur.
Registry Registry =LocateRegistry.getRegistry(host, port );
Greeting greeting =(Greeting) register.lookup(name);
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));
}
}
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
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.
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
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.