Ce serait plus simple si tous les composants étaient exécutés sur le même espace de tas de la même machine virtuelle Java sur le même ordinateur, mais dans la pratique, nous ne sommes souvent pas confrontés à une telle situation si le client n'est qu'un périphérique capable d'exécuter Java. faire? Et si, pour des raisons de sécurité, seuls les programmes du serveur pouvaient accéder à la base de données ?
Nous savons que dans la plupart des cas, les appels de méthodes se produisent entre deux objets sur le même tas. Que faire si vous souhaitez appeler des méthodes sur des objets sur des machines différentes ?
Habituellement, nous obtenons des informations d'un ordinateur à un autre ordinateur via le flux d'entrée/sortie du socket, ouvrons la connexion socket de l'autre ordinateur, puis obtenons le outputStream pour écrire les données. Mais si nous voulons appeler un autre ordinateur sur votre. ordinateur, quelles sont les méthodes des objets sur une autre machine virtuelle Java ? Bien sûr, nous pouvons définir et concevoir nous-mêmes le protocole de communication à appeler, puis transmettre les résultats d'exécution via Socket, et cela peut également être comme appeler des méthodes sur la machine locale, c'est-à-dire si nous voulons appeler des objets distants (tels que comme les autres tas) ), mais cela devrait être comme un appel normal.
C'est ce que nous apporte RMI.
La conception des appels de procédures à distance
Il y a 4 choses à créer : serveur, client, installations auxiliaires du serveur et installations auxiliaires du client.
1. Créez des applications client et serveur L'application serveur est un service distant, un objet avec des méthodes que le client appellera.
2. Créez des assistants côté client et serveur. Ils géreront tous les détails d'entrée/sortie réseau sous-jacents du client et du serveur, donnant l'impression que le client et le programme traitent les appels locaux.
Tâches des installations auxiliaires Les installations auxiliaires sont des objets qui effectuent réellement la communication. Elles donnent au client l'impression qu'il appelle un objet local. L'objet client semble appeler une méthode distante, mais en fait, il appelle simplement une méthode A. proxy qui gère les détails du socket et du streaming localement Du côté du serveur, les installations auxiliaires du serveur se connecteront via le socket. La requête de l'installation client analyse les informations packagées puis appelle le service réel, de sorte que l'appel est local à l'objet de service. Une fois que l'installation auxiliaire du service a obtenu la valeur de retour, elle l'encapsule et la renvoie (via le flux de sortie du socket. ) à l'assistant du client. L'assistant du client décompressera les informations et les transférera vers l'objet client.
Le processus d’appel d’une méthode
1. L'objet client appelle doBigThing() sur l'objet installation auxiliaire
2. Les installations auxiliaires du client regroupent les informations d'appel et les envoient aux installations auxiliaires du serveur via le réseau.
3. L'outil auxiliaire côté serveur décode les informations provenant de l'outil auxiliaire côté client et les utilise pour appeler le service réel.
Le schéma décrivant ce processus est le suivant :
JavaRMI fournit des objets d'assistance côté client et côté serveur
En Java, RMI nous a aidé à créer des fonctionnalités auxiliaires côté client et côté serveur. Il sait également comment faire ressembler les fonctionnalités auxiliaires côté client à de vrais services. En d'autres termes, RMI sait fournir les mêmes méthodes pour les appels clients. .
De plus, RMI fournit toute l'infrastructure nécessaire à l'exécution, y compris les requêtes de service et les fonctionnalités auxiliaires qui permettent aux clients de trouver et d'obtenir des clients (de vrais agents de service).
Lors de l'utilisation de RMI, il n'est pas nécessaire d'écrire des programmes réseau ou d'entrée/sortie. L'appel du client à une méthode distante est identique à un appel de méthode sur la même machine virtuelle Java.
Les appels généraux sont un peu différents des appels RMI. Bien que pour le client, cet appel de méthode semble local, mais l'installation auxiliaire du client effectuera l'appel via le réseau. Cet appel impliquera éventuellement des sockets et des flux. et l'agent le convertira en information distante. La manière dont les informations intermédiaires sont envoyées de la machine virtuelle Java à la machine virtuelle Java dépend du protocole utilisé par l'objet d'installation auxiliaire.
Lorsque vous utilisez RMI, vous devez décider du protocole : JRMP ou IIOP est le protocole natif de RMI. Il est conçu pour les appels à distance entre Java. Par contre, IIOP est produit pour CORBA, ce qui nous permet d'appeler Java. Pour les objets ou d'autres types de méthodes distantes, CORBA est généralement plus gênant que RMI, car si les deux extrémités ne sont pas Java, de nombreuses opérations de traduction et de conversation terribles se produiront.
Nous ne nous soucions que des opérations Java vers Java, nous utiliserons donc une RMI assez simple.
Dans RMI, les fonctionnalités auxiliaires côté client sont appelées stubs et les fonctionnalités auxiliaires côté serveur sont appelées squelettes.
Comment créer un service distant
1.Créer une interface distante
L'interface distante définit les méthodes que le client peut appeler à distance. Il s'agit d'une classe polymorphe en tant que service. Le stub et le service implémenteront cette interface.
2. Implémentez l'interface distante
Il s'agit de la classe d'exécution réelle. Elle implémente les méthodes définies sur l'interface. C'est l'objet que le client appellera.
3. Utilisez rmic pour générer un stub et un squelette
Le client et le serveur ont des assistants. Nous n'avons pas besoin de créer ces classes ou de générer le code source de ces classes. Cela sera automatiquement géré lors de l'exécution de l'outil rmic attaché au JDK.
4. Démarrez RMIregistry (rmiregistry)
rmiregistry est comme un annuaire téléphonique, l'utilisateur obtiendra le proxy (l'objet stub/helper du client) à partir d'ici
5. Démarrez le service à distance
L'objet de service doit commencer à s'exécuter. La classe qui implémente le service démarrera l'instance de service et l'enregistrera auprès de RMIRegistry. Ce n'est qu'après l'enregistrement qu'elle pourra servir l'utilisateur.
Code du serveur
Définir l'interface
/**
*
*MaRemote.java
*
* Fonction : À FAIRE
* Nom de la classe : MyRemote.java
*
* ver. Support de personnage mis à jour et nouveau contenu.
*──────────────────────────────────────── ────
* V1.00 2013-3-19 Première version du module Su Ruo
*
* Copyright (c) 2013 Dennisit Corporation Tous droits réservés.
*
* E-mail :<a href="mailto:[email protected]">Envoyer un e-mail</a>
*
*
* Remote est une interface marquée, ce qui signifie qu'il n'y a pas de méthodes. Cependant, elle a une signification particulière pour RMI, cette règle doit donc être suivie.
* Notez que extends est utilisé ici et que les interfaces peuvent hériter d'autres interfaces.
*
*/
l'interface publique MyRemote étend Remote{
/**
* L'interface distante définit les méthodes que le client peut appeler à distance. C'est une classe polymorphe en tant que service.
* Mobilisez le stub qui implémente cette interface, et comme ce stub effectuera le travail de réseau et d'entrée/sortie, diverses choses peuvent arriver
* Problème, le client gère ou déclare des exceptions pour reconnaître ce type de risque. Si la méthode déclare une exception dans l'interface, appelez la méthode.
* Toutes les procédures doivent gérer ou redéclarer cette exception.
*
* Les paramètres et les valeurs de retour des méthodes distantes doivent être primitifs ou sérialisables. Tous les paramètres des méthodes distantes le seront.
* Le package est transmis via le réseau et lorsqu'il est terminé par sérialisation, la valeur de retour est la même, par conséquent, si un type personnalisé est utilisé.
*, il doit être sérialisé
* @retour
* @throws RemoteException
* Toutes les méthodes de l'interface doivent déclarer RemoteException
*/
public String sayHello() lève RemoteException ;
}
/**
*
*MyRemoteImpl.java
*
* Fonction : À FAIRE
* Nom de la classe : MyRemoteImpl.java
*
* ver. Support de personnage mis à jour et nouveau contenu.
*──────────────────────────────────────── ────
* V1.00 2013-3-19 Première version du module Su Ruo
*
* Copyright (c) 2013 Dennisit Corporation Tous droits réservés.
*
* E-mail :<a href="mailto:[email protected]">Envoyer un e-mail</a>
*
* Pour devenir un objet de service distant, l'objet doit avoir des fonctions liées à la distance. La méthode la plus simple consiste à hériter d'UnicastRemoteObject.
* (depuis java.rmi.server) pour laisser cette classe parent gérer le travail
*
*/
la classe publique MyRemoteImpl étend UnicastRemoteObject implémente MyRemote{
/**
* Le constructeur de la classe parent déclare une exception, vous devez donc écrire le constructeur car cela signifie que votre constructeur appellera du code de programme à risque
*
* UnicastRemoteObject a un petit problème, son constructeur lance RemoteException. La seule façon de le gérer est.
* Déclarez un constructeur pour votre propre implémentation afin qu'il y ait un endroit pour déclarer RemoteException. Lorsque la classe est initialisée, la classe parent.
* Le constructeur sera définitivement appelé. Si le constructeur de la classe parent lève une exception, le constructeur personnalisé que nous devons également déclarer lèvera une exception.
* @throws RemoteException
*/
protected MyRemoteImpl() lance RemoteException {
}
/**
* Implémentez toutes les méthodes de l'interface sortante, mais n'avez pas besoin de déclarer RemoteException
*/
@Outrepasser
chaîne publique sayBonjour(){
return "le serveur dit, rmi hello world!";
}
public static void main (String[] arguments) {
essayer {
/**
* Nous disposons déjà d'un service distant et nous devons permettre aux utilisateurs distants d'y accéder. Cela peut être fait en l'initialisant et en l'ajoutant au registre RMI.
* (Il doit être en cours d'exécution, sinon ce programme échouera). Lors de l'enregistrement d'un objet, le système RMI ajoutera le stub au registre,
* Parce que c'est ce dont le client a besoin. Utilisez rebind() de java.rmi.Naming pour enregistrer le service.
*/
Service MyRemote = new MyRemoteImpl();
/**
* Créez un objet distant, puis utilisez static Naming.rebind() pour créer une association. Le nom enregistré sera fourni pour la requête du client.
*/
Naming.rebind("Remote Hello World", service);
} attraper (Exception e) {
e.printStackTrace();
}
}
}
public void exec(){
essayer {
/**
* Le client doit obtenir l'objet stub car il doit appeler sa méthode. Cela dépend du registre RMI. Le client interrogera le téléphone.
* Recherchez dans le même répertoire pour trouver des services dont les noms correspondent.
* Le client interroge RMIRegistry et renvoie l'objet stub
* Naming.lookup("rmi://127.0.0.1/Remote Hello World");
*Description des paramètres
* rmi://127.0.0.1/Remote Bonjour Monde
* 127.0.0.1 représente le nom d'hôte ou l'adresse IP de l'hôte
* Remote Hello World doit être le même que le nom enregistré
*
*/
Service MyRemote = (MyRemote)Naming.lookup("rmi://127.0.0.1/Remote Hello World");
String tmp = service.sayHello();
System.out.println(tmp);
} attraper (Exception e) {
e.printStackTrace();
}
}
public static void main (String[] arguments) {
new MyRemoteClient().exec();
}
}
L'outil rmic fourni avec le JDK générera deux classes, stub et skeleton, en fonction de l'implémentation du service. Il ajoutera _Stub ou _Skeleton après le nom de l'implémentation distante selon les règles de dénomination. rmic a plusieurs options, notamment ne pas générer de squelettes, observer le code source des classes générées ou utiliser IIOP comme protocole de communication. Les classes générées seront placées dans le répertoire courant. N'oubliez pas que rmic doit pouvoir trouver les classes implémentées. Par conséquent, vous devrez peut-être exécuter rmic à partir du répertoire où se trouve l'implémentation (en pratique, vous devrez peut-être prendre en compte la structure du répertoire du package et son nom complet, pour plus de simplicité, le package n'est pas utilisé ici)
Appelez la ligne de commande pour démarrer rmiregistry. Assurez-vous de le démarrer à partir d'un répertoire pouvant accéder à la classe. Le moyen le plus simple est de l'exécuter à partir du répertoire de la classe.
La capture d'écran en cours d'exécution est la suivante
Avis:
Le client utilise l'interface pour appeler la méthode sur le stub. La machine virtuelle Java du client doit avoir une classe stub, mais le client ne fera pas référence à la classe stub dans le code du programme. Le client exploite toujours le véritable objet distant via l'interface.
Le serveur doit avoir des stubs et des squelettes, ainsi que des interfaces de service et distantes. Il nécessite la classe stub car le stub sera remplacé par le service réel connecté à RMIRegistry.
Erreurs courantes lors de l'utilisation de RMI :
1. J'ai oublié de démarrer rmiregistry avant de démarrer le service distant (rmiregistry doit être démarré avant d'utiliser Naming.rebind() pour enregistrer le service)
2. J'ai oublié de rendre les paramètres et les types de retour sérialisables (cela ne sera pas détecté lors de la compilation et ne sera découvert que lors de l'exécution)
3. Oubliez de remettre la classe stub au client
RMI est très approprié pour écrire et exécuter des services à distance, mais nous n'utiliserons pas RMI seul pour exécuter des services de sites Web. Pour les applications à grande échelle au niveau de l'entreprise, nous avons besoin de fonctions plus nombreuses et de meilleure qualité. et la sécurité et la gestion de bases de données, etc. Cela nécessite l'utilisation d'EnterpriseApplicationServer.
Le serveur JavaEE comprend un serveur Web et un serveur Enterprise JavaBeans (EJB). Le serveur EJB agit entre les appels RMI et la couche de service.
Application du RMI dans JINI
Jini utilise également RMI (bien que d'autres protocoles puissent également être utilisés), mais il possède plusieurs fonctions clés supplémentaires.
1. Découverte adaptative
2. Réseaux d'auto-guérison
Le client RMI doit d'abord obtenir l'adresse et le nom du service distant. Le code du programme de requête du client doit contenir l'adresse IP ou le nom d'hôte du service distant (car RMIRegistry s'y trouve) et le nom enregistré par le service.
Mais lorsqu'ils utilisent JINI, les utilisateurs n'ont besoin de connaître qu'une chose, l'interface implémentée par le service.
Jini utilise un service de recherche, qui est plus puissant et plus adaptable que RMIRegistry, car Jini fera automatiquement de la publicité sur le réseau lorsque le service de requête sera mis en ligne, il utilisera la technologie de multidiffusion IP pour envoyer des informations à l'ensemble du réseau. est mis en ligne après la diffusion du service de requête, et le client peut également envoyer des messages à l'ensemble du réseau pour se renseigner.
Lorsque le service sera mis en ligne, il explorera dynamiquement le service de requête JINI sur le réseau et demandera l'enregistrement. Lors de l'enregistrement, le service enverra un objet sérialisé au service de requête. Cet objet peut être le stub du service distant RMI ou le. pilote du périphérique réseau. , ou même le service lui-même qui peut être exécuté sur le client. Et ce qui est enregistré, c'est l'interface implémentée.
Comment fonctionne l'exploration adaptative
1.Le service de requête Jini démarre sur le réseau et utilise la technologie de multidiffusion IP pour se promouvoir
2. Un autre service Jini qui a été démarré cherchera à s'enregistrer auprès du service de requête nouvellement démarré. Il enregistre la fonction plutôt que le nom, c'est-à-dire l'interface implémentée, puis envoie l'objet sérialisé au service de requête.
3. Les clients Internet veulent obtenir quelque chose pour implémenter ScientificCalculator, mais ils ne savent pas où le trouver, alors ils demandent au service de requête
4. Le service de requête répond aux résultats de la requête
Fonctionnement d'un réseau d'auto-guérison
1. Un certain service Jini nécessite un enregistrement et le service de requête accordera un bail. Les services nouvellement enregistrés doivent renouveler le bail régulièrement. Sinon, le service de requête supposera que le service est hors ligne. état complet du réseau de service disponible.
2. Le service est hors ligne en raison d'un arrêt, le bail n'est donc pas mis à jour et le service de requête est lancé.