__Image Source:
https://upload.wikimedia.org/wikipedia/commons/f/f7/Distributed object communication.png[Wikimedia.org
Dans le lien://java/exemple-java-rmi-bonjour-monde/[exemple Java RMI Bonjour Monde], nous avons présenté le
https://en.wikipedia.org/wiki/Java
remote
method
invocation[Java Remote Method Invocation]avec une base Communication
à base de chaînes
entre serveur-client. Dans cet exemple, nous allons un peu plus loin et introduisons la communication serveur-client en utilisant
https://en.wikipedia.org/wiki/Distributed
object[Objets distribués].
1. L’interface distante
Nous allons d’abord développer la
Interface distante
qui contient toutes les méthodes implémentées par le serveur.
Interface
doit toujours être` public` et étendre
Remote
. Toutes les méthodes décrites dans
Remote Interface
doivent répertorier` RemoteException` dans leur clause throws.
RMIInterface.java
package com.techfou.rmiinterface; import java.rmi.Remote; import java.rmi.RemoteException; import java.util.List; public interface RMIInterface extends Remote { Book findBook(Book b) throws RemoteException; List<Book> allBooks() throws RemoteException; }
2. La classe d’objets distribués
Il s’agit de la classe de l’objet que le serveur et le client échangeront et doit implémenter l’interface sérialisable. Il est également extrêmement important que cette classe déclare une valeur explicite
serialVersionUID
afin de garantir la cohérence entre différentes implémentations du compilateur java.
Si nous l’ignorons ou si la classe d’objets distribués du serveur déclare un
serialVersionUID
différent de la classe d’objets distribués du client, le processus de désérialisation aboutira à une exception` InvalidClassException`.
Sur Eclipse IDE, vous pouvez générer un serialVersionUID comme ceci:
Book.java
package com.techfou.rmiinterface; import java.io.Serializable; public class Book implements Serializable { private static final long serialVersionUID = 1190476516911661470L; private String title; private String isbn; private double cost; public Book(String isbn) { this.isbn = isbn; } public Book(String title, String isbn, double cost) { this.title = title; this.isbn = isbn; this.cost = cost; } public String getTitle() { return title; } public String getIsbn() { return isbn; } public double getCost() { return cost; } public String toString() { return "> " + this.title + " ($" + this.cost + ")"; } }
3. Le serveur
Le serveur étend
UnicastRemoteObject
et implémente le` RMIInterface`. Dans la méthode principale, nous lions le serveur sur localhost avec le nom «MyBookstore». Pour plus de simplicité au lieu d’utiliser une base de données ou un "fichier", nous avons créé la méthode
initializeList ()
qui remplit une
liste
avec des` objets de type livre` représentant les livres que notre librairie a (…
oui seulement 5. Mais 5 livres géniaux!).
Nous devons également ajouter un
serialVersionUID
pour le serveur, mais comme le serveur que nous avons conçu dans cet exemple ne doit exister que sur une machine, nous n’avons pas besoin d’y réfléchir deux fois, nous pouvons simplement définir un` serialVersionUID` par défaut. Si, toutefois, la classe de serveurs était également distribuée, nous devions nous assurer que le
serialVersionUID
de la classe était le même sur toutes les plates-formes qui l’ont implémentée.
Librairie.java
package com.mkyong.rmiserver; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import com.mkyong.rmiinterface.Book; import com.mkyong.rmiinterface.RMIInterface; public class Bookstore extends UnicastRemoteObject implements RMIInterface { private static final long serialVersionUID = 1L; private List<Book> bookList; protected Bookstore(List<Book> list) throws RemoteException { super(); this.bookList = list; } //The client sends a Book object with the isbn information on it //(note: it could be a string with the isbn too) //With this method the server searches in the List bookList //for any book that has that isbn and returns the whole object @Override public Book findBook(Book book) throws RemoteException { Predicate<Book> predicate = x -> x.getIsbn().equals(book.getIsbn()); return bookList.stream().filter(predicate).findFirst().get(); } @Override public List<Book> allBooks() throws RemoteException { return bookList; } private static List<Book> initializeList() { List<Book> list = new ArrayList<>(); list.add(new Book("Head First Java, 2nd Edition", "978-0596009205", 31.41)); list.add(new Book("Java In A Nutshell", "978-0596007737", 10.90)); list.add(new Book("Java: The Complete Reference", "978-0071808552", 40.18)); list.add(new Book("Head First Servlets and JSP", "978-0596516680", 35.41)); list.add(new Book("Java Puzzlers: Traps, Pitfalls, and Corner Cases", "978-0321336781", 39.99)); return list; } public static void main(String[]args) { try { Naming.rebind("//localhost/MyBookstore", new Bookstore(initializeList())); System.err.println("Server ready"); } catch (Exception e) { System.err.println("Server exception: " + e.getMessage()); } } }
4. Le client
Le client "recherche" le serveur via "l’objet RMIInterface" qui "recherche" une référence à l’objet distant associé au nom que nous passons en tant que paramètre. Ce que nous venons de décrire est ce que fait Naming.lookup ("//localhost/MyBookstore"); `.
Le reste du code pour le client consiste simplement à créer un exemple de travail que vous pourriez expérimenter avec espoir.
Client.java
package com.mkyong.rmiclient; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.util.List; import java.util.NoSuchElementException; import javax.swing.JOptionPane; import com.mkyong.rmiinterface.Book; import com.mkyong.rmiinterface.RMIInterface; public class Customer { private static RMIInterface look__up; public static void main(String[]args) throws MalformedURLException, RemoteException, NotBoundException { look__up = (RMIInterface) Naming.lookup("//localhost/MyBookstore"); boolean findmore; do { String[]options = {"Show All", "Find a book", "Exit"}; int choice = JOptionPane.showOptionDialog(null, "Choose an action", "Option dialog", JOptionPane.DEFAULT__OPTION, JOptionPane.INFORMATION__MESSAGE, null, options, options[0]); switch (choice) { case 0: List<Book> list = look__up.allBooks(); StringBuilder message = new StringBuilder(); list.forEach(x -> { message.append(x.toString() + "\n"); }); JOptionPane.showMessageDialog(null, new String(message)); break; case 1: String isbn = JOptionPane.showInputDialog("Type the isbn of the book you want to find."); try { Book response = look__up.findBook(new Book(isbn)); JOptionPane.showMessageDialog(null, "Title: " + response.getTitle() + "\n" + "Cost: $" + response.getCost(), response.getIsbn(), JOptionPane.INFORMATION__MESSAGE); } catch (NoSuchElementException ex) { JOptionPane.showMessageDialog(null, "Not found"); } break; default: System.exit(0); break; } findmore = (JOptionPane.showConfirmDialog(null, "Do you want to exit?", "Exit", JOptionPane.YES__NO__OPTION) == JOptionPane.NO__OPTION); } while (findmore); } }
5. Comment l’exécuter
5.1 Après avoir créé les quatre fichiers java avec votre IDE préféré ou téléchargé le code ci-dessous, accédez au dossier source comme indiqué ci-dessous.
5.2 La première chose à faire est de compiler nos sources. Run
1. compileEverything.bat
si vous avez téléchargé le code ci-dessous ou ouvrez une fenêtre de commande dans votre répertoire et exécutez:
Terminal
$ javac src/com/mkyong/rmiinterface/RMIInterface.java src/com/mkyong/rmiinterface/Book.java src/com/mkyong/rmiserver/Bookstore.java src/com/mkyong/rmiclient/Customer.java
5.3 Confirmez que vos sources ont été compilées en accédant à leurs répertoires respectifs:
5.4 Ensuite, nous devons commencer la chimie. Encore une fois soit exécuter le
2. startServer.bat
ou ouvrez une fenêtre de commande et exécutez:
Terminal
$ cd src $ start rmiregistry $ java com.mkyong.rmiserver.Bookstore
5.5 Si RmiRegistry a démarré avec succès, une autre fenêtre ressemblant à ceci:
5.6 Nous sommes maintenant prêts à exécuter notre client:
Ouvrez une nouvelle fenêtre d’invite de commande (ou exécutez le fichier
3. runClient.bat
à partir des fichiers téléchargés) et exécutez ceci:
Terminal
$ cd src $ java com.mkyong.rmiclient.Customer
5.6.1 La
classe client
s’exécute et nous invite à l’action:
5.6.2 Lorsque nous cliquons sur le bouton “Afficher tout”:
5.6.3 Après avoir cliqué sur le bouton “OK”:
5.6.4 Nous cliquons sur le bouton “Non”, car nous ne voulons pas encore quitter et la boîte de dialogue suivante apparaît. Nous tapons un ISBN (ex. «978-0596009205») et cliquez sur «OK».
5.6.5 Si le livre a été trouvé dans la liste du serveur:
5.6.6 S’il n’a pas été trouvé:
5.6.7 Le programme continuera en nous demandant:
Si nous cliquons sur le bouton “Oui”, le programme se fermera. Si nous cliquons sur «Non», nous reviendrons au menu principal pour choisir une action, comme indiqué en 5.6.1.
Le serveur continuera à fonctionner jusqu’à la fermeture de sa fenêtre. Même après la fermeture du client, nous pouvons en ouvrir un nouveau ou même plusieurs clients exécutés simultanément.
Télécharger le code source
Téléchargement - lien://wp-content/uploads/2017/01/RMIObjects.zip[RMIObjects.zip](5 KB)
Références
Interface - API Java]. https://docs.oracle.com/javase/8/docs/api/java/rmi/Remote.html [Remote
Exemple]. https://en.wikipedia.org/wiki/Java remote method__invocation[Wikipedia
-
Invocation de méthode à distance Java]. https://en.wikipedia.org/wiki/Distributed__object [Wikipedia -
Objets distribués]
lien://étiquette/objet distribué/[objet distribué]lien://étiquette/rmi/[rmi]