Introduction Ce document est un support de cours : ce n'est pas un cours complet. Des approfondissements ncessitent l'aide d'un enseignant. L'tudiant y trouvera cependant une grande quantit d'informations lui permettant la plupart du temps de travailler seul. Ce document comporte probablement des erreurs : toute suggestion constructive est la bienvenue l'adresse serge.tahe@istia.univangers.fr. Il existe d'excellents livres sur Java. Parmi ceux-ci : 1. Programmer en Java de Claude Delannoy aux ditions Eyrolles 2. Java client-serveur de Cdric Nicolas, Christophe Avare, Frdric Najman chez Eyrolles. Le premier livre est un excellent ouvrage d'introduction pdagogique au langage Java. Une fois acquis son contenu, on pourra passer au second ouvrage qui prsente des aspects plus avancs de Java (Java Beans, JDBC, Corba/Rmi). Il prsente une vue industrielle de Java intressante. Pour approfondir Java dans diffrents domaines, on pourra se rfrer la collection "Java series" chez O'Reilly. Pour une utilisation professionnelle de Java au sein d'une plate-forme J2EE on pourra lire : 3. Programmation j2EE aux ditions Wrox et distribu par Eyrolles.
I - Les bases du langage Java................................................................................................................................... 8 I-A - Introduction.................................................................................................................................................... 8 I-B - Les donnes de Java....................................................................................................................................8 I-B-1 - Les types de donnes prdfinis..........................................................................................................9 I-B-2 - Notation des donnes littrales............................................................................................................ 9 I-B-3 - Dclaration des donnes...................................................................................................................... 9 I-B-3-a - Rle des dclarations...................................................................................................................9 I-B-3-b - Dclaration des constantes........................................................................................................ 10 I-B-3-c - Dclaration des variables........................................................................................................... 10 I-B-4 - Les conversions entre nombres et chanes de caractres................................................................. 10 I-B-5 - Les tableaux de donnes................................................................................................................... 12 I-C - Les instructions lmentaires de Java........................................................................................................13 I-C-1 - Ecriture sur cran............................................................................................................................... 13 I-C-2 - Lecture de donnes tapes au clavier............................................................................................... 14 I-C-3 - Exemple d'entres-sorties...................................................................................................................15 I-C-4 - Affectation de la valeur d'une expression une variable................................................................... 16 I-C-4-a - Interprtation de l'opration d'affectation................................................................................... 16 I-C-4-b - Expression arithmtique............................................................................................................. 16 I-C-4-c - Priorits dans l'valuation des expressions arithmtiques......................................................... 17 I-C-4-d - Expressions relationnelles..........................................................................................................17 I-C-4-e - Expressions boolennes............................................................................................................ 19 I-C-4-f - Traitement de bits....................................................................................................................... 19 I-C-4-g - Combinaison d'oprateurs..........................................................................................................19 I-C-4-h - Oprateurs d'incrmentation et de dcrmentation................................................................... 20 I-C-4-i - L'oprateur ?................................................................................................................................20 I-C-4-j - Priorit gnrale des oprateurs.................................................................................................20 I-C-4-k - Les changements de type.......................................................................................................... 21 I-D - Les instructions de contrle du droulement du programme......................................................................21 I-D-1 - Arrt.................................................................................................................................................... 21 I-D-2 - Structure de choix simple................................................................................................................... 21 I-D-3 - Structure de cas................................................................................................................................. 22 I-D-4 - Structure de rptition........................................................................................................................ 23 I-D-4-a - Nombre de rptitions connu.....................................................................................................23 I-D-4-b - Nombre de rptitions inconnu.................................................................................................. 24 I-E - La structure d'un programme Java............................................................................................................. 26 I-F - La gestion des exceptions...........................................................................................................................27 I-G - Compilation et excution d'un programme Java.........................................................................................30 I-H - Arguments du programme principal............................................................................................................ 31 I-I - Passage de paramtres une fonction....................................................................................................... 31 I-J - L'exemple impots......................................................................................................................................... 32 II - Classes et interfaces........................................................................................................................................... 36 II-A - L' objet par l'exemple................................................................................................................................. 36 II-A-1 - Gnralits......................................................................................................................................... 36 II-A-2 - Dfinition de la classe personne....................................................................................................... 36 II-A-3 - La mthode initialise.......................................................................................................................... 37 II-A-4 - L'oprateur new................................................................................................................................. 38 II-A-5 - Le mot cl this................................................................................................................................... 39 II-A-6 - Un programme de test.......................................................................................................................39 II-A-7 - Une autre mthode initialise.............................................................................................................. 41 II-A-8 - Constructeurs de la classe personne................................................................................................ 42 II-A-9 - Les rfrences d'objets......................................................................................................................43 II-A-10 - Les objets temporaires.....................................................................................................................44 II-A-11 - Mthodes de lecture et d'criture des attributs privs..................................................................... 45 II-A-12 - Les mthodes et attributs de classe................................................................................................46 II-A-13 - Passage d'un objet une fonction.................................................................................................. 47 II-A-14 - Encapsuler les paramtres de sortie d'une fonction dans un objet................................................. 48 II-A-15 - Un tableau de personnes................................................................................................................ 49 II-B - L'hritage par l'exemple............................................................................................................................. 49
-2Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
II-B-1 - Gnralits......................................................................................................................................... 49 II-B-2 - Construction d'un objet enseignant....................................................................................................51 II-B-3 - Surcharge d'une mthode..................................................................................................................52 II-B-4 - Le polymorphisme..............................................................................................................................53 II-B-5 - Surcharge et polymorphisme............................................................................................................. 53 II-C - Classes internes......................................................................................................................................... 55 II-D - Les interfaces............................................................................................................................................. 56 II-E - Classes anonymes..................................................................................................................................... 60 II-F - Les paquetages.......................................................................................................................................... 63 II-F-1 - Crer des classes dans un paquetage.............................................................................................. 63 II-F-2 - Recherche des paquetages............................................................................................................... 67 II-G - L'exemple IMPOTS.................................................................................................................................... 70 III - Classes d'usage courant.................................................................................................................................... 74 III-A - La documentation...................................................................................................................................... 74 III-B - Les classes de test................................................................................................................................... 76 III-C - La classe String.........................................................................................................................................77 III-D - La classe Vector........................................................................................................................................79 III-E - La classe ArrayList.................................................................................................................................... 81 III-F - La classe Arrays........................................................................................................................................ 82 III-G - La classe Enumeration............................................................................................................................. 87 III-H - La classe Hashtable..................................................................................................................................88 III-I - Les fichiers texte.........................................................................................................................................90 III-I-1 - Ecrire.................................................................................................................................................. 90 III-I-2 - Lire......................................................................................................................................................91 III-I-3 - Sauvegarde d'un objet personne....................................................................................................... 92 III-J - Les fichiers binaires................................................................................................................................... 94 III-J-1 - La classe RandomAccessFile........................................................................................................... 94 III-J-2 - La classe article.................................................................................................................................94 III-J-3 - Ecrire un enregistrement................................................................................................................... 95 III-J-4 - Lire un enregistrement.......................................................................................................................96 III-J-5 - Conversion texte --> binaire.............................................................................................................. 97 III-J-6 - Conversion binaire --> texte.............................................................................................................. 99 III-J-7 - Accs direct aux enregistrements................................................................................................... 101 III-K - Utiliser les expression rgulires.............................................................................................................103 III-K-1 - Le paquetage java.util.regex...........................................................................................................103 III-K-2 - Vrifier qu'une chane correspond un modle donn.................................................................. 106 III-K-3 - Trouver tous les lments d'une chane correspondant un modle............................................ 107 III-K-4 - Rcuprer des parties d'un modle................................................................................................108 III-K-5 - Un programme d'apprentissage......................................................................................................109 III-K-6 - La mthode split de la classe Pattern............................................................................................ 111 III-L - Exercices..................................................................................................................................................112 III-L-1 - Exercice 1........................................................................................................................................112 III-L-2 - Exercice 2........................................................................................................................................114 III-L-3 - Exercice 3........................................................................................................................................115 III-L-4 - Exercice 4........................................................................................................................................116 III-L-5 - Exercice 5........................................................................................................................................118 IV - Interfaces graphiques.......................................................................................................................................120 IV-A - Les bases des interfaces graphiques..................................................................................................... 120 IV-A-1 - Une fentre simple......................................................................................................................... 120 IV-A-2 - Grer un vnement.......................................................................................................................122 IV-A-3 - Un formulaire avec bouton............................................................................................................. 125 IV-A-4 - Les gestionnaires d'vnements.................................................................................................... 129 IV-A-5 - Les mthodes des gestionnaires d'vnements............................................................................ 130 IV-A-6 - Les classes adaptateurs.................................................................................................................131 IV-A-7 - Conclusion...................................................................................................................................... 132 IV-B - Construire une interface graphique avec JBuilder.................................................................................. 132 IV-B-1 - Notre premier projet Jbuilder..........................................................................................................132 IV-B-2 - Les fichiers gnrs par Jbuilder pour une interface graphique.................................................... 137
-3Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IV-B-2-a - La classe principale............................................................................................................... 137 IV-B-2-b - La classe de la fentre.......................................................................................................... 141 IV-B-3 - Dessiner une interface graphique.................................................................................................. 142 IV-B-3-a - Un exemple............................................................................................................................ 142 IV-B-3-b - Le code de la classe de la fentre........................................................................................ 148 IV-B-3-c - Conclusion.............................................................................................................................. 151 IV-B-4 - Chercher de l'aide.......................................................................................................................... 151 IV-B-4-a - Aide : Sommaire.....................................................................................................................152 IV-B-4-b - Aide : Index............................................................................................................................ 153 IV-B-5 - Quelques composants swing..........................................................................................................154 IV-B-5-a - composants JLabel et JTextField.......................................................................................... 154 IV-B-5-b - composant JComboBox......................................................................................................... 156 IV-B-5-c - composant JList..................................................................................................................... 158 IV-B-5-d - Cases cocher JCheckBox, boutons radio JButtonRadio.................................................... 164 IV-B-5-e - composant JScrollBar............................................................................................................ 167 IV-B-5-f - composant JTextArea............................................................................................................. 170 IV-B-6 - vnements souris......................................................................................................................... 172 IV-B-7 - Crer une fentre avec menu........................................................................................................ 176 IV-C - Botes de dialogue.................................................................................................................................. 181 IV-C-1 - Botes de message........................................................................................................................ 181 IV-C-2 - Looks and Feels.............................................................................................................................181 IV-C-3 - Botes de confirmation....................................................................................................................183 IV-C-4 - Bote de saisie................................................................................................................................184 IV-D - Botes de slection................................................................................................................................. 184 IV-D-1 - Bote de slection JFileChooser.................................................................................................... 185 IV-D-2 - Botes de slection JColorChooser et JFontChooser.................................................................... 190 IV-E - L'application graphique IMPOTS.............................................................................................................196 IV-F - Ecriture d'applets.....................................................................................................................................202 IV-F-1 - Introduction..................................................................................................................................... 202 IV-F-2 - La classe JApplet........................................................................................................................... 203 IV-F-2-a - Dfinition.................................................................................................................................203 IV-F-2-b - Excution d'une applet : les mthodes init, start et stop........................................................204 IV-F-3 - Transformation d'une application graphique en applet................................................................... 204 IV-F-4 - L'option de mise en forme <applet> dans un document HTML......................................................212 IV-F-5 - Accder des ressources distantes depuis une applet................................................................. 214 IV-F-5-a - La classe URL........................................................................................................................214 IV-F-5-b - Un exemple console...............................................................................................................215 IV-F-5-c - Un exemple graphique........................................................................................................... 217 IV-F-5-d - Une applet.............................................................................................................................. 219 IV-G - L'applet IMPOTS.....................................................................................................................................220 IV-H - Conclusion...............................................................................................................................................224 IV-I - Jbuilder sous Linux...................................................................................................................................224 V - Gestion des bases de donnes avec l'API JDBC............................................................................................ 237 V-A - Gnralits............................................................................................................................................... 237 V-B - Les tapes importantes dans l'exploitation des bases de donnes......................................................... 238 V-B-1 - Introduction...................................................................................................................................... 238 V-B-2 - L'tape de connexion...................................................................................................................... 240 V-B-3 - mission de requtes vers la base de donnes............................................................................. 242 V-B-3-a - La classe Statement............................................................................................................... 242 V-B-3-b - mettre une requte d'interrogation de la base......................................................................242 V-B-3-c - La classe ResultSet : rsultat d'une requte select................................................................ 243 V-B-3-d - Un premier exemple................................................................................................................244 V-B-3-e - La classe ResultSetMetadata................................................................................................. 245 V-B-3-f - Un deuxime exemple............................................................................................................. 245 V-B-3-g - mettre une requte de mise jour de la base de donnes..................................................246 V-B-3-h - Un troisime exemple............................................................................................................. 247 V-B-3-i - mettre une requte SQL quelconque.................................................................................... 249 V-B-3-j - Quatrime exemple.................................................................................................................. 249
-4Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
V-C - IMPOTS avec une base de donnes...................................................................................................... 252 V-D - Exercices..................................................................................................................................................259 V-D-1 - Exercice 1........................................................................................................................................259 V-D-2 - Exercice 2........................................................................................................................................259 V-D-3 - Exercice 3........................................................................................................................................261 V-D-4 - Exercice 4........................................................................................................................................268 VI - Les Threads d'excution.................................................................................................................................. 273 VI-A - Introduction..............................................................................................................................................273 VI-B - Cration de threads d'excution............................................................................................................. 274 VI-C - Intrt des threads..................................................................................................................................277 VI-D - Une horloge graphique........................................................................................................................... 278 VI-E - Applet horloge......................................................................................................................................... 281 VI-F - Synchronisation de tches...................................................................................................................... 283 VI-F-1 - Un comptage non synchronis....................................................................................................... 283 VI-F-2 - Un comptage synchronis par mthode.........................................................................................286 VI-F-3 - Comptage synchronis par un objet...............................................................................................287 VI-F-4 - Synchronisation par vnements....................................................................................................288 VII - Programmation TCP-IP................................................................................................................................... 292 VII-A - Gnralits............................................................................................................................................. 292 VII-A-1 - Les protocoles de l'Internet........................................................................................................... 292 VII-A-2 - Le modle OSI.............................................................................................................................. 292 VII-A-3 - Le modle TCP/IP......................................................................................................................... 294 VII-A-4 - Fonctionnement des protocoles de l'Internet.................................................................................296 VII-A-5 - Les problmes d'adressage dans l'Internet................................................................................... 297 VII-A-5-a - Les classes d'adresses IP.................................................................................................... 298 VII-A-5-b - Les protocoles de conversion Adresse Internet <--> Adresse physique............................... 299 VII-A-6 - La couche rseau dite couche IP de l'internet.............................................................................. 300 VII-A-6-a - Le routage............................................................................................................................. 300 VII-A-6-b - Messages d'erreur et de contrle......................................................................................... 301 VII-A-7 - La couche transport : les protocoles UDP et TCP........................................................................ 301 VII-A-7-a - Le protocole UDP : User Datagram Protocol........................................................................301 VII-A-7-b - Le protocole TCP : Transfer Control Protocol.......................................................................302 VII-A-8 - La couche Applications..................................................................................................................302 VII-A-9 - Conclusion..................................................................................................................................... 304 VII-B - Gestion des adresses rseau en Java.................................................................................................. 304 VII-B-1 - Dfinition........................................................................................................................................ 304 VII-B-2 - Quelques exemples....................................................................................................................... 305 VII-B-2-a - Identifier la machine locale................................................................................................... 305 VII-B-2-b - Identifier une machine quelconque....................................................................................... 305 VII-C - Communications TCP-IP........................................................................................................................306 VII-C-1 - Gnralits.....................................................................................................................................306 VII-C-2 - Les caractristiques du protocole TCP......................................................................................... 307 VII-C-3 - La relation client-serveur............................................................................................................... 307 VII-C-4 - Architecture d'un client.................................................................................................................. 308 VII-C-5 - Architecture d'un serveur...............................................................................................................308 VII-C-6 - La classe Socket........................................................................................................................... 308 VII-C-6-a - Dfinition............................................................................................................................... 308 VII-C-6-b - Ouverture d'une connexion avec une machine Serveur....................................................... 309 VII-C-6-c - Envoyer des informations sur le rseau............................................................................... 310 VII-C-6-d - Lire des informations venant du rseau............................................................................... 310 VII-C-6-e - Fermeture de la connexion...................................................................................................310 VII-C-6-f - L'architecture du client........................................................................................................... 310 VII-C-7 - La classe ServerSocket.................................................................................................................311 VII-C-7-a - Dfinition............................................................................................................................... 311 VII-C-7-b - Ouverture du service............................................................................................................ 311 VII-C-7-c - Acceptation d'une demande de connexion........................................................................... 312 VII-C-7-d - Lecture/Ecriture via la socket de service.............................................................................. 312 VII-C-7-e - Identifier le client...................................................................................................................312
-5Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
VII-C-7-f - Fermer le service................................................................................................................... 312 VII-C-7-g - Architecture de base d'un serveur........................................................................................312 VII-D - Applications............................................................................................................................................ 313 VII-D-1 - Serveur d'cho.............................................................................................................................. 313 VII-D-2 - Un client java pour le serveur d'cho............................................................................................317 VII-D-3 - Un client TCP gnrique............................................................................................................... 320 VII-D-4 - Un serveur Tcp gnrique.............................................................................................................326 VII-D-5 - Un client Web................................................................................................................................332 VII-D-6 - Client Web grant les redirections................................................................................................ 334 VII-D-7 - Serveur de calcul d'impts............................................................................................................ 337 VII-E - Exercices................................................................................................................................................ 343 VII-E-1 - Exercice 1 - Client TCP gnrique graphique...............................................................................343 VII-E-1-a - Prsentation de l'application................................................................................................. 343 VII-E-1-b - FONCTIONNEMENT DE L'APPLICATION........................................................................... 344 VII-E-1-c - TRAVAIL A FAIRE................................................................................................................ 346 VII-E-2 - Exercice 2 - Un serveur de ressources.........................................................................................346 VII-E-2-a - INTRODUCTION................................................................................................................... 346 VII-E-2-b - L'INTERFACE VISUELLE..................................................................................................... 347 VII-E-2-c - FONCTIONNEMENT DE L'APPLICATION........................................................................... 348 VII-E-2-d - TRAVAIL A FAIRE................................................................................................................ 350 VII-E-3 - Exercice 3 - un client smtp............................................................................................................350 VII-E-3-a - INTRODUCTION................................................................................................................... 350 VII-E-3-b - L'INTERFACE VISUELLE..................................................................................................... 352 VII-E-3-c - LES MENUS..........................................................................................................................353 VII-E-3-d - FONCTIONNEMENT DE L'APPLICATION........................................................................... 353 VII-E-3-e - GESTION D'UN FICHIER DE CONFIGURATION................................................................ 355 VII-E-3-f - TRAVAIL A FAIRE................................................................................................................. 356 VII-E-4 - Exercice 4 - client POPPASS........................................................................................................356 VII-E-4-a - Introduction............................................................................................................................356 VII-E-4-b - Le formulaire du client.......................................................................................................... 357 VII-E-4-c - Les menus.............................................................................................................................358 VII-E-4-d - Fonctionnement de l'application............................................................................................358 VII-E-4-e - TRAVAIL A FAIRE................................................................................................................ 359 VIII - JAVA RMI.......................................................................................................................................................360 VIII-A - Introduction............................................................................................................................................ 360 VIII-B - Apprenons par l'exemple...................................................................................................................... 360 VIII-B-1 - L'application serveur..................................................................................................................... 360 VIII-B-1-a - tape 1 : l'interface de l'objet/serveur.................................................................................. 360 VIII-B-1-b - tape 2 : criture de l'objet serveur.....................................................................................361 VIII-B-1-c - tape 3 : compilation de l'application serveur......................................................................362 VIII-B-1-d - tape 4 : criture du client...................................................................................................362 VIII-B-1-e - gnration des fichiers .class ncessaires l'application client-serveur..............................364 VIII-B-1-f - tape 6 : Excution de l'application client-serveur d'cho.................................................... 365 VIII-B-1-g - Le client et le serveur sur deux machines diffrentes......................................................... 366 VIII-B-1-h - Rsum................................................................................................................................ 372 VIII-B-1-i - Serveur d'cho sur linux, clients sur Windows et Linux........................................................ 372 VIII-C - Deuxime exemple : Serveur SQL sur machine Windows................................................................... 373 VIII-C-1 - Le problme..................................................................................................................................373 VIII-C-2 - tape 1 : l'interface distante......................................................................................................... 373 VIII-C-3 - tape 2 : criture du serveur....................................................................................................... 374 VIII-C-4 - criture du client RMI...................................................................................................................376 VIII-C-5 - tape 3 : cration des fichiers .class............................................................................................379 VIII-C-6 - tape 4 : Tests avec serveur & client sur mme machine windows............................................ 379 VIII-C-7 - tape 5 : Tests avec serveur sur machine windows et client sur machine.................................. 380 VIII-C-8 - Conclusion.................................................................................................................................... 381 VIII-D - Exercices............................................................................................................................................... 383 VIII-D-1 - Exercice 1.....................................................................................................................................383 VIII-D-2 - Exercice 2.....................................................................................................................................383
-6Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IX - Construction d'applications distribues CORBA.............................................................................................. 384 IX-A - Introduction..............................................................................................................................................384 IX-B - Processus de dveloppement d'une application CORBA....................................................................... 384 IX-B-1 - Introduction..................................................................................................................................... 384 IX-B-2 - criture de l'interface du serveur................................................................................................... 384 IX-B-3 - Compilation de l'interface IDL du serveur...................................................................................... 385 IX-B-4 - Compilation des classes gnres partir de l'interface IDL........................................................ 386 IX-B-5 - criture du serveur......................................................................................................................... 387 IX-B-5-a - Implmentation de l'interface iSrvEcho..................................................................................387 IX-B-5-b - criture de la classe de cration du serveur......................................................................... 387 IX-B-5-b-i - Les paramtres du serveur............................................................................................ 388 IX-B-5-b-ii - Crer l'objet d'accs au service d'annuaire CORBA......................................................388 IX-B-5-b-iii - Enregistrer le serveur dans l'annuaire des services CORBA........................................389 IX-B-5-c - Compilation de la classe de lancement serveur.................................................................... 390 IX-B-6 - criture du client.............................................................................................................................390 IX-B-6-a - Le code.................................................................................................................................. 390 IX-B-6-b - La connexion du client au serveur.........................................................................................391 IX-B-6-c - Compilation.............................................................................................................................392 IX-B-7 - Tests............................................................................................................................................... 393 IX-B-7-a - Lancement du service d'annuaire.......................................................................................... 393 IX-B-7-b - Lancement du serveur d'cho................................................................................................393 IX-B-7-c - Lancement du client sur le mme poste que celui du serveur...............................................393 IX-B-7-d - Lancement du client sur poste Windows autre que celui du serveur..................................... 393 IX-C - Exemple 2 : un serveur SQL.................................................................................................................. 394 IX-C-1 - Introduction..................................................................................................................................... 394 IX-C-2 - criture de l'interface IDL du serveur.............................................................................................394 IX-C-3 - Compilation de l'interface IDL du serveur...................................................................................... 396 IX-C-4 - criture du serveur SQL................................................................................................................ 397 IX-C-5 - criture du programme de lancement du serveur SQL................................................................. 399 IX-C-6 - criture du client............................................................................................................................ 400 IX-C-7 - Tests............................................................................................................................................... 403 IX-C-7-a - Pr-requis...............................................................................................................................403 IX-C-7-b - Lancement du service d'annuaire.......................................................................................... 404 IX-C-7-c - Lancement du serveur SQL...................................................................................................404 IX-C-7-d - Lancement d'un client sur la mme machine que le serveur.................................................405 IX-C-7-e - Lancement d'un client sur une autre machine que celle du serveur......................................405 IX-D - Correspondances IDL - JAVA.................................................................................................................405
-7Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
-8Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
x=x*2;
-9Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Exemple :
Remarque Pourquoi dclarer des constantes ? 1. La lecture du programme sera plus aise si l'on a donn la constante un nom significatif : Exemple :
2. La modification du programme sera plus aise si la "constante" vient changer. Ainsi dans le cas prcdent, si le taux de tva passe 33%, la seule modification faire sera de modifier l'instruction dfinissant sa valeur :
Si l'on avait utilis 0.186 explicitement dans le programme, ce serait alors de nombreuses instructions qu'il faudrait modifier.
- 10 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Voici un programme prsentant les principales techniques de conversion entre nombres et chanes de caractres. La conversion d'une chane vers un nombre peut chouer si la chane ne reprsente pas un nombre valide. Il y a alors gnration d'une erreur fatale appele exception en Java. Cette erreur peut tre gre par la clause try/catch suivante :
try{ appel de la fonction susceptible de gnrer l'exception } catch (Exception e){ traiter l'exception e } instruction suivante
Si la fonction ne gnre pas d'exception, on passe alors instruction suivante, sinon on passe dans le corps de la clause catch puis instruction suivante. Nous reviendrons ultrieurement sur la gestion des exceptions.
import java.io.*; public class conv1{ public static void main(String arg[]){ String S; final int i=10; final long l=100000; final float f=(float)45.78; double d=-14.98; // nombre --> chane S=""+i; affiche(S); S=""+l; affiche(S); S=""+f; affiche(S); S=""+d; affiche(S); //boolean --> chane final boolean b=false; S=""+new Boolean(b); affiche(S); // chane --> int int i1; i1=Integer.parseInt("10"); affiche(""+i1); try{ i1=Integer.parseInt("10.67"); affiche(""+i1); } catch (Exception e){ affiche("Erreur "+e); } // chane --> long long l1; l1=Long.parseLong("100"); affiche(""+l1); try{ l1=Long.parseLong("10.675"); affiche(""+l1); } catch (Exception e){ affiche("Erreur "+e); } // chane --> double double d1; d1=Double.valueOf("100.87").doubleValue(); affiche(""+d1); try{ d1=Double.valueOf("abcd").doubleValue(); affiche(""+d1); } catch (Exception e){ affiche("Erreur "+e);
- 11 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} // chane --> float float f1; f1=Float.valueOf("100.87").floatValue(); affiche(""+f1); try{ d1=Float.valueOf("abcd").floatValue(); affiche(""+f1); } catch (Exception e){ affiche("Erreur "+e); } }// fin main public static void affiche(String S){ System.out.println("S="+S); } }// fin classe
ou
Type[] Tableau=new Type[n]
Les deux syntaxes sont lgales. n est le nombre de donnes que peut contenir le tableau. La syntaxe Tableau[i] dsigne la donne n i o i appartient l'intervalle [0,n-1]. Toute rfrence la donne Tableau[i] o i n'appartient pas l'intervalle [0,n- 1] provoquera une exception. Un tableau deux dimensions pourra tre dclar comme suit :
Type Tableau[][]=new Type[n][p]
ou
Type[][] Tableau=new Type[n][p]
La syntaxe Tableau[i] dsigne la donne n i de Tableau o i appartient l'intervalle [0,n-1]. Tableau[i] est lui-mme un tableau : Tableau[i][j] dsigne la donne n j de Tableau[i] o j appartient l'intervalle [0,p-1]. Toute rfrence une donne de Tableau avec des index incorrects gnre une erreur fatale.
- 12 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Voici un exemple :
public class test1{ public static void main(String arg[]){ float[][] taux=new float[2][2]; taux[1][0]=0.24F; taux[1][1]=0.33F; System.out.println(taux[1].length); System.out.println(taux[1][1]); } }
Les instructions lmentaires apparaissent clairement lorsqu'on considre la structure d'un micro-ordinateur et de ses priphriques.
1 2 3 4 5
lecture d'informations provenant du clavier traitement d'informations criture d'informations l'cran lecture d'informations provenant d'un fichier disque criture d'informations dans un fichier disque
ou
System.err.println(expression)
- 13 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
o expression est tout type de donne qui puisse tre converti en chane de caractres pour tre affich l'cran. Dans l'exemple prcdent, nous avons vu deux instructions d'criture :
System.out.println(taux[1].length); System.out.println(taux[1][1]);
System.out crit dans un fichier texte qui est par dfaut l'cran. Il en est de mme pour System.err. Ces fichiers portent un numro (ou descripteur) respectivement 1 et 2. Le flux d'entre du clavier (System.in) est galement considr comme un fichier texte, de descripteur 0. Dos comme Unix supportent le tubage (pipe) de commandes :
commande1 | commande2
Tout ce que commande1 crit avec System.out est tub (redirig) vers l'entre System.in de commande2. Dit autrement, commande2 lit avec System.in, les donnes produites par commande2 avec System.out qui ne sont donc plus affiches l'cran. Ce systme est trs utilis sous Unix. Dans ce tubage, le flux System.err n'est lui pas redirig : il crit sur l'cran. C'est pourquoi il est utilis pour crire les messages d'erreurs (d'o son nom err) : on est assur que lors d'un tubage de commandes, les messages d'erreur continueront s'afficher l'cran. On prendra donc l'habitude d'crire les messages d'erreur l'cran avec le flux System.err plutt qu'avec le flux System.out.
Nous n'expliquerons pas ici les dtails de cette instruction qui fait intervenir la notion de constructions d'objets. Nous l'utiliserons telle-quelle. La construction d'un flux peut chouer : une erreur fatale, appele exception en Java, est alors gnre. A chaque fois qu'une mthode est susceptible de gnrer une exception, le compilateur Java exige qu'elle soit gre par le programmeur. Aussi, pour crer le flux d'entre prcdent, il faudra en ralit crire :
BufferedReader IN=null; try{ IN=new BufferedReader(new InputStreamReader(System.in)); } catch (Exception e){ System.err.println("Erreur " +e); System.exit(1); }
De nouveau, on ne cherchera pas expliquer ici la gestion des exceptions. Une fois le flux IN prcdent construit, on peut lire une ligne de texte par l'instruction :
String ligne; ligne=IN.readLine();
La ligne tape au clavier est range dans la variable ligne et peut ensuite tre exploite par le programme.
- 14 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les instructions
Object obj=new Object(); System.out.println(""+obj); System.out.println(obj.getClass().getName());
ont pour but de montrer que n'importe quel objet peut faire l'objet d'un affichage. Nous ne chercherons pas ici expliquer la signification de ce qui est affich. Nous avons galement l'affichage de la valeur d'un objet dans le bloc :
try{ IN=new BufferedReader(new InputStreamReader(System.in)); } catch (Exception e){ affiche(e); System.exit(1); }
La variable e est un objet de type Exception qu'on affiche ici avec l'appel affiche(e). Nous avions rencontr, sans en parler, cet affichage de la valeur d'une exception dans le programme de conversion vu plus haut.
- 15 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
C'est ainsi que l'opration V1=V2=expression est lgale. A cause de la priorit, c'est l'oprateur = le plus droite qui va tre valu. On a donc V1=(V2=expression). L'expression V2=expression est value et a pour valeur V. L'valuation de cette expression a provoqu l'affectation de V V2. L'oprateur = suivant est alors valu sous la forme V1=V. La valeur de cette expression est encore V. Son valuation provoque l'affectation de V V1. Ainsi donc, l'opration V1=V2=expression est une expression dont l'valuation 1 2 provoque l'affectation de la valeur de expression aux variables V1 et V2 rend comme rsultat la valeur de expression.
Il existe diverses fonctions mathmatiques : double sqrt(double x) racine carre double cos(double x) Cosinus double sin(double x) Sinus double tan(double x) Tangente double pow(double x,double y) x la puissance y (x>0) double exp(double x) Exponentielle double log(double x) Logarithme nprien double abs(double x) valeur absolue etc...
- 16 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Toutes ces fonctions sont dfinies dans une classe Java appele Math. Lorsqu'on les utilise, il faut les prfixer avec le nom de la classe o elles sont dfinies. Ainsi on crira :
double x, y=4; x=Math.sqrt(y);
- 17 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
1 2
Le rsultat d'une expression relationnelle est le boolen false si expression est faussetrue sinon. Exemple :
boolean fin; int x; fin=x>4;
Comparaison de deux caractres Soient deux caractres C1 et C2. Il est possible de les comparer avec les oprateu <, <=, ==, !=, >, >= Ce sont alors leurs codes ASCII, qui sont des nombres, qui sont alors compars. On rappelle que selon l'ordre ASCII on a les relations suivantes : espace < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. <'z' Comparaison de deux chanes de caractres Elles sont compares caractre par caractre. La premire ingalit rencontre entre deux caractres induit une ingalit de mme sens sur les chanes. Exemples : Soit comparer les chanes "Chat" et "Chien"
"Chat" "Chien" ----------------------'C' = 'C' 'h' = 'h' 'a' < 'i'
Cette dernire ingalit permet de dire que "Chat" < "Chien". Soit comparer les chanes "Chat" et "Chaton". Il y a galit tout le temps jusqu' puisement de la chane "Chat". Dans ce cas, la chane puise est dclare la plus "petite". On a donc la relation "Chat" < "Chaton". Fonctions de comparaisons de deux chanes On ne peut utiliser ici les oprateurs relationnels <, <=, ==, !=, >, >= . Il faut utiliser des mthodes de la classe String :
String chaine1, chaine2; chaine1=#; chaine2=#; int i=chaine1.compareTo(chaine2); boolean egal=chaine1.equals(chaine2)
- 18 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
0 si les deux chanes sont gales 1 si chane n1 > chane n2 -1 si chane n1 < chane n2
La variable egal aura la valeur true si les deux chanes sont gales.
Les oprateurs relationnels ont priorit sur les oprateurs && et ||.
i<<n dcale i de n bits sur la gauche. Les bits entrants sont des zros. i>>n dcale i de n bits sur la droite. Si i est un entier sign (signed char, int, long) le bit de signe est prserv. i & j fait le ET logique de i et j bit bit. i | j fait le OU logique de i et j bit bit. ~i complmente i 1 i^j fait le OU EXCLUSIF de i et j
valeur 0x23F0 0x0123 le bit de signe est prserv. 0xFF12 le bit de signe est prserv. 0x1023 0xF33F 0xEDC0
Il en est de mme avec les oprateurs /, %,* ,<<, >>, &, |, ^ Ainsi a=a+2; peut s'crire a+=2;
I-C-4-i - L'oprateur ?
L'expression expr_cond ? expr1:expr2 est value de la faon suivante : 1 2 3 l'expression expr_cond est value. C'est une expression conditionnelle valeur vrai ou faux Si elle est vraie, la valeur de l'expression est celle de expr1. expr2 n'est pas value. Si elle est fausse, c'est l'inverse qui se produit : la valeur de l'expression est celle de expr2. expr1 n'est pas value.
Exemple i=(j>4 ? j+1:j-1); affectera la variable i : j+1 si j>4, j-1 sinon C'est la mme chose que d'crire if(j>4) i=j+1; else i=j-1; mais c'est plus concis.
gd indique qu'a priorit gale, c'est la priorit gauche-droite qui est observe. Cela signifie que lorsque dans une expression, l'on a des oprateurs de mme priorit, c'est l'oprateur le plus gauche dans l'expression qui est valu en premier. dg indique une priorit droite-gauche.
- 20 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ici il est ncessaire de changer le type de i ou j en rel sinon la division donnera le quotient entier et non rel. i est une valeur code de faon exacte sur 2 octets (float) i est la mme valeur code de faon approche en rel sur 4 octets Il y a donc transcodage de la valeur de i. Ce transcodage n'a lieu que le temps d'un calcul, la variable i conservant toujours son type int.
action arrte le processus en cours et rend la valeur status au processus pre exit provoque la fin du processus en cours et rend la main au processus appelant. La valeur de status peut tre utilise par celui-ci. Sous DOS, cette variable status est rendue DOS dans la variable systme ERRORLEVEL dont la valeur peut tre teste dans un fichier batch. Sous Unix, c'est la variable $? qui rcupre la valeur de status si l'interprteur de commandes est le Bourne Shell (/bin/sh). Exemple :
System.exit(0);
notes: la condition est entoure de parenthses. chaque action est termine par point-virgule. les accolades ne sont pas termines par point-virgule.
- 21 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
les accolades ne sont ncessaires que s'il y a plus d'une action. la clause else peut tre absente. Il n'y a pas de then.
exemple
if (x>0) { nx=nx+1;sx=sx+x;} else dx=dx-x;
Dans l'exemple prcdent, le else se rapporte quel if ? La rgle est qu'un else se rapporte toujours au if le plus proche : if(n>6) dans l'exemple. Considrons un autre exemple :
public static void main(void) { int n=0; if(n>1) if(n>6) System.out.println(">6"); else; // else du if(n>6) : rien faire else System.out.println("<=1"); // else du if(n>1) }
Ici nous voulions mettre un else au if(n>1) et pas de else au if(n>6). A cause de la remarque prcdente, nous sommes obligs de mettre un else au if(n>6), dans lequel il n'y a aucune instruction.
- 22 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
default: actions_sinon; }
notes La valeur de l'expression de contrle, ne peut tre qu'un entier ou un caractre. l'expression de contrle est entoure de parenthses. la clause default peut tre absente. les valeurs vi sont des valeurs possibles de l'expression. Si l'expression a pour valeur vi , les actions derrire la clause case vi sont excutes. l'instruction break fait sortir de la structure de cas. Si elle est absente la fin du bloc d'instructions de la valeur vi, l'excution se poursuit alors avec les instructions de la valeur vi+1.
exemple En algorithmique
selon la valeur de choix cas 0 arrt cas 1 excuter module M1 cas 2 excuter module M2 sinon erreur<--vrai findescas
En Java
int choix, erreur; switch(choix){ case 0: System.exit(0); case 1: M1();break; case 2: M2();break; default: erreur=1; }
Notes les 3 arguments du for sont l'intrieur d'une parenthse. les 3 arguments du for sont spars par des points-virgules. chaque action du for est termine par un point-virgule. l'accolade n'est ncessaire que s'il y a plus d'une action. l'accolade n'est pas suivie de point-virgule.
- 23 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On boucle tant que la condition est vrifie. La boucle peut ne jamais tre excute. notes: la condition est entoure de parenthses. chaque action est termine par point-virgule. l'accolade n'est ncessaire que s'il y a plus d'une action. l'accolade n'est pas suivie de point-virgule.
On boucle jusqu' ce que la condition devienne fausse ou tant que la condition est vraie. Ici la boucle est faite au moins une fois. notes la condition est entoure de parenthses. chaque action est termine par point-virgule. l'accolade n'est ncessaire que s'il y a plus d'une action.
- 24 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On boucle tant que la condition est vraie (value avant chaque tour de boucle). Instructions_dpart sont effectues avant d'entrer dans la boucle pour la premire fois. Instructions_fin_boucle sont excutes aprs chaque tour de boucle. notes les 3 arguments du for sont l'intrieur de parenthses. les 3 arguments du for sont spars par des points-virgules. chaque action du for est termine par un point-virgule. l'accolade n'est ncessaire que s'il y a plus d'une action. l'accolade n'est pas suivie de point-virgule. les diffrentes instructions dans instructions_depart et instructions_fin_boucle sont spares par des virgules.
Exemples Les programmes suivants calculent tous la somme des n premiers nombres entiers.
1 for(i=1, somme=0;i<=n;i=i+1) somme=somme+a[i]; 2 for (i=1, somme=0;i<=n;somme=somme+a[i], i=i+1); 3 i=1;somme=0; while(i<=n) { somme+=i; i++; } 4 i=1; somme=0; do somme+=i++; while (i<=n);
Instructions de gestion de boucle break fait sortir de la boucle for, while, do ... while. continue fait passer l'itration suivante des boucles for, while, do ... while
- 25 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La fonction main, appele aussi mthode est excute la premire lors de l'excution d'un programme Java. Elle doit avoir obligatoirement la signature prcdente :
public static void main(String arg[]){
ou
public static void main(String[] arg){
Le nom de l'argument arg peut tre quelconque. C'est un tableau de chanes de caractres reprsentant les arguments de la ligne de commande. Nous y reviendrons un peu plus loin. Si on utilise des fonctions susceptibles de gnrer des exceptions qu'on ne souhaite pas grer finement, on pourra encadrer le code du programme par une clause try/catch :
public class test1{ public static void main(String arg[]){ try{ # code du programme } catch (Exception e){ // gestion de l'erreur }// try }// main }// class
Au dbut du code source et avant la dfinition de la classe, il est usuel de trouver des instructions d'importation de classes. Par exemple :
import java.io.*; public class test1{ public static void main(String arg[]){ # code du programme }// main }// class
qui crit java l'cran. Il y a dans cette simple instruction beaucoup de choses : System est une classe dont le nom complet est java.lang.System out est une proprit de cette classe de type java.io.PrintStream, une autre classe println est une mthode de la classe java.io.PrintStream.
- 26 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous ne compliquerons pas inutilement cette explication qui vient trop tt puisqu'elle ncessite la comprhension de la notion de classe pas encore aborde. On peut assimiler une classe une ressource. Ici, le compilateur aura besoin d'avoir accs aux deux classes java.lang.System et java.io.PrintStream. Les centaines de classes de Java sont rparties dans des archives aussi appeles des paquetages (package). Les instruction import places en dbut de programme servent indiquer au compilateur de quelles classes externes le programme a besoin (celles utilises mais non dfinies dans le fichier source qui sera compil). Ainsi dans notre exemple, notre programme a besoin des classes java.lang.System et java.io.PrintStream. On le dit avec l'instruction import. On pourrait crire en dbut de programme :
import java.lang.System; import java.io.PrintStream;
Un programme Java utilisant couramment plusieurs dizaines de classes externes, il serait pnible d'crire toutes les fonction import ncessaires. Les classes ont t regroupes dans des paquetages et on peut alors importer le paquetage entier. Ainsi pour importer les paquetages java.lang et java.io, on crira :
import java.lang.*; import java.io.*;
Le paquetage java.lang contient toutes les classes de base de Java et il est import automatiquement par le compilateur. Aussi finalement n'crira-t-on que :
import java.io.*;
Lorsqu'une fonction est susceptible de gnrer une exception, le compilateur Java oblige le programmeur grer celle-ci dans le but d'obtenir des programmes plus rsistants aux erreurs : il faut toujours viter le "plantage" sauvage d'une application. Ici, la fonction readLine gnre une exception s'il n'y a rien lire parce que par exemple le flux d'entre a t ferm. La gestion d'une exception se fait selon le schma suivant :
try{ appel de la fonction susceptible de gnrer l'exception } catch (Exception e){ traiter l'exception e } instruction suivante
Si la fonction ne gnre pas d'exception, on passe alors instruction suivante, sinon on passe dans le corps de la clause catch puis instruction suivante. Notons les points suivants : e est un objet driv du type Exception. On peut tre plus prcis en utilisant des types tels que IOException, SecurityException, ArithmeticException, etc : il existe une vingtaine de types d'exceptions. En crivant catch (Exception e), on indique qu'on veut grer toutes les types d'exceptions. Si le code de la clause try est
- 27 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
susceptible de gnrer plusieurs types d'exceptions, on peut vouloir tre plus prcis en grant l'exception avec plusieurs clauses catch :
try{ appel de la fonction susceptible de gnrer l'exception } catch (IOException e){ traiter l'exception e } } catch (ArrayIndexOutOfBoundsException e){ traiter l'exception e } } catch (RunTimeException e){ traiter l'exception e } instruction suivante
Ici, qu'il y ait exception ou pas, le code de la clause finally sera toujours excut. La classe Exception a une mthode getMessage() qui rend un message dtaillant l'erreur qui s'est produite. Ainsi si on veut afficher celui-ci, on crira :
catch (Exception ex){ System.err.println("L'erreur suivante s'est produite : "+ex.getMessage()); ... }//catch
La classe Exception a une mthode toString() qui rend une chane de caractres indiquant le type de l'exception ainsi que la valeur de la proprit Message. On pourra ainsi crire :
catch (Exception ex){ System.err.println ("L'erreur suivante s'est produite : "+ex.toString()); ... }//catch
Nous avons ici une opration string + Exception qui va tre automatiquement transforme en string + Exception.toString() par le compilateur afin de faire la concatnation de deux chanes de caractres. L'exemple suivant montre une exception gnre par l'utilisation d'un lment de tableau inexistant :
// tableaux // imports import java.io.*;
- 28 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public class tab1{ public static void main(String[] args){ // dclaration & initialisation d'un tableau int[] tab=new int[] {0,1,2,3}; int i; // affichage tableau avec un for for (i=0; i<tab.length; i++) System.out.println("tab[" + i + "]=" + tab[i]); // gnration d'une exception try{ tab[100]=6; }catch (Exception e){ System.err.println("L'erreur suivante s'est produite : " + e); }//try-catch }//main }//classe
Voici un autre exemple o on gre l'exception provoque par l'affectation d'une chane de caractres un nombre lorsque la chane ne reprsente pas un nombre :
// imports import java.io.*; public class console1{ public static void main(String[] args){ // cration d'un flux d'entre BufferedReader IN=null; try{ IN=new BufferedReader(new InputStreamReader(System.in)); }catch(Exception ex){} // On demande le nom System.out.print("Nom : "); // lecture rponse String nom=null; try{ nom=IN.readLine(); }catch(Exception ex){} // on demande l'ge int age=0; boolean ageOK=false; while ( ! ageOK){ // question System.out.print("ge : "); // lecture-vrification rponse try{ age=Integer.parseInt(IN.readLine()); ageOK=true; }catch(Exception ex) { System.err.println("Age incorrect, recommencez..."); }//try-catch }//while // affichage final System.out.println("Vous vous appelez " + nom + " et vous avez " + age + " ans"); }//Main }//classe
- 29 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
ge : 23 Vous vous appelez dupont et vous avez 23 ans E:\data\serge\MSNET\c#\bases\1>console1 Nom : dupont ge : xx Age incorrect, recommencez... ge : 12 Vous vous appelez dupont et vous avez 12 ans
Le fichier source contenant la classe coucou prcdente doit obligatoirement s'appeler coucou.java :
E:\data\serge\JAVA\ESSAIS\intro1>dir 10/06/2002 08:42 228 coucou.java
La compilation et l'excution d'un programme Java se fait dans une fentre DOS. Les excutables javac.exe (compilateur) et java.exe (interprteur) se trouvent dans le rpertoire bin du rpertoire d'installation du JDK :
E:\data\serge\JAVA\classes\paquetages\personne>dir "e:\program files\jdk14\bin\java?.exe" 07/02/2002 12:52 24 649 java.exe 07/02/2002 12:52 28 766 javac.exe
Le compilateur javac.exe va analyser le fichier source .java et produire un fichier compil .class. Celui-ci n'est pas immdiatement excutable par le processeur. Il ncessite un interprteur Java (java.exe) qu'on appelle une machine virtuelle ou JVM (Java Virtual Machine). A partir du code intermdiaire prsent dans le fichier .class, la machine virtuelle va gnrer des instructions spcifiques au processeur de la machine sur laquelle elle s'excute. Il existe des machines virtuelles Java pour diffrents types de systmes d'exploitation (Windows, Unix, Mac OS,...). Un fichier .class pourra tre excut par n'importe laquelle de ces machines virtuelles donc sur n'importe que systme d'exploitation. Cette portabilit inter-systmes est l'un des atouts majeurs de Java. Compilons le programme prcdent :
E:\data\serge\JAVA\ESSAIS\intro1>"e:\program files\jdk14\bin\javac" coucou.java E:\data\serge\JAVA\ESSAIS\intro1>dir 10/06/2002 08:42 228 coucou.java 10/06/2002 08:48 403 coucou.class
- 30 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On notera que dans la demande d'excution ci-dessus, on n'a pas prcis le suffixe .class du fichier coucou.class excuter. Il est implicite. Si le rpertoire bin du JDK est dans le PATH de la machine DOS, on pourra ne pas donner le chemin complet des excutables javac.exe et java.exe. On crira alors simplement
javac coucou.java java coucou
Les valeurs des paramtres effectifs "papa" et 20 ont t recopies dans les paramtres formels S et a. Ceux-ci ont t ensuite modifis. Les paramtres effectifs ont t eux inchangs. On notera bien ici le type des paramtres effectifs : S est une rfrence d'objet c.a.d. l'adresse d'un objet en mmoire age est une valeur entire
Chaque ligne a 3 champs. Pour calculer l'impt I, on recherche la premire ligne o QF<=champ1. Par exemple, si QF=23000 on trouvera la ligne 24740 0.15 2072.5
- 32 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'impt I est alors gal 0.15*R - 2072.5*nbParts. Si QF est tel que la relation QF<=champ1 n'est jamais vrifie, alors ce sont les coefficients de la dernire ligne qui sont utiliss. Ici : 0 0.65 49062 ce qui donne l'impt I=0.65*R - 49062*nbParts. Le programme Java correspondant est le suivant :
import java.io.*; public class impots{ // ------------ main public static void main(String arg[]){ // donnes // limites des tranches d'impts double Limites[]={12620, 13190, 15640, 24740, 31810, 39970, 48360,55790, 92970, 127860, 151250, 172040, 195000, 0}; // coeff appliqu au nombre de parts double Coeffn[]={0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5,12106, 16754.5, 23147.5, 30710, 39312, 49062}; // le programme // cration du flux d'entre clavier BufferedReader IN=null; try{ IN=new BufferedReader(new InputStreamReader(System.in)); } catch(Exception e){ erreur("Cration du flux d'entre", e, 1); } // on rcupre le statut marital boolean OK=false; String reponse=null; while(! OK){ try{ System.out.print("Etes-vous mari(e) (O/N) ? "); reponse=IN.readLine(); reponse=reponse.trim().toLowerCase(); if (! reponse.equals("o") && !reponse.equals("n")) System.out.println("Rponse incorrecte. Recommencez"); else OK=true; } catch(Exception e){ erreur("Lecture tat marital",e,2); } } boolean Marie = reponse.equals("o"); // nombre d'enfants OK=false; int NbEnfants=0; while(! OK){ try{ System.out.print("Nombre d'enfants : "); reponse=IN.readLine(); try{ NbEnfants=Integer.parseInt(reponse); if(NbEnfants>=0) OK=true; else System.err.println("Rponse incorrecte. Recommencez"); } catch(Exception e){ System.err.println("Rponse incorrecte. Recommencez"); }// try } catch(Exception e){
- 33 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
erreur("Lecture tat marital",e,2); }// try }// while // salaire OK=false; long Salaire=0; while(! OK){ try{ System.out.print("Salaire annuel : "); reponse=IN.readLine(); try{ Salaire=Long.parseLong(reponse); if(Salaire>=0) OK=true; else System.err.println("Rponse incorrecte. Recommencez"); } catch(Exception e){ System.err.println("Rponse incorrecte. Recommencez"); }// try } catch(Exception e){ erreur("Lecture Salaire",e,4); }// try }// while // calcul du nombre de parts double NbParts; if(Marie) NbParts=(double)NbEnfants/2+2; else NbParts=(double)NbEnfants/2+1; if (NbEnfants>=3) NbParts+=0.5; // revenu imposable double Revenu; Revenu=0.72*Salaire; // quotient familial double QF; QF=Revenu/NbParts; // recherche de la tranche d'impots correspondant QF int i; int NbTranches=Limites.length; Limites[NbTranches-1]=QF; i=0; while(QF>Limites[i]) i++; // l'impt long impots=(long)(i*0.05*Revenu-Coeffn[i]*NbParts); // on affiche le rsultat System.out.println("Impt payer : " + impots); }// main // ------------ erreur private static void erreur(String msg, Exception e, int exitCode){ System.err.println(msg+"("+e+")"); System.exit(exitCode); }// erreur }// class
- 34 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Impt payer : 33388 C:\Serge\java\impots\1>java impots Etes-vous mari(e) (O/N) ? w Rponse incorrecte. Recommencez Etes-vous mari(e) (O/N) ? q Rponse incorrecte. Recommencez Etes-vous mari(e) (O/N) ? o Nombre d'enfants : q Rponse incorrecte. Recommencez Nombre d'enfants : 2 Salaire annuel : q Rponse incorrecte. Recommencez Salaire annuel : 1 Impt payer : 0
- 35 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// mthode m4
A partir de la classe C1 prcdente, on peut crer de nombreux objets O1, O2,# Tous auront les proprits p1, p2,# et les mthodes m3, m4, # Ils auront des valeurs diffrentes pour leurs proprits pi ayant ainsi chacun un tat qui leur est propre. Par analogie la dclaration int i,j; cre deux objets (le terme est incorrect ici) de type (classe) int. Leur seule proprit est leur valeur. Si O1 est un objet de type C1, O1.p1 dsigne la proprit p1 de O1 et O1.m1 la mthode m1 de O1. Considrons un premier modle d'objet : la classe personne.
- 36 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} }
Nous avons ici la dfinition d'une classe, donc un type de donne. Lorsqu'on va crer des variables de ce type, on les appellera des objets. Une classe est donc un moule partir duquel sont construits des objets. Les membres ou champs d'une classe peuvent tre des donnes ou des mthodes (fonctions). Ces champs peuvent avoir l'un des trois attributs suivants : priv Un champ priv (private) n'est accessible que par les seules mthodes internes de la classe public Un champ public est accessible par toute fonction dfinie ou non au sein de la classe protg Un champ protg (protected) n'est accessible que par les seules mthodes internes de la classe ou d'un objet driv (voir ultrieurement le concept d'hritage).
En gnral, les donnes d'une classe sont dclares prives alors que ses mthodes sont dclares publiques. Cela signifie que l'utilisateur d'un objet (le programmeur) a n'aura pas accs directement aux donnes prives de l'objet b pourra faire appel aux mthodes publiques de l'objet et notamment celles qui donneront accs ses donnes prives.
Remarques L'ordre de dclaration des attributs private, protected et public est quelconque.
- 37 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Quel est le rle de la mthode initialise ? Parce que nom, prenom et age sont des donnes prives de la classe personne, les instructions
personne p1; p1.prenom="Jean"; p1.nom="Dupont"; p1.age=30;
sont illgales. Il nous faut initialiser un objet de type personne via une mthode publique. C'est le rle de la mthode initialise. On crira :
personne p1; p1.initialise("Jean","Dupont",30);
dclare p1 comme une rfrence un objet de type personne. Cet objet n'existe pas encore et donc p1 n'est pas initialis. C'est comme si on crivait :
personne p1=null;
o on indique explicitement avec le mot cl null que la variable p1 ne rfrence encore aucun objet. Lorsqu'on crit ensuite
p1.initialise("Jean","Dupont",30);
on fait appel la mthode initialise de l'objet rfrenc par p1. Or cet objet n'existe pas encore et le compilateur signalera l'erreur. Pour que p1 rfrence un objet, il faut crire :
personne p1=new personne();
Cela a pour effet de crer un objet de type personne non encore initialis : les attributs nom et prenom qui sont des rfrences d'objets de type String auront la valeur null, et age la valeur 0. Il y a donc une initialisation par dfaut. Maintenant que p1 rfrence un objet, l'instruction d'initialisation de cet objet
p1.initialise("Jean","Dupont",30);
est valide.
- 38 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'instruction this.prenom=P signifie que l'attribut prenom de l'objet courant (this) reoit la valeur P. Le mot cl this dsigne l'objet courant : celui dans lequel se trouve la mthode excute. Comment le connat-on ? Regardons comment se fait l'initialisation de l'objet rfrenc par p1 dans le programme appelant :
p1.initialise("Jean","Dupont",30);
C'est la mthode initialise de l'objet p1 qui est appele. Lorsque dans cette mthode, on rfrence l'objet this, on rfrence en fait l'objet p1. La mthode initialise aurait aussi pu tre crite comme suit :
public void initialise(String P, String N, int age){ prenom=P; nom=N; this.age=age; }
Lorsqu'une mthode d'un objet rfrence un attribut A de cet objet, l'criture this.A est implicite. On doit l'utiliser explicitement lorsqu'il y a conflit d'identificateurs. C'est le cas de l'instruction :
this.age=age;
o age dsigne un attribut de l'objet courant ainsi que le paramtre age reu par la mthode. Il faut alors lever l'ambigut en dsignant l'attribut age par this.age.
La classe personne est dfinie dans le fichier source personne.java et est compile :
E:\data\serge\JAVA\BASES\OBJETS\2>javac personne.java E:\data\serge\JAVA\BASES\OBJETS\2>dir 10/06/2002 09:21 473 personne.java 10/06/2002 09:22 835 personne.class 10/06/2002 09:23 165 test1.java
- 39 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On peut s'tonner que le programme test1.java n'importe pas la classe personne avec une instruction :
import personne;
Lorsque le compilateur rencontre dans le code source une rfrence de classe non dfinie dans ce mme fichier source, il recherche la classe divers endroits : dans les paquetages imports par les instructions import dans le rpertoire partir duquel le compilateur a t lanc
Dans notre exemple, le compilateur a t lanc depuis le rpertoire contenant le fichier personne.class, ce qui explique qu'il a trouv la dfinition de la classe personne. Mettre dans ce cas de figure une instruction import provoque une erreur de compilation :
E:\data\serge\JAVA\BASES\OBJETS\2>javac test1.java test1.java:1: '.' expected import personne; ^ 1 error
Pour viter cette erreur mais pour rappeler que la classe personne doit tre importe, on crira l'avenir en dbut de programme :
// classes importes // import personne;
Il est possible de rassembler plusieurs classes dans un mme fichier source. Rassemblons ainsi les classes personne et test1 dans le fichier source test2.java. La classe test1 est renomme test2 pour tenir compte du changement du nom du fichier source :
// paquetages imports import java.io.*; class personne{ // attributs private String prenom; // prnom de ma personne private String nom; // son nom private int age; // son ge // mthode public void initialise(String P, String N, int age){ this.prenom=P; this.nom=N; this.age=age; }//initialise // mthode public void identifie(){ System.out.println(prenom+","+nom+","+age); }//identifie }//classe
- 40 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public class test2{ public static void main(String arg[]){ personne p1=new personne(); p1.initialise("Jean","Dupont",30); p1.identifie(); } }
On notera que la classe personne n'a plus l'attribut public. En effer, dans un fichier source java, seule une classe peut avoir l'attribut public. C'est celle qui a la fonction main. Par ailleurs, le fichier source doit porter le nom de cette dernire. Compilons le fichier test2.java :
E:\data\serge\JAVA\BASES\OBJETS\3>dir 10/06/2002 09:36 633 test2.java E:\data\serge\JAVA\BASES\OBJETS\3>javac test2.java E:\data\serge\JAVA\BASES\OBJETS\3>dir 10/06/2002 09:36 633 test2.java 10/06/2002 09:41 832 personne.class 10/06/2002 09:41 418 test2.class
On remarquera qu'un fichier .class a t gnr pour chacune des classes prsentes dans le fichier source. Excutons maintenant le fichier test2.class :
E:\data\serge\JAVA\BASES\OBJETS\2>java test2 Jean,Dupont,30
Par la suite, on utilisera indiffremment les deux mthodes : classes rassembles dans un unique fichier source une classe par fichier source
On a maintenant deux mthodes portant le nom initialise : c'est lgal tant qu'elles admettent des paramtres diffrents. C'est le cas ici. Le paramtre est maintenant une rfrence P une personne. Les attributs de la personne P sont alors affects l'objet courant (this). On remarquera que la mthode initialise a un accs direct aux attributs de l'objet P bien que ceux-ci soient de type private. C'est toujours vrai : les mthodes d'un objet O1 d'une classe C a toujours accs aux attributs privs des autres objets de la mme classe C. Voici un test de la nouvelle classe personne :
// import personne; import java.io.*; public class test1{ public static void main(String arg[]){ personne p1=new personne(); p1.initialise("Jean","Dupont",30); System.out.print("p1="); p1.identifie(); personne p2=new personne();
- 41 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
et ses rsultats :
p1=Jean,Dupont,30 p2=Jean,Dupont,30
- 42 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public void initialise(personne P){ this.prenom=P.prenom; this.nom=P.nom; this.age=P.age; } // mthode public void identifie(){ System.out.println(prenom+","+nom+","+age); } }
Nos deux constructeurs se contentent de faire appel aux mthodes initialise correspondantes. On rappelle que lorsque dans un constructeur, on trouve la notation initialise(P) par exemple, le compilateur traduit par this.initialise(P). Dans le constructeur, la mthode initialise est donc appele pour travailler sur l'objet rfrenc par this, c'est dire l'objet courant, celui qui est en cours de construction. Voici un programme de test :
// import personne; import java.io.*; public class test1{ public static void main(String arg[]){ personne p1=new personne("Jean","Dupont",30); System.out.print("p1="); p1.identifie(); personne p2=new personne(p1); System.out.print("p2="); p2.identifie(); } }
- 43 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
p1 rfrence l'objet personne("Jean","Dupont",30) mais n'est pas l'objet lui-mme. En C, on dirait que c'est un pointeur, c.a.d. l'adresse de l'objet cr. Si on crit ensuite :
p1=null
Ce n'est pas l'objet personne("Jean","Dupont",30) qui est modifi, c'est la rfrence p1 qui change de valeur. L'objet personne("Jean","Dupont",30) sera "perdu" s'il n'est rfrenc par aucune autre variable. Lorsqu'on crit :
personne p2=p1;
on initialise le pointeur p2 : il "pointe" sur le mme objet (il dsigne le mme objet) que le pointeur p1. Ainsi si on modifie l'objet "point" (ou rfrenc) par p1, on modifie celui rfrenc par p2. Lorsqu'on crit :
personne p3=new personne(p1);
il y a cration d'un nouvel objet, copie de l'objet rfrenc par p1. Ce nouvel objet sera rfrenc par p3. Si on modifie l'objet "point" (ou rfrenc) par p1, on ne modifie en rien celui rfrenc par p3. C'est ce que montrent les rsultats obtenus.
- 44 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public personne(String P, String N, int age){ System.out.println("Constructeur personne(String, String, int)"); initialise(P,N,age); } public personne(personne P){ System.out.println("Constructeur personne(personne)"); initialise(P); }
- 45 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Pour le rfrencer, on crit personne.nbPersonnes pour montrer que c'est un attribut de la classe personne ellemme. Ici, nous avons cr un attribut priv auquel on n'aura pas accs directement en-dehors de la classe. On cre donc une mthode publique pour donner accs l'attribut de classe nbPersonnes. Pour rendre la valeur de nbPersonnes la mthode n'a pas besoin d'un objet particulier : en effet nbPersonnes n'est pas l'attribut d'un objet particulier, il est l'attribut de toute une classe. Aussi a-t-on besoin d'une mthode de classe dclare elle aussi static :
public static long getNbPersonnes(){ return nbPersonnes; }
qui de l'extrieur sera appele avec la syntaxe personne.getNbPersonnes(). Voici un exemple. La classe personne devient la suivante
public class personne{ // attribut de classe private static long nbPersonnes=0; // attributs d'objets # // constructeurs public personne(String P, String N, int age){ initialise(P,N,age); nbPersonnes++; } public personne(personne P){ initialise(P); nbPersonnes++; } // mthode
- 46 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
# // mthode de classe public static long getNbPersonnes(){ return nbPersonnes; } }// class
- 47 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
p1.identifie(); }// main private static void modifie(personne P){ System.out.print("Paramtre formel avant modification : "); P.identifie(); P.initialise("Sylvie","Vartan",52); System.out.print("Paramtre formel aprs modification : "); P.identifie(); }// modifie }// class
La mthode modifie est dclare static parce que c'est une mthode de classe : on n'a pas la prfixer par un objet pour l'appeler. Les rsultats obtenus sont les suivants :
Constructeur personne(String, String, Paramtre effectif avant modification Paramtre formel avant modification : Paramtre formel aprs modification : Paramtre effectif aprs modification int) : Jean,Dupont,30 Jean,Dupont,30 Sylvie,Vartan,52 : Sylvie,Vartan,52
On voit qu'il n'y a construction que d'un objet : celui de la personne p1 de la fonction main et que l'objet a bien t modifi par la fonction modifie.
La classe prcdente a un constructeur permettant d'initialiser un entier et deux mthodes permettant de lire et modifier la valeur de cet entier. On teste cette classe avec le programme suivant :
// import entieres; public class test2{ public static void main(String[] arg){ entieres I=new entieres(12); System.out.println("I="+I.getValue()); change(I); System.out.println("I="+I.getValue()); } private static void change(entieres entier){ entier.setValue(15); } }
- 48 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'instruction personne[] amis=new personne[3]; cre un tableau de 3 lments de type personne. Ces 3 lments sont initialiss ici avec la valeur null, c.a.d. qu'ils ne rfrencent aucun objet. De nouveau, par abus de langage, on parle de tableau d'objets alors que ce n'est qu'un tableau de rfrences d'objets. La cration du tableau d'objets, tableau qui est un objet lui-mme (prsence de new) ne cre donc en soi aucun objet du type de ses lments : il faut le faire ensuite. On obtient les rsultats suivants :
---------------Constructeur personne(String, String, int) Constructeur personne(String, String, int) Constructeur personne(String, String, int) Jean,Dupont,30 Sylvie,Vartan,52 Neil,Armstrong,66
- 49 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
parent ne sont pas rptes dans la dfinition de la classe fille : on se contente d'indiquer les attributs et mthodes rajouts par la classe fille :
class enseignant extends personne{ // attributs private int section; // constructeur public enseignant(String P, String N, int age,int section){ super(P,N,age); this.section=section; } }
La mthode identifie a t lgrement modifie pour rendre une chane de caractres identifiant la personne et porte maintenant le nom identite. Ici la classe enseignant rajoute aux mthodes et attributs de la classe personne : un attribut section qui est le n de section auquel appartient l'enseignant dans le corps des enseignants (une section par discipline en gros) un nouveau constructeur permettant d'initialiser tous les attributs d'un enseignant
- 50 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'instruction super(P,N,age) est un appel au constructeur de la classe parent, ici la classe personne. On sait que ce constructeur initialise les champs prenom, nom et age de l'objet personne contenu l'intrieur de l'objet tudiant. Cela parat bien compliqu et on pourrait prfrer crire :
// constructeur public enseignant(String P, String N, int age,int section){ this.prenom=P; this.nom=N this.age=age this.section=section; }
C'est impossible. La classe personne a dclar privs (private) ses trois champs prenom, nom et age. Seuls des objets de la mme classe ont un accs direct ces champs. Tous les autres objets, y compris des objets fils comme ici, doivent passer par des mthodes publiques pour y avoir accs. Cela aurait t diffrent si la classe personne avait dclar protgs (protected) les trois champs : elle autorisait alors des classes drives avoir un accs direct aux trois champs. Dans notre exemple, utiliser le constructeur de la classe parent tait donc la bonne solution et c'est la mthode habituelle : lors de la construction d'un objet fils, on appelle d'abord le constructeur de l'objet parent puis on complte les initialisations propres cette fois l'objet fils (section dans notre exemple). Tentons un premier programme :
// import personne; // import enseignant; public class test1{ public static void main(String arg[]){ System.out.println(new enseignant("Jean","Dupont",30,27).identite()); } }
Ce programme ce contente de crer un objet enseignant (new) et de l'identifier. La classe enseignant n'a pas de mthode identit mais sa classe parent en a une qui de plus est publique : elle devient par hritage une mthode publique de la classe enseignant. Les fichiers source des classes sont rassembls dans un mme rpertoire puis compils :
E:\data\serge\JAVA\BASES\OBJETS\4>dir 10/06/2002 10:00 765 personne.java 10/06/2002 10:00 212 enseignant.java 10/06/2002 10:01 192 test1.java E:\data\serge\JAVA\BASES\OBJETS\4>javac *.java E:\data\serge\JAVA\BASES\OBJETS\4>dir 10/06/2002 10/06/2002 10/06/2002 10/06/2002 10/06/2002 10/06/2002 10:00 10:00 10:01 10:02 10:02 10:02 765 personne.java 212 enseignant.java 192 test1.java 316 enseignant.class 1 146 personne.class 550 test1.class
- 51 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La mthode identite de la classe enseignant s'appuie sur la mthode identite de sa classe mre (super.identite) pour afficher sa partie "personne" puis complte avec le champ section qui est propre la classe enseignant. La classe enseignant dispose maintenant deux mthodes identite : celle hrite de la classe parent personne la sienne propre
Si E est un ojet enseignant, E.identite dsigne la mthode identite de la classe enseignant. On dit que la mthode identite de la classe mre est "surcharge" par la mthode identite de la classe fille. De faon gnrale, si O est un objet et M une mthode, pour excuter la mthode O.M, le systme cherche une mthode M dans l'ordre suivant : dans la classe de l'objet O dans sa classe mre s'il en a une dans la classe mre de sa classe mre si elle existe etc
L'hritage permet donc de surcharger dans la classe fille des mthodes de mme nom dans la classe mre. C'est ce qui permet d'adapter la classe fille ses propres besoins. Associe au polymorphisme que nous allons voir un peu plus loin, la surcharge de mthodes est le principal intrt de l'hritage. Considrons le mme exemple que prcdemment :
// import personne; // import enseignant; public class test1{ public static void main(String arg[]){ System.out.println(new enseignant("Jean","Dupont",30,27).identite()); } }
- 52 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
II-B-4 - Le polymorphisme
Considrons une ligne de classes : C0 -> C1 -> C2 -> # ->Cn o Ci -> Cj indique que la classe Cj est drive de la classe Ci. Cela entrane que la classe Cj a toutes les caractristiques de la classe Ci plus d'autres. Soient des objets Oi de type Ci. Il est lgal d'crire : Oi=Oj avec j>i En effet, par hritage, la classe Cj a toutes les caractristiques de la classe Ci plus d'autres. Donc un objet Oj de type Cj contient en lui un objet de type Ci. L'opration Oi=Oj fait que Oi est une rfrence l'objet de type Ci contenu dans l'objet Oj. Le fait qu'une variable Oi de classe Ci puisse en fait rfrencer non seulement un objet de la classe Ci mais en fait tout objet driv de la classe Ci est appel polyporphisme : la facult pour une variable de rfrencer diffrents types d'objets. Prenons un exemple et considrons la fonction suivante indpendante de toute classe :
public static void affiche(Object obj){ #. }
La classe Object est la "mre" de toutes les classes Java. Ainsi lorsqu'on crit :
public class personne
on crit implicitement :
public class personne extends Object
Ainsi tout objet Java contient en son sein une partie de type Object. Ainsi on pourra crire :
enseignant e; affiche(e);
Le paramtre formel de type Object de la fonction affiche va recevoir une valeur de type enseignant. Comme enseignant drive de Object, c'est lgal.
- 53 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La mthode obj.toString() rend une chane de caractres identifiant l'objet obj sous nom_de_la_classe@adresse_de_l'objet. Que se passe-t-il dans le cas de notre exemple prcdent :
enseignant e=new enseignant(...); affiche(e);
la
forme
Le systme devra excuter l'instruction System.out.println(e.toString()) o e est un objet enseignant. Il va chercher une mthode toString dans la hirarchie des classes menant la classe enseignant en commenant par la dernire : dans la classe enseignant, il ne trouve pas de mthode toString() dans la classe mre personne, il ne trouve pas de mthode toString() dans la classe mre Object, il trouve la mthode toString() et l'excute
C'est dire nom_de_la_classe@adresse_de_l'objet. Comme ce n'est pas trs explicite, on est tent de dfinir une mthode toString pour les classes personne et etudiant qui surchargeraient la mthode toString de la classe mre Object. Plutt que d'crire des mthodes qui seraient proches des mthodes identite dj existantes dans les classes personne et enseignant, contentons-nous de renommer toString ces mthodes identite :
public class personne{ ... public String toString(){ return "personne("+prenom+","+nom+","+age+")"; } ... } class enseignant extends personne{ int section; # public String toString(){ return "enseignant("+super.toString()+","+section+")"; } }
Avec le mme programme de test qu'auparavant, les rsultats obtenus sont les suivants :
enseignant(personne(Lucile,Dumas,56),61) personne(Jean,Dupont,30)
- 54 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La classe test1 contient la dfinition d'une autre classe, la classe article. On dit que article est une classe interne la classe test1. Cela peut tre utile lorsque la classe interne n'a d'utilit que dans la classe qui la contient. Lors de la compilation du source test1.java cidessus, on obtient deux fichiers .class :
E:\data\serge\JAVA\classes\interne>dir 05/06/2002 17:26 1 362 test1.java 05/06/2002 17:26 941 test1$article.class 05/06/2002 17:26 1 020 test1.class
- 55 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Un fichier test1$article.class a t gnr pour la classe article interne la classe test1. Si on excute le programme ci-dessus, on obtient les rsultats suivants :
E:\data\serge\JAVA\classes\interne>java test1 art=article(a100,velo,1000.0,10,5)
Les mthodes hasMoreElements() et nextElement() devront tre dfinies dans la classe C. Considrons le code suivant dfinissant une classe lve dfinissant le nom d'un lve et sa note dans une matire :
// une classe lve public class lve{ // des attributs publics public String nom; public double note; // constructeur public lve(String NOM, double NOTE){ nom=NOM; note=NOTE; }//constructeur }//lve
Nous dfinissons une classe notes rassemblant les notes de tous les lves dans une matire :
// classes importes // import lve // classe notes public class notes{ // attributs protected String matire; protected lve[] lves; // constructeur public notes (String MATIERE, lve[] ELEVES){ // mmorisation lves & matire matire=MATIERE; lves=ELEVES; }//notes // toString - 56 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public String toString(){ String valeur="matire="+matire +", notes=("; int i; // on concatne toutes les notes for (i=0;i<lves.length-1;i++){ valeur+="["+lves[i].nom+","+lves[i].note+"],"; }; //dernire note if(lves.length!=0){ valeur+="["+lves[i].nom+","+lves[i].note+"]";} valeur+=")"; // fin return valeur; }//toString }//classe
Les attributs matire et lves sont dclars protected pour tre accessibles d'une classe drive. Nous dcidons de driver la classe notes dans une classe notesStats qui aurait deux attributs supplmentaires, la moyenne et l'carttype des notes :
public class notesStats extends notes implements Istats { // attributs private double _moyenne; private double _cartType;
Cela signifie que la classe notesStats doit avoir deux mthodes appeles moyenne et cartType avec la signature indique dans l'interface Istats. La classe notesStats est la suivante :
// // // // classes importes import notes; import Istats; import lve;
public class notesStats extends notes implements Istats { // attributs private double _moyenne; private double _cartType; // constructeur public notesStats (String MATIERE, lve[] ELEVES){ // construction de la classe parente super(MATIERE,ELEVES); // calcul moyenne des notes double somme=0; for (int i=0;i<lves.length;i++){ somme+=lves[i].note; } if(lves.length!=0) _moyenne=somme/lves.length; else _moyenne=-1; // cart-type double carrs=0; for (int i=0;i<lves.length;i++){ carrs+=Math.pow((lves[i].note-_moyenne),2); }//for if(lves.length!=0) _cartType=Math.sqrt(carrs/lves.length); else _cartType=-1; }//constructeur // ToString public String toString(){ return super.toString()+",moyenne="+_moyenne+",cart-type="+_cartType;
- 57 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}//ToString // mthodes de l'interface Istats public double moyenne(){ // rend la moyenne des notes return _moyenne; }//moyenne public double cartType(){ // rend l'cart-type return _cartType; }//cartType }//classe
La moyenne _moyenne et l'cart-type _ecartType sont calculs ds la construction de l'objet. Aussi les mthodes moyenne et cartType n'ont-elles qu' rendre la valeur des attributs _moyenne et _ecartType. Les deux mthodes rendent -1 si le tableau des lves est vide. La classe de test suivante :
// // // // // classes importes import lve; import Istats; import notes; import notesStats;
// classe de test public class test{ public static void main(String[] args){ // qqs lves & notes lve[] ELEVES=new lve[] { new lve("paul",14),new lve("nicole",16), new lve("jacques",18)}; // qu'on enregistre dans un objet notes notes anglais=new notes("anglais",ELEVES); // et qu'on affiche System.out.println(""+anglais); // idem avec moyenne et cart-type anglais=new notesStats("anglais",ELEVES); System.out.println(""+anglais); }//main }//classe
Les diffrentes classes de cet exemple font toutes l'objet d'un fichier source diffrent :
E:\data\serge\JAVA\interfaces\notes>dir 06/06/2002 14:06 707 notes.java 06/06/2002 14:06 878 notes.class 06/06/2002 14:07 1 160 notesStats.java 06/06/2002 14:02 101 Istats.java 06/06/2002 14:02 138 Istats.class 06/06/2002 14:05 247 lve.java 06/06/2002 14:05 309 lve.class 06/06/2002 14:07 1 103 notesStats.class 06/06/2002 14:10 597 test.java 06/06/2002 14:10 931 test.class
La classe notesStats aurait trs bien pu implmenter les mthodes moyenne et cartType pour elle-mme sans indiquer qu'elle implmentait l'interface Istats. Quel est donc l'intrt des interfaces ? C'est le suivant : une fonction
- 58 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
peut admettre pour paramtre une donne ayant le type d'une interface I. Tout objet d'une classe C implmentant l'interface I pourra alors tre paramtre de cette fonction. Considrons l'interface suivante :
// une interface Iexemple public interface Iexemple{ int ajouter(int i,int j); int soustraire(int i,int j); }//interface
L'interface Iexemple dfinit deux mthodes ajouter et soustraire. Les classes classe1 et classe2 suivantes implmentent cette interface.
// classes importes // import Iexemple; public class classe1 implements Iexemple{ public int ajouter(int a, int b){ return a+b+10; } public int soustraire(int a, int b){ return a-b+20; } }//classe // classes importes // import Iexemple; public class classe2 implements Iexemple{ public int ajouter(int a, int b){ return a+b+100; } public int soustraire(int a, int b){ return a-b+200; } }//classe
Par souci de simplification de l'exemple les classes ne font rien d'autre que d'implmenter l'interface Iexemple. Maintenant considrons l'exemple suivant :
// classes importes // import classe1; // import classe2; // classe de test public class test{ // une fonction statique private static void calculer(int i, int j, Iexemple inter){ System.out.println(inter.ajouter(i,j)); System.out.println(inter.soustraire(i,j)); }//calculer // la fonction main public static void main(String[] arg){ // cration de deux objets classe1 et classe2 classe1 c1=new classe1(); classe2 c2=new classe2(); // appels de la fonction statique calculer calculer(4,3,c1); calculer(14,13,c2); }//main }//classe test
La fonction statique calculer admet pour paramtre un lment de type Iexemple. Elle pourra donc recevoir pour ce paramtre aussi bien un objet de type classe1 que de type classe2. C'est ce qui est fait dans la fonction main avec les rsultats suivants :
17
- 59 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
21 127 201
On voit donc qu'on a l une proprit proche du polymorphisme vu pour les classes. Si donc un ensemble de classes Ci non lies entre-elles par hritage (donc on ne peut utiliser le polymorphisme de l'hritage) prsentent un ensemble de mthodes de mme signature, il peut tre intressant de regrouper ces mthodes dans une interface I dont hriteraient toutes les classes concernes. Des instances de ces classes Ci peuvent alors tre utilises comme paramtres de fonctions admettant un paramtre de type I, c.a.d. des fonctions n'utilisant que les mthodes des objets Ci dfinies dans l'interface I et non les attributs et mthodes particuliers des diffrentes classes Ci. Dans l'exemple prcdent, chaque classe ou interface faisait l'objet d'un fichier source spar :
E:\data\serge\JAVA\interfaces\oprations>dir 06/06/2002 14:33 128 Iexemple.java 06/06/2002 14:34 218 classe1.java 06/06/2002 14:32 220 classe2.java 06/06/2002 14:33 144 Iexemple.class 06/06/2002 14:34 325 classe1.class 06/06/2002 14:34 326 classe2.class 06/06/2002 14:36 583 test.java 06/06/2002 14:36 628 test.class
Notons enfin que l'hritage d'interfaces peut tre multiple, c.a.d. qu'on peut crire
public class classeDrive extends classeDeBase implements i1,i2,..,in{ ... }
- 60 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
return a+b+10; } public int soustraire(int a, int b){ return a-b+20; } };//dfinition i1 Iexemple i2=new Iexemple(){ public int ajouter(int a, int b){ return a+b+100; } public int soustraire(int a, int b){ return a-b+200; } };//dfinition i2 // un autre objet Iexemple Iexemple i3=new classe3(); // appels de la fonction statique calculer calculer(4,3,i1); calculer(14,13,i2); calculer(24,23,i3); }//main }//classe test
On cre un objet i1 dont le seul rle est d'implmenter l'interface Iexemple. Cet objet est de type Iexemple. On peut donc crer des objets de type interface. De trs nombreuses mthodes de classes Java rendent des objets de type interface c.a.d. des objets dont le seul rle est d'implmenter les mthodes d'une interface. Pour crer l'objet i1, on pourrait tre tent d'crire :
Iexemple i1=new Iexemple()
Seulement une interface ne peut tre instantie. Seule une classe implmentant cette interface peut l'tre. Ici, on dfinit une telle classe " la vole" dans le corps mme de la dfinition de l'objet i1 :
Iexemple i1=new Iexemple(){ public int ajouter(int a, int b){ // dfinition de ajouter } public int soustraire(int a, int b){ // dfinition de soustraire } };//dfinition i1
- 61 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// dfinition de soustraire } };//dfinition classe1 ................. public static void main(String[] arg){ ........... Iexemple i1=new classe1(); }//main }//classe
Dans l'exemple ci-dessus, on instantie bien une classe et non pas une interface. Une classe dfinie " la vole" est dite une classe anonyme. C'est une mthode souvent utilise pour instantier des objets dont le seul rle est d'implmenter une interface. L'excution du programme prcdent donne les rsultats suivants :
17 21 127 201 1047 2001
L'exemple prcent utilisait des classes anonymes pour implmenter une interface. Celles-ci peuvent tre utilises galement pour driver des classes n'ayant pas de constructeurs avec paramtres. Considrons l'exemple suivant :
// classes importes // import Iexemple; class classe3 implements Iexemple{ public int ajouter(int a, int b){ return a+b+1000; } public int soustraire(int a, int b){ return a-b+2000; } };//dfinition classe3 public class test4{ // une fonction statique private static void calculer(int i, int j, Iexemple inter){ System.out.println(inter.ajouter(i,j)); System.out.println(inter.soustraire(i,j)); }//calculer // mthode main public static void main(String args[]){ // dfinition d'une classe anonym drivant classe3 // pour redfinir soustraire classe3 i1=new classe3(){ public int ajouter(int a, int b){ return a+b+10000; }//soustraire };//i1 // appels de la fonction statique calculer calculer(4,3,i1); }//main }//classe
Nous y retrouvons une classe classe3 implmentant l'interface Iexemple. Dans la fonction main, nous dfinissons une variable i1 ayant pour type, une classe drive de classe3. Cette classe drive est dfinie " la vole" dans une classe anonyme et redfinit la mthode ajouter de la classe classe3. La syntaxe est identique celle de la classe anonyme implmentant une interface. Seulement ici, le compilateur dtecte que classe3 n'est pas une interface mais une classe. Pour lui, il s'agit alors d'une drivation de classe. Toutes les mthodes qu'il trouvera dans le corps de la classe anonyme remplaceront les mthodes de mme nom de la classe de base.
- 62 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Si nous regardons la dfinition de la classe System nous dcouvrons qu'elle s'appelle en fait java.lang.System :
au lieu de
java.lang.System.out.println("Coucou");
Parce que de faon implicite, il y a pour tout programme Java, une importation systmatique du "paquetage" java.lang. Ainsi tout se passe comme si on avait au dbut de tout programme l'instruction :
import java.lang.*;
- 63 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Que signifie cette instruction ? Elle donne accs toutes les classes du paquetage java.lang. Le compilateur y trouvera le fichier System.class dfinissant la classe System. On ne sait pas encore o le compilateur trouvera le paquetage java.lang ni quoi un paquetage ressemble. Nous y reviendrons. Pour crer une classe dans un paquetage, on crit :
package paquetage; // dfinition de la classe ...
Pour l'exemple, crons dans un paquetage notre classe personne tudie prcdemment. Nous choisirons istia.st comme nom de paquetage. La classe personne devient :
// nom du paquetage dans lequel sera cr la classe personne package istia.st; // classe personne public class personne{ // nom, prnom, ge private String prenom; private String nom; private int age; // constructeur 1 public personne(String P, String N, int age){ this.prenom=P; this.nom=N; this.age=age; } // toString public String toString(){ return "personne("+prenom+","+nom+","+age+")"; } }//classe
Cette classe est compile puis place dans un rpertoire istia\st du rpertoire courant. Pourquoi istia\st ? Parce que le paquetage s'appelle istia.st.
E:\data\serge\JAVA\classes\paquetages\personne>dir 06/06/2002 16:28 467 personne.java 06/06/2002 16:04 <DIR> istia E:\data\serge\JAVA\classes\paquetages\personne>dir istia 06/06/2002 16:04 <DIR> st E:\data\serge\JAVA\classes\paquetages\personne>dir istia\st 06/06/2002 16:28 675 personne.class
On remarquera que la classe personne est maintenant prfixe du nom de son paquetage istia.st. O le compilateur trouvera-t-il la classe istia.st.personne ? Le compilateur cherche les classes dont il a besoin dans une liste prdfinie de rpertoires et dans une arborescence partant du rpertoire courant. Ici, il cherchera la classe istia.st.personne dans un fichier istia\st\personne.class. C'est pourquoi nous avons mis le fichier personne.class dans le rpertoire istia\st. Compilons puis excutons le programme de test :
E:\data\serge\JAVA\classes\paquetages\personne>dir 06/06/2002 16:28 467 personne.java
- 64 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
06/06/2002 16:06 246 test.java 06/06/2002 16:04 <DIR> istia 06/06/2002 16:06 738 test.class E:\data\serge\JAVA\classes\paquetages\personne>java test p1=personne(Jean,Dupont,20)
Nous avons mis le paquetage istia.st dans le rpertoire courant. Ce n'est pas obligatoire. Mettons-le dans un dossier appel mesClasses toujours dans le rpertoire courant. Rappelons que les classes du paquetage istia.st sont places dans un dossier istia\st. L'arborescence du rpertoire courant est la suivante :
E:\data\serge\JAVA\classes\paquetages\personne>dir 06/06/2002 16:28 467 personne.java 06/06/2002 16:06 246 test.java 06/06/2002 16:06 738 test.class 06/06/2002 16:47 236 test2.java 06/06/2002 16:50 740 test2.class 06/06/2002 16:21 <DIR> mesClasses E:\data\serge\JAVA\classes\paquetages\personne>dir mesClasses
- 65 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
06/06/2002 16:22 <DIR> istia E:\data\serge\JAVA\classes\paquetages\personne>dir mesClasses\istia 06/06/2002 16:22 <DIR> st E:\data\serge\JAVA\classes\paquetages\personne>dir mesClasses\istia\st 06/06/2002 16:01 1 153 personne.class
Le compilateur ne trouve plus le paquetage istia.st depuis qu'on l'a dplac. Remarquons qu'il le cherche cause de l'instruction import. Par dfaut, il le cherche partir du rpertoire courant dans un dossier appel istia\st qui n'existe plus. Examinons les options du compilateur :
E:\data\serge\JAVA\classes\paquetages\personne>javac Usage: javac <options> <source files> where possible options include: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -O Optimize; may hinder debugging or enlarge class file -nowarn Generate no warnings -verbose Output messages about what the compiler is doing -deprecation Output source locations where deprecated APIs are used -classpath <path> Specify where to find user class files -sourcepath <path> Specify where to find input source files -bootclasspath <path> Override location of bootstrap class files -extdirs <dirs> Override location of installed extensions -d <directory> Specify where to place generated class files -encoding <encoding> Specify character encoding used by source files -source <release> Provide source compatibility with specified release -target <release> Generate class files for specific VM version -help Print a synopsis of standard options
Ici l'option -classpath peut nous tre utile. Elle permet d'indiquer au compilateur o chercher ses classes et paquetages. Essayons. Compilons en disant au compilateur que le paquetage istia.st est dsormais dans le dossier mesClasses :
E:\data\serge\JAVA\classes\paquetages\personne>javac -classpath mesClasses test2.java E:\data\serge\JAVA\classes\paquetages\personne>dir 06/06/2002 16:47 236 test2.java 06/06/2002 17:03 740 test2.class 06/06/2002 16:21 <DIR> mesClasses
C'est maintenant au tour de la machine virtuelle Java de ne pas trouver la classe istia/st/personne. Elle la cherche dans le rpertoire courant alors qu'elle est maintenant dans le rpertoire mesClasses. Regardons les options de la machine virtuelle Java :
E:\data\serge\JAVA\classes\paquetages\personne>java Usage: java [-options] class [args...] (to execute a class) or java -jar [-options] jarfile [args...] (to execute a jar file)
- 66 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
where options include: -client to select the "client" VM -server to select the "server" VM -hotspot is a synonym for the "client" VM [deprecated] The default VM is client. -cp -classpath <directories and zip/jar files separated by ;> set search path for application classes and resources -D<name>=<value> set a system property -verbose[:class|gc|jni] enable verbose output -version print product version and exit -showversion print product version and continue -? -help print this help message -X print help on non-standard options -ea[:<packagename>...|:<classname>] -enableassertions[:<packagename>...|:<classname>] enable assertions -da[:<packagename>...|:<classname>] -disableassertions[:<packagename>...|:<classname>] disable assertions -esa | -enablesystemassertions enable system assertions -dsa | -disablesystemassertions disable system assertions
On voit que la JVM a galement une option classpath comme le compilateur. Utilisons-la pour lui dire o se trouve le paquetage istia.st :
E:\data\serge\JAVA\classes\paquetages\personne>java.bat -classpath mesClasses test2 Exception in thread "main" java.lang.NoClassDefFoundError: test2
On n'a pas beaucoup progress. C'est maintenant la classe test2 elle-mme qui n'est pas trouve. Pour la raison suivante : en l'absence du mot cl classpath, le rpertoire courant est systmatiquement explor lors de la recherche de classes mais pas lorsqu'il est prsent. Du coup, la classe test2.class qui se trouve dans le rpertoire courant n'est pas trouve. La solution ? Ajouter le rpertoire courant au classpath. Le rpertoire courant est reprsent par le symbole .
E:\data\serge\JAVA\classes\paquetages\personne>java -classpath mesClasses;. test2 p1=personne(Jean,Dupont,20)
Pourquoi toutes ces complications ? Le but des paquetages est d'viter les conflits de noms entre classes. Considrons deux entreprises E1 et E2 distribuant des classes empaquetes respectivement dans les paquetages com.e1 et com.e2. Soit un client C qui achte ces deux ensembles de classes dans lesquelles les deux entreprises ont dfini toutes deux une classe personne. Le client C rfrencera la classe personne de l'entreprise E1 par com.e1.personne et celle de l'entreprise E2 par com.e2.personne vitant ainsi un conflit de noms.
pour avoir accs toutes les classes du paquetage java.util, o celui-ci est-il trouv ? Nous avons dit que les paquetages taient cherchs par dfaut dans le rpertoire courant ou dans la liste des rpertoires dclars dans l'option classpath du compilateur ou de la JVM si cette option est prsente. Ils sont galement cherchs dans les rpertoires lib du rpertoire d'installation du JDK. Considrons ce rpertoire :
- 67 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Dans cet exemple, les arborescences jdk14\lib et jdk14\jre\lib seront explores pour y chercher soit des fichiers .class, soit des fichiers .jar ou .zip qui sont des archives de classes. Faisons par exemple une recherche des fichiers .jar se trouvant sous le rpertoire jdk14 prcdent :
Il y en a plusieurs dizaines. Un fichier .jar peut s'ouvrir avec l'utilitaire winzip. Ouvrons le fichier rt.jar ci-dessus (rt=RunTime). On y trouve plusieurs centaines de fichiers .class dont celles appartenant au paquetage java.util :
- 68 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Une mthode simple pour grer les paquetages est alors de les placer dans le rpertoire <jdk>\jre\lib o <jdk> est le rpertoire d'installation du JDK. En gnral, un paquetage contient plusieurs classes et il est pratique de rassembler celles-ci dans un unique fichier .jar (JAR=Java ARchive file). L'excutable jar.exe se trouve dans le dossier <jdk>\bin :
E:\data\serge\JAVA\classes\paquetages\personne>dir "e:\program files\jdk14\bin\jar.exe" 07/02/2002 12:52 28 752 jar.exe
Une aide l'utilisation du programme jar peut tre obtenue en l'appelant sans paramtres :
E:\data\serge\JAVA\classes\paquetages\personne>"e:\program files\jdk14\bin\jar.exe" Syntaxe : jar {ctxu}[vfm0M] [fichier-jar] [fichier-manifest] [rp -C] fichiers ... Options : -c crer un nouveau fichier d''archives -t gnrer la table des matires du fichier d''archives -x extraire les fichiers nomms (ou tous les fichiers) du fichier d''archives -u mettre jour le fichier d''archives existant -v gnrer des informations verbeuses sur la sortie standard -f spcifier le nom du fichier d''archives -m inclure les informations manifest provenant du fichier manifest spcifi -0 stocker seulement ; ne pas utiliser la compression ZIP -M ne pas crer de fichier manifest pour les entres -i gnrer l''index pour les fichiers jar spcifis -C passer au rpertoire spcifi et inclure le fichier suivant Si un rpertoire est spcifi, il est trait rcursivement. Les noms des fichiers manifest et d''archives doivent tre spcifis dans l''ordre des indicateurs ''m'' et ''f''. Exemple 1 : pour archiver deux fichiers de classe dans le fichier d''archives classes.jar : jar cvf classes.jar Foo.class Bar.class Exemple 2 : utilisez le fichier manifest existant ''monmanifest'' pour archiver tous les fichiers du rpertoire foo/ dans ''classes.jar'': jar cvfm classes.jar monmanifest -C foo/ .
- 69 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
E:\data\serge\JAVA\classes\paquetages\personne>dir istia 06/06/2002 16:04 <DIR> st E:\data\serge\JAVA\classes\paquetages\personne>dir istia\st 06/06/2002 16:28 675 personne.class
Crons un fichier istia.st.jar archivant toutes les classes du paquetage istia.st donc toutes les classes de l'arborescence istia\st ci-dessus :
E:\data\serge\JAVA\classes\paquetages\personne>"e:\program files\jdk14\bin\jar" cvf istia.st.jar istia\st\* E:\data\serge\JAVA\classes\paquetages\personne>dir 06/06/2002 16:28 467 personne.java 06/06/2002 17:36 195 test.java 06/06/2002 16:04 <DIR> istia 06/06/2002 16:06 738 test.class 06/06/2002 16:47 236 test2.java 06/06/2002 18:15 740 test2.class 06/06/2002 18:08 874 istia.st.jar
On remarque qu'on n'a eu qu' citer le nom de l'archive explorer sans avoir dire explicitement o elle se trouvait. Tous les rpertoires de l'arborescence <jdk>\jre\lib sont explors pour trouver le fichier .jar demand.
- 70 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
on calcule son coefficient familial QF=R/nbParts on calcule son impt I. Considrons le tableau suivant : 12620.0 13190 15640 24740 31810 39970 48360 55790 92970 127860 151250 172040 195000 0 0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.50 0.55 0.60 0.65 0 631 1290.5 2072.5 3309.5 4900 6898.5 9316.5 12106 16754.5 23147.5 30710 39312 49062
Chaque ligne a 3 champs. Pour calculer l'impt I, on recherche la premire ligne o QF<=champ1. Par exemple, si QF=23000 on trouvera la ligne 24740 0.15 2072.5 L'impt I est alors gal 0.15*R - 2072.5*nbParts. Si QF est tel que la relation QF<=champ1 n'est jamais vrifie, alors ce sont les coefficients de la dernire ligne qui sont utiliss. Ici : 0 0.65 49062 ce qui donne l'impt I=0.65*R - 49062*nbParts. La classe impots sera dfinie comme suit :
// cration d'une classe impots public class impots{ // les donnes ncessaires au calcul de l'impt // proviennent d'une source extrieure private double[] limites, coeffR, coeffN; // constructeur public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception{ // on vrifie que les 3 tableaux ont la mme taille boolean OK=LIMITES.length==COEFFR.length && LIMITES.length==COEFFN.length; if (! OK) throw new Exception ("Les 3 tableaux fournis n'ont pas la mme taille("+ LIMITES.length+","+COEFFR.length+","+COEFFN.length+")"); // c'est bon this.limites=LIMITES; this.coeffR=COEFFR; this.coeffN=COEFFN; }//constructeur // calcul de l'impt public long calculer(boolean mari, int nbEnfants, int salaire){ // calcul du nombre de parts double nbParts; if (mari) nbParts=(double)nbEnfants/2+2; else nbParts=(double)nbEnfants/2+1; if (nbEnfants>=3) nbParts+=0.5;
- 71 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// calcul revenu imposable & Quotient familial double revenu=0.72*salaire; double QF=revenu/nbParts; // calcul de l'impt limites[limites.length-1]=QF+1; int i=0; while(QF>limites[i]) i++; // retour rsultat return (long)(revenu*coeffR[i]-nbParts*coeffN[i]); }//calculer }//classe
Un objet impots est cr avec les donnes permettant le calcul de l'impt d'un contribuable. C'est la partie stable de l'objet. Une fois cet objet cr, on peut appeler de faon rpte sa mthode calculer qui calcule l'impt du contribuable partir de son statut marital (mari ou non), son nombre d'enfants et son salaire annuel. Un programme de test pourait tre le suivant :
//classes importes // import impots; import java.io.*; public class test { public static void main(String[] arg) throws IOException { // programme interactif de calcul d'impt // l'utilisateur tape trois donnes au clavier : mari nbEnfants salaire // le programme affiche alors l'impt payer final String syntaxe="syntaxe : mari nbEnfants salaire\n" +"mari : o pour mari, n pour non mari\n" +"nbEnfants : nombre d'enfants\n" +"salaire : salaire annuel en F"; // tableaux de donnes ncessaires au calcul de l'impt double[] limites=new double[] {12620,13190,15640,24740,31810,39970,48360,55790,92970,127860,151250,172040,195000,0}; double[] coeffR=new double[] {0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65}; double[] coeffN=new double[] {0,631,1290.5,2072.5,3309.5,4900,6898.5,9316.5,12106,16754.5,23147.5,30710,39312,49062}; // cration d'un flux de lecture BufferedReader IN=new BufferedReader(new InputStreamReader(System.in)); // cration d'un objet impt impots objImpt=null; try{ objImpt=new impots(limites,coeffR,coeffN); }catch (Exception ex){ System.err.println("L'erreur suivante s'est produite : " + ex.getMessage()); System.exit(1); }//try-catch // boucle infinie while(true){ // on demande les paramtres du calcul de l'impt System.out.print("Paramtres du calcul de l'impt au format mari nbEnfants salaire ou rien pour arrter :"); String paramtres=IN.readLine().trim(); // qq chose faire ? if(paramtres==null || paramtres.equals("")) break; // vrification du nombre d'arguments dans la ligne saisie String[] args=paramtres.split("\\s+"); int nbParamtres=args.length; if (nbParamtres!=3){ System.err.println(syntaxe); continue; }//if // vrification de la validit des paramtres // mari String mari=args[0].toLowerCase();
- 72 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
if (! mari.equals("o") && ! mari.equals("n")){ System.err.println(syntaxe+"\nArgument mari incorrect : tapez o ou n"); continue; }//if // nbEnfants int nbEnfants=0; try{ nbEnfants=Integer.parseInt(args[1]); if(nbEnfants<0) throw new Exception(); }catch (Exception ex){ System.err.println(syntaxe+"\nArgument nbEnfants incorrect : tapez un entier positif ou nul"); continue; }//if // salaire int salaire=0; try{ salaire=Integer.parseInt(args[2]); if(salaire<0) throw new Exception(); }catch (Exception ex){ System.err.println(syntaxe+"\nArgument salaire incorrect : tapez un entier positif ou nul"); continue; }//if // les paramtres sont corrects - on calcule l'impt System.out.println("impt="+objImpt.calculer(mari.equals("o"),nbEnfants,salaire)+" F"); // contribuable suivant }//while }//main }//classe
- 73 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
III-A - La documentation
Si vous avez install le JDK de Sun dans le dossier <jdk>, la documentation est disponible dans le dossier <jdk>\docs :
Quelquefois on a un jdk mais sans documentation. Celle-ci peut tre trouve sur le site de Sun http://www.sun.com. Dans le dossier docs on trouve un fichier index.html qui est le point de dpart de l'aide du JDK :
Le lien API & Language ci-dessus donne accs aux classes Java. Le lien Demos/Tutorials est particulirement utile pour avoir des exemples de programmes Java. Suivons le lien API & Language :
Cette page est le vritable point de dpart de la documentation sur les classes. On pourra crer un raccourci dessus pour y avoir un accs rapide. L'URL est <jdk>\docs\api\index.html. On y trouve des liens sur les centaines de classes Java du JDK. Lorsqu'on dbute, la principale difficult est de savoir ce que font ces diffrentes classes. Dans un premier temps, cette aide n'a donc d'intrt que si on connat le nom de la classe sur laquelle on veut des informations. On peut aussi se laisser guider par les noms des classes qui indiquent normalement le rle de la classe. Prenons un exemple et cherchons des informations sur la classe Vector qui implmente un tableau dynamique. Il suffit de chercher dans la liste des classes du cadre de gauche le lien de la classe Vector :
- 75 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On y trouve la hirarchie dans laquelle se trouve la classe, ici java.util.Vector la liste des champs (attributs) de la classe la liste des constructeurs la liste des mthodes
Par la suite, nous prsentons diverses classes. Nous invitons le lecteur systmatiquement vrifier la dfinition complte des classes utilises.
return prenom; } public String getNom(){ return nom; } public int getAge(){ return age; } //modifieurs public void setPrenom(String P){ this.prenom=P; } public void setNom(String N){ this.nom=N; } public void setAge(int age){ this.age=age; } }
La classe enseignant est drive de la classe personne et est dfinie comme suit :
class enseignant extends personne{ // attributs private int section; // constructeur public enseignant(String P, String N, int age,int section){ super(P,N,age); this.section=section; } // toString public String toString(){ return "etudiant("+super.toString()+","+section+")"; } }
Nous utiliserons galement une classe etudiant drive de la classe personne et dfinie comme suit :
class etudiant extends personne{ String numero; public etudiant(String P, String N, int age,String numero){ super(P,N,age); this.numero=numero; } public String toString(){ return "etudiant("+super.toString()+","+numero+")"; } }
- 77 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La classe String est riche d'attributs et mthodes. En voici quelques-uns : public char charAt(int i) donne le caractre i de la chane, le premier caractre ayant l'indice 0. Ainsi String("cheval").charAt(3) est gal 'v' chaine1.compareTo(chaine2) compare chaine1 chaine2 et rend 0 si chaine1=chaine2, 1 su chaine1>chaine2, -1 si chaine1<chaine2 chaine1.equals(chaine2) rend vrai si chaine1=chaine2, faux sinon chaine1.toLowerCase() rend chaine1 en minuscules chaine1.toUpperCase() rend chaine1 en majuscules chaine1.trim() rend chaine1 dbarasse de ses espaces de dbut et de fin String("chapeau").subString(2,4) rend la chane "ape" permet de mettre les caractres de la chane dans un tableau de caractres nombre de caractres de la chane rend la premire position de chaine2 dans la chane courante ou -1 si chaine2 n'est pas prsente rend la premire position de chaine2 dans la chane courante ou -1 si chaine2 n'est pas prsente. La recherche commence partir du caractre n startIndex. rend la dernire position de chaine2 dans la chane courante ou -1 si chaine2 n'est pas prsente rend vrai si la chane courante commence par chaine2 rend vrai si la chane courante finit par chaine2 rend vrai si la chane courante correspond l'expression rgulire regex. La chane courante est compose de champs spars par une chane de caractres modlise par l'expression rgulire regex. La mthode split permet de rcuprer les champs dans un tableau. remplace dans la chane courante le caractre oldChar par le caractre newChar.
public boolean equals(Object anObject) public String toLowerCase() public String toUpperCase() public String trim() public String substring(int beginIndex, int endIndex) public char[] toCharArray() int length() int indexOf(String chaine2)
boolean startsWith(String chaine2) boolean endsWith(String chaine2) boolean matches(String regex) String[] split(String regex)
- 78 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
affiche("uneChaine.IndexOf(\"vole\")="+uneChaine.indexOf("vole")); affiche("uneChaine.IndexOf(\"x\")="+uneChaine.indexOf("x")); affiche("uneChaine.LastIndexOf('a')="+uneChaine.lastIndexOf('a')); affiche("uneChaine.LastIndexOf('x')="+uneChaine.lastIndexOf('x')); affiche("uneChaine.substring(4,7)="+uneChaine.substring(4,7)); affiche("uneChaine.ToUpper()="+uneChaine.toUpperCase()); affiche("uneChaine.ToLower()="+uneChaine.toLowerCase()); affiche("uneChaine.Replace('a','A')="+uneChaine.replace('a','A')); String[] champs=uneChaine.split("\\s+"); for (int i=0;i<champs.length;i++){ affiche("champs["+i+"]=["+champs[i]+"]"); }//for affiche("(\" abc \").trim()=["+" abc ".trim()+"]"); }//Main // affiche public static void affiche(String msg){ // affiche msg System.out.println(msg); }//affiche }//classe
- 79 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Compilons ce programme :
E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>dir 10/06/2002 10:41 1 134 personne.class 10/06/2002 10:41 619 enseignant.class 10/06/2002 10:41 610 etudiant.class 10/06/2002 10:42 1 035 test1.java E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>javac test1.java E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>dir 10/06/2002 10:41 1 134 personne.class 10/06/2002 10:41 619 enseignant.class 10/06/2002 10:41 610 etudiant.class 10/06/2002 10:42 1 035 test1.java 10/06/2002 10:43 1 506 test1.class
Par la suite, nous ne rpterons plus le processus de compilation et d'excution des programmes de tests. Il suffit de reproduire ce qui a t fait ci-dessus.
- 80 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
construit un tableau vide nombre d'lment du tableau ajoute l'objet rfrenc par obj au tableau ajoute l'objet rfrenc par obj au tableau en position index rfrence de l'objet n index du tableau - les indices commencent 0 rend vrai si le tableau est vide enlve l'lment d'indice index vide le tableau de tous ses lments met le tableau dynamique dans un tableau classique rend une chane d'identification du tableau
- 81 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 82 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// fonction de test public static void main(String[] arg){ new sort2(); }//main }//classe
Examinons ce programme. La fonction main cre un objet sort2. Le constructeur de la classe sort2 est le suivant :
// constructeur public sort2() { // un tableau de personnes personne[] amis=new personne[]{new personne("tintin",100),new personne("milou",80), new personne("tournesol",40)}; // tri du tableau de personnes Arrays.sort(amis,this); // vrification for(int i=0;i<3;i++) System.out.println(amis[i]); }//constructeur
Le tableau trier est un tableau d'objets personne. La classe personne est dfinie de faon prive (private) l'intrieur de la classe sort2. La mthode statique sort de la classe Arrays ne sait pas comment trier un tableau d'objets personne, aussi est-on oblig ici d'utiliser la forme void sort(Object[] obj, Comparator C). Comparator est une interface ne dfinissant qu'une mthode :
int compare(Object o1, Object o2)
Dans le prototype void sort(Object[] obj, Comparator C) le second argument C doit tre un objet implmentant l'interface Comparator. Dans le constructeur sort2, on a choisi l'objet courant this :
// tri du tableau de personnes Arrays.sort(amis,this);
Ceci nous oblige faire deux choses : 1. indiquer que la classe sort2 implmente l'interface Comparator
public class sort2 implements Comparator{
- 83 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Pour comparer deux objets personne, on utilise ici l'ge (on aurait pu utiliser le nom). Les rsultats de l'excution sont les suivants :
[tournesol,40] [milou,80] [tintin,100]
- 84 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le second paramtre de la mthode sort doit tre un objet implmentant l'interface Comparator. Ici nous crons un tel objet par new java.util.Comparator() et le texte qui suit {#.} dfinit la classe dont on cre un objet. On appelle cela une classe anonyme car elle ne porte pas de nom. Dans cette classe anonyme qui doit implmenter l'interface Comparator, on dfinit la mthode compare de cette interface. Celle-ci se contente d'appeler la mthode compare1 de la classe sort2. On est alors ramen au cas prcdent. La classe sort2 n'implmente plus l'interface Comparator. Aussi sa dclaration devient-elle :
public class sort2 {
Maintenant nous testons la mthode binarySearch de la classe Arrays sur l'exemple suivant :
import java.util.*; public class sort4 { // une classe prive interne private class personne{ // attributs private String nom; private int age; // constructeur public personne(String nom, int age){ this.nom=nom; // nom de la personne this.age=age; // son ge } // rcuprer le nom public String getNom(){ return nom; } // rcuprer l'ge public int getAge(){ return age; } // identit de la personne public String toString(){ return ("["+nom+","+age+"]"); } }; // classe personne // constructeur public sort4() { // un tableau de personnes personne[] amis=new personne[]{new personne("tintin",100),new personne("milou",80), new personne("tournesol",40)}; // des comparateurs java.util.Comparator comparateur1= new java.util.Comparator(){ public int compare(Object o1, Object o2){ return compare1(o1,o2); }//compare }//classe ; java.util.Comparator comparateur2= new java.util.Comparator(){ public int compare(Object o1, Object o2){ return compare2(o1,o2); }//compare }//classe ; // tri du tableau de personnes Arrays.sort(amis,comparateur1); // vrification for(int i=0;i<3;i++) System.out.println(amis[i]); - 85 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// recherches cherche("milou",amis,comparateur2); cherche("xx",amis,comparateur2); }//constructeur // la fonction qui compare des personnes public int compare1(Object o1, Object o2){ // doit rendre // -1 si o1 "plus petit que" o2 // 0 si o1 "gal " o2 // +1 si o1 "plus grand que" o2 personne p1=(personne)o1; personne p2=(personne)o2; int age1=p1.getAge(); int age2=p2.getAge(); if(age1<age2) return (-1); else if (age1==age2) return (0); else return +1; }//compare1 // la fonction qui compare une personne un nom public int compare2(Object o1, Object o2){ // o1 est une personne // o2 est un String, le nom nom2 d'une personne // doit rendre // -1 si o1.nom "plus petit que" nom2 // 0 si o1.nom "gal " nom2 // +1 si o1.nom "plus grand que" nom2 personne p1=(personne)o1; String nom1=p1.getNom(); String nom2=(String)o2; return nom1.compareTo(nom2); }//compare2 public void cherche(String ami,personne[] amis, Comparator comparateur){ // recherche ami dans le tableau amis int position=Arrays.binarySearch(amis,ami,comparateur); // trouv ? if(position>=0) System.out.println(ami + " a " + amis[position].getAge() + " ans"); else System.out.println(ami + " n'existe pas dans le tableau"); }//cherche // main public static void main(String[] arg){ new sort4(); }//main }//classe
Ici, nous avons procd un peu diffremment des exemples prcdents. Les deux objets Comparator ncessaires aux mthodes sort et binarySearch ont t crs et affects aux variables comparateur1 et comparateur2.
java.util.Comparator comparateur1= new java.util.Comparator(){ public int compare(Object o1, Object o2){ return compare1(o1,o2); }//compare }//classe ; java.util.Comparator comparateur2= new java.util.Comparator(){ public int compare(Object o1, Object o2){ return compare2(o1,o2); }//compare }//classe ;
- 86 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Une recherche dichotomique sur le tableau amis est faite deux fois dans le constructeur de sort4 :
// recherches cherche("milou",amis,comparateur2); cherche("xx",amis,comparateur2);
La mthode cherche reoit tous les paramtres dont elle a besoin pour appeler la mthode binarySearch :
public void cherche(String ami,personne[] amis, Comparator comparateur){ // recherche ami dans le tableau amis int position=Arrays.binarySearch(amis,ami,comparateur); // trouv ? if(position>=0) System.out.println(ami + " a " + amis[position].getAge() + " ans"); else System.out.println(ami + " n'existe pas dans le tableau"); }//cherche
La mthode binarySearch travaille avec le comparateur comparateur2 qui lui-mme fait appel la mthode compare2 de la classe sort4. La mthode rend la position du nom cherch dans le tableau s'il existe ou un nombre <0 sinon. La mthode compare2 sert comparer un objet personne un nom de type String.
// la fonction qui compare une personne un nom public int compare2(Object o1, Object o2){ // o1 est une personne // o2 est un String, le nom nom2 d'une personne // doit rendre // -1 si o1.nom "plus petit que" nom2 // 0 si o1.nom "gal " nom2 // +1 si o1.nom "plus grand que" nom2 personne p1=(personne)o1; String nom1=p1.getNom(); String nom2=(String)o2; return nom1.compareTo(nom2); }//compare2
Contrairement la mthode sort, la mthode binarySearch ne reoit pas deux objets personne, mais un objet personne et un objet String dans cet ordre. Le 1er paramtre est un lment du ableau amis, le second le nom de la personne cherche.
Voici un exemple :
// les classes importes import java.util.*; public class test1{
- 87 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// le programme principal main - static - mthode de classe public static void main(String arg[]){ // la cration des objets instances de classes personne p=new personne("Jean","Dupont",30); enseignant en=new enseignant("Paula","Hanson",56,27); etudiant et=new etudiant("Chris","Garot",22,"19980405"); System.out.println("p="+p.toString()); System.out.println("en="+en.toString()); System.out.println("et="+et.toString()); // le polymorphisme personne p2=(personne)en; System.out.println("p2="+p2.toString()); personne p3=(personne)et; System.out.println("p3="+p3.toString()); // un vecteur Vector V=new Vector(); V.addElement(p);V.addElement(en);V.addElement(et); System.out.println("Taille du vecteur V = "+V.size()); int i; for(i=0;i<V.size();i++){ p2=(personne) V.elementAt(i); System.out.println("V["+i+"]="+p2.toString()); } // une numration Enumeration E=V.elements(); i=0; while(E.hasMoreElements()){ p2=(personne) E.nextElement(); System.out.println("V["+i+"]="+p2.toString()); i++; } }// fin main }//fin classe
- 88 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les cls sont uniques, c.a.d. qu'il ne peut y avoir deux cls identiques. Les mthodes et proprits principales de la classe Hashtable sont les suivantes : public Hashtable() public int size() public Object put(Object key, Object value) public Object get(Object key) public boolean containsKey(Object key) public boolean contains(Object value) public Enumeration keys() public Object remove(Object key) public String toString() Voici un exemple :
// les classes importes import java.util.*; public class test1{ // le programme principal main - static - mthode de classe public static void main(String arg[]){ // la cration des objets instances de classes personne p=new personne("Jean","Dupont",30); enseignant en=new enseignant("Paula","Hanson",56,27); etudiant et=new etudiant("Chris","Garot",22,"19980405"); System.out.println("p="+p.toString()); System.out.println("en="+en.toString()); System.out.println("et="+et.toString()); // le polymorphisme personne p2=(personne)en; System.out.println("p2="+p2.toString()); personne p3=(personne)et; System.out.println("p3="+p3.toString()); // un dictionnaire Hashtable H=new Hashtable(); H.put("personne1",p); H.put("personne2",en); H.put("personne3",et); Enumeration E=H.keys(); int i=0; String cle; while(E.hasMoreElements()){ cle=(String) E.nextElement(); p2=(personne) H.get(cle); System.out.println("cl "+i+"="+cle+" valeur="+p2.toString()); i++; } }//fin main }//fin classe
constructeur - construit un dictionnaire vide nombre d'lments dans le dictionnaire - un lment tant une paire (cl, valeur) ajoute la paire (key, value) au dictionnaire rcupre l'objet associ la cl key ou null si la cl key n'existe pas vrai si la cl key existe dans le dictionnaire vrai si la valeur value existe dans le dictionnaire rend les cls du dictionnaire sous forme d'numration enlve la paire (cl, valeur) o cl=key identifie le dictionnaire
- 89 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les mthodes utiles de la classe PrintWriter sont les suivantes : void print(Type T) void println(Type T) void flush() void close() crit la donne T (String, int, #.) idem en terminant par une marque de fin de ligne vide le buffer si on n'est pas en mode autoflush ferme le flux d'criture
- 90 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} // criture dans le fichier try{ fic.println("Jean,Dupont,27"); fic.println("Pauline,Garcia,24"); fic.println("Gilles,Dumond,56"); } catch (Exception e){ Erreur(e,3); } // fermeture du fichier try{ fic.close(); } catch (Exception e){ Erreur(e,2); } }// fin main private static void Erreur(Exception e, int code){ System.err.println("Erreur : "+e); System.exit(code); }//Erreur }//classe
III-I-2 - Lire
Pour lire le contenu d'un fichier, il faut disposer d'un flux de lecture associ au fichier. On peut utiliser pour cela la classe FileReader et le constructeur suivant : FileReader(String nomFichier) ouvre un flux de lecture partir du fichier indiqu. Lance une exception si l'opration choue.
La classe FileReader possde un certain nombre de mthodes pour lire dans un fichier, mthodes hrites de la classe Reader. Pour lire des lignes de texte dans un fichier texte, il est prfrable d'utiliser la classe BufferedReader avec le constructeur suivant : BufferedReader(Reader in) ouvre un flux de lecture bufferis partir d'un flux d'entre in. Ce flux de type Reader peut provenir du clavier, d'un fichier, du rseau, ...
Les mthodes utiles de la classe BufferedReader sont les suivantes : int read() String readLine() nt read(char[] buffer, int offset, int taille) lit un caractre lit une ligne de texte lit taille caractres dans le fichier et les met dans le tableau buffer partir de la position offset. ferme le flux de lecture
void close()
- 91 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
import java.io.*; public class lire{ public static void main(String[] arg){ personne p=null; // ouverture du fichier BufferedReader IN=null; try{ IN=new BufferedReader(new FileReader("out")); } catch (Exception e){ Erreur(e,1); } // donnes String ligne=null; String[] champs=null; String prenom=null; String nom=null; int age=0; // gestion des ventuelles erreurs try{ while((ligne=IN.readLine())!=null){ champs=ligne.split(","); prenom=champs[0]; nom=champs[1]; age=Integer.parseInt(champs[2]); System.out.println(""+new personne(prenom,nom,age)); }// fin while } catch (Exception e){ Erreur(e,2); } // fermeture fichier try{ IN.close(); } catch (Exception e){ Erreur(e,3); } }// fin main // Erreur public static void Erreur(Exception e, int code){ System.err.println("Erreur : "+e); System.exit(code); } }// fin classe
- 92 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La mthode sauveAttributs reoit en unique paramtre le flux PrintWriter dans lequel elle doit crire. Un programme de test pourrait tre le suivant :
// imports import java.io.*; // import personne; public class sauver{ public static void main(String[] arg){ // ouverture du fichier PrintWriter fic=null; try{ f ic=new PrintWriter(new FileWriter("out")); } catch (Exception e){ Erreur(e,1); } // criture dans le fichier try{ new personne("Jean","Dupont",27).sauveAttributs(fic); new personne("Pauline","Garcia",24).sauveAttributs(fic); new personne("Gilles","Dumond",56).sauveAttributs(fic); } catch (Exception e){ Erreur(e,3); } // fermeture du fichier try{ fic.close(); } catch (Exception e){ Erreur(e,2); } }// fin main // Erreur private static void Erreur(Exception e, int code){ System.err.println("Erreur : "+e); System.exit(code); }//Erreur }//classe
- 93 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 94 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 95 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// les stocks fic.writeInt(art.stockActuel); fic.writeInt(art.stockMinimum); }// fin crire // ------------------------erreur public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); }// fin erreur }// fin class
C'est le programme suivant qui nous permet de vrifier que l'excution s'est correctement faite.
art.nom=art.nom.trim(); // prix art.prix=fic.readDouble(); // stocks art.stockActuel=fic.readInt(); art.stockMinimum=fic.readInt(); }// fin crire // ---------------------affiche public static void affiche(article art){ System.out.println("code : "+art.code); System.out.println("nom : "+art.nom); System.out.println("prix : "+art.prix); System.out.println("Stock actuel : "+art.stockActuel); System.out.println("Stock minimum : "+art.stockMinimum); }// fin affiche // ------------------------erreur public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); }// fin erreur }// fin class
- 97 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
RandomAccessFile dataBin=null; try{ dataBin=new RandomAccessFile("data.bin","rw"); } catch (Exception E){ erreur("Impossible d'ouvrir le fichier data.bin",1); } // les donnes sont prises dans un fichier texte BufferedReader dataTxt=null; try{ dataTxt=new BufferedReader(new FileReader("data.txt")); } catch (IOException E){ erreur("Impossible d'ouvrir le fichier data.txt",2); } // fichier .txt --> fichier .bin String ligne=null; String[] champs=null; int numLigne=0; String champ=null; article art=new article(); // article crer try{ while((ligne=dataTxt.readLine())!=null){ // une ligne de + numLigne++; // dcomposition en champs champs=ligne.split(":"); // il faut 5 champs if(champs.length!=5) erreur("Ligne "+numLigne+" errone dans data.txt",3); //code art.code=champs[0]; if(art.code.length()!=4) erreur("Code erron en ligne "+numLigne+" du fichier data.txt",12); // nom, prnom art.nom=champs[1]; // prix try{ art.prix=Double.parseDouble(champs[2]); } catch (Exception E){ erreur("Prix erron en ligne "+numLigne+" du fichier data.txt",4); } // stock actuel try{ art.stockActuel=Integer.parseInt(champs[3]); } catch (Exception E){ erreur("Stock actuel erron en ligne "+ numLigne + " du fichier data.txt",5); } // stock actuel try{ art.stockActuel=Integer.parseInt(champs[3]); } catch (Exception E){ erreur("Stock actuel erron en ligne "+ numLigne + " du fichier data.txt",5); } // on crit l'enregistrement try{ ecrire(dataBin,art); } catch (IOException E){ erreur("Erreur lors de l'criture de l'enregistrement "+numLigne,7); } // on passe la ligne suivante }// fin while } catch (IOException E){ erreur("Erreur lors de la lecture du fichier data.txt aprs la ligne "+numLigne,8); } // c'est fini try{ dataBin.close(); } catch (Exception E){ erreur("Impossible de fermer le fichier data.bin",10); } try{
- 98 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
dataTxt.close(); } catch (Exception E){ erreur("Impossible de fermer le fichier data.txt",11); } }// fin main // mthode d'criture public static void ecrire(RandomAccessFile fic, article art) throws IOException{ // code fic.writeBytes(art.code); // le nom limit 20 caractres art.nom=art.nom.trim(); int l=art.nom.length(); int nbBlancs=20-l; if(nbBlancs>0){ String blancs=""; for(int i=0;i<nbBlancs;i++) blancs+=" "; art.nom+=blancs; } else art.nom=art.nom.substring(0,20); fic.writeBytes(art.nom); // le prix fic.writeDouble(art.prix); // les stocks fic.writeInt(art.stockActuel); fic.writeInt(art.stockMinimum); }// fin crire // ------------------------erreur public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); }// fin erreur }// fin class
C'est le programme suivant qui permet de vrifier que celui-ci a correctement fonctionn.
- 99 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
PrintWriter dataTxt=null; try{ dataTxt=new PrintWriter(new FileWriter("data.text")); } catch (IOException E){ erreur("Impossible d'ouvrir le fichier data.text en criture",2); } // fichier .bin --> fichier .text article art=new article(); // article crer // on exploite le fichier binaire int numRecord=0; long l=0; // taille du fichier try{ l=dataBin.length(); } catch (IOException e){ erreur("Erreur lors du calcul de la longueur du fichier data.bin",2); } long pos=0; // position courante dans le fichier try{ pos=dataBin.getFilePointer(); } catch (IOException e){ erreur("Erreur lors de la lecture de la position courante dans data.bin",2); } // tant qu'on n'a pas dpass la fin du fichier while(pos<l){ // lire enregistrement courant et l'exploiter numRecord++; try{ lire(dataBin,art); } catch (Exception e){ erreur("Erreur lors de la lecture de l'enregistrement "+numRecord,2); } affiche(art); // criture de la ligne de texte correspondante dans dataTxt dataTxt.println(art.code.trim()+":"+art.nom.trim()+":"+art.prix+":"+art.stockActuel+":"+art.stockMinimum ); // on continue ? try{ pos=dataBin.getFilePointer(); } catch (IOException e){ erreur("Erreur lors de la lecture de la position courante dans data.bin",2); } }// fin while // c'est fini try{ dataBin.close(); } catch (Exception E){ erreur("Impossible de fermer le fichier data.bin",2); } try{ dataTxt.close(); } catch (Exception E){ erreur("Impossible de fermer le fichier data.text",2); } }// fin main // mthode de lecture public static void lire(RandomAccessFile fic, article art) throws IOException{ // lecture code art.code=""; for(int i=0;i<4;i++) art.code+=(char)fic.readByte(); // nom art.nom=""; for(int i=0;i<20;i++) art.nom+=(char)fic.readByte(); art.nom=art.nom.trim(); // prix art.prix=fic.readDouble(); // stocks art.stockActuel=fic.readInt(); art.stockMinimum=fic.readInt(); }// fin crire
- 100 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// ---------------------affiche public static void affiche(article art){ System.out.println("code : "+art.code); System.out.println("nom : "+art.nom); System.out.println("prix : "+art.prix); System.out.println("Stock actuel : "+art.stockActuel); System.out.println("Stock minimum : "+art.stockMinimum); }// fin affiche // ------------------------erreur public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); }// fin erreur }// fin class
- 101 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// on dfinit la structure public String code; public String nom; public double prix; public int stockActuel; public int stockMinimum; }//classe article // main public static void main(String[] args){ // on vrifie les arguments int nbArguments=args.length; String syntaxe="syntaxe : pg numro_de_fiche"; if(nbArguments!=1) erreur(syntaxe,20); // vrification n de fiche int numRecord=0; try{ numRecord=Integer.parseInt(args[0]); } catch(Exception e){ erreur(syntaxe+"\nNumro de fiche incorrect",21); } // on ouvre le fichier binaire en lecture RandomAccessFile dataBin=null; try{ dataBin=new RandomAccessFile("data.bin","r"); } catch (Exception E){ erreur("Impossible d'ouvrir le fichier data.bin en lecture",1); } // on se positionne sur la fiche dsire try{ dataBin.seek((numRecord-1)*40); } catch (Exception e){ erreur("La fiche "+numRecord+" n'existe pas",23); } // on la lit article art=new article(); try{ lire(dataBin,art); } catch (Exception e){ erreur("Erreur lors de la lecture de l'enregistrement "+numRecord,2); } // on l'affiche affiche(art); // c'est fini try{ dataBin.close(); } catch (Exception E){ erreur("Impossible de fermer le fichier data.bin",2); }//try-catch }// fin main // mthode de lecture public static void lire(RandomAccessFile fic, article art) throws IOException{ // lecture code art.code=""; for(int i=0;i<4;i++) art.code+=(char)fic.readByte(); // nom art.nom=""; for(int i=0;i<20;i++) art.nom+=(char)fic.readByte(); art.nom=art.nom.trim(); // prix art.prix=fic.readDouble(); // stocks art.stockActuel=fic.readInt(); art.stockMinimum=fic.readInt(); }// fin crire // ---------------------affiche
- 102 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public static void affiche(article art){ System.out.println("code : "+art.code); System.out.println("nom : "+art.nom); System.out.println("prix : "+art.prix); System.out.println("Stock actuel : "+art.stockActuel); System.out.println("Stock minimum : "+art.stockMinimum); }// fin affiche // ------------------------erreur public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); }// fin erreur }// fin class
- 103 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Description Marque le caractre suivant comme caractre spcial ou littral. Par exemple, "n" correspond au caractre "n". "\n" correspond un caractre de nouvelle ligne. La squence "\\" correspond "\", tandis que "\(" correspond "(". ^ Correspond au dbut de la saisie. $ Correspond la fin de la saisie. * Correspond au caractre prcdent zro fois ou plusieurs fois. Ainsi, "zo*" correspond "z" ou "zoo". + Correspond au caractre prcdent une ou plusieurs fois. Ainsi, "zo+" correspond "zoo", mais pas "z". ? Correspond au caractre prcdent zro ou une fois. Par exemple, "a?ve?" correspond "ve" dans "lever". . Correspond tout caractre unique, sauf le caractre de nouvelle ligne. (modle) Recherche le modle et mmorise la correspondance. La sous-chane correspondante peut tre extraite de la collection Matches obtenue, l'aide d'Item [0]...[n]. Pour trouver des correspondances avec des caractres entre parenthses ( ), utilisez "\(" ou "\)". x|y Correspond soit x soit y. Par exemple, "z| foot" correspond "z" ou "foot". "(z|f)oo" correspond "zoo" ou "foo". {n} n est un nombre entier non ngatif. Correspond exactement n fois le caractre. Par exemple, "o{2}" ne correspond pas "o" dans "Bob," mais aux deux premiers "o" dans "fooooot". {n,2} n est un entier non ngatif. Correspond au moins n fois le caractre. Par exemple, "o{2,}" ne correspond pas "o" dans "Bob", mais tous les "o" dans "fooooot". "o{1,}" quivaut "o+" et "o{0,}" quivaut "o*". {n,m} m et n sont des entiers non ngatifs. Correspond au moins n et au plus m fois le caractre. Par exemple, "o{1,3}" correspond aux trois premiers "o" dans "foooooot" et "o{0,1}" quivaut "o?". [xyz] Jeu de caractres. Correspond l'un des caractres indiqus. Par exemple, "[abc]" correspond "a" dans "plat". [^xyz] Jeu de caractres ngatif. Correspond tout caractre non indiqu. Par exemple, "[^abc]" correspond "p" dans "plat". [a-z] Plage de caractres. Correspond tout caractre dans la srie spcifie. Par exemple, "[a-z]" correspond tout caractre alphabtique minuscule compris entre "a" et "z". [^m-z] Plage de caractres ngative. Correspond tout caractre ne se trouvant pas dans la - 104 - srie spcifie. Par exemple, "[^m-z]" Ce document est issu de http://www.developpez.com et reste la proprit exclusive de tout caractre ne se trouvant distribution par correspond son auteur. La copie, modification et/ou quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur. pas entre "m" et http://tahe.developpez.com/java/cours/temp/ "z". \b Correspond une limite reprsentant un mot, autrement dit, la position entre un \
Caractre
Correspond n, o n est une valeur d'chappement hexadcimale. Les valeurs d'chappement hexadcimales doivent comprendre deux chiffres obligatoirement. Par exemple, "\x41" correspond "A". "\x041" quivaut "\x04" & "1". Permet d'utiliser les codes ASCII dans des expressions rgulires. Un lment dans un modle peut tre prsent en 1 ou plusieurs exemplaires. Considrons quelques exemples autour du symbole \d qui reprsente 1 chiffre : modle \d \d? \d* \d+ \d{2} \d{3,} \d{5,7} signification un chiffre 0 ou 1 chiffre 0 ou davantage de chiffres 1 ou davantage de chiffres 2 chiffres au moins 3 chiffres entre 5 et 7 chiffres
Imaginons maintenant le modle capable de dcrire le format attendu pour une chane de caractres : chane recherche une date au format jj/mm/aa une heure au format hh:mm:ss un nombre entier non sign un suite d'espaces ventuellement vide un nombre entier non sign qui peut tre prcd ou suivi d'espaces un nombre entier qui peut tre sign et prcd ou suivi d'espaces un nombre rel non sign qui peut tre prcd ou suivi d'espaces un nombre rel qui peut tre sign et prcd ou suivi d'espaces une chane contenant le mot juste modle \d{2}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} \d+ \s* \s*\d+\s* \s*[+|-]?\s*\d+\s* \s*\d+(.\d*)?\s* \s*[+|]?\s*\d+(.\d*)?\s* \bjuste\b
On peut prciser o on recherche le modle dans la chane : modle ^modle modle$ ^modle$ modle signification le modle commence la chane le modle finit la chane le modle commence et finit la chane le modle est cherch partout dans la chane en commenant par le dbut de celle-ci.
- 105 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
chane recherche une chane se terminant par un point d'exclamation une chane se terminant par un point une chane commenant par la squence // une chane ne comportant qu'un mot ventuellement suivi ou prcd d'espaces une chane ne comportant deux mot ventuellement suivis ou prcds d'espaces une chane contenant le mot secret
\bsecret\b
Les sous-ensembles d'un modle peuvent tre "rcuprs". Ainsi non seulement, on peut vrifier qu'une chane correspond un modle particulier mais on peut rcuprer dans cette chane les lments correspondant aux sousensembles du modle qui ont t entours de parenthses. Ainsi si on analyse une chane contenant une date jj/ mm/aa et si on veut de plus rcuprer les lments jj, mm, aa de cette date on utilisera le modle (\d\d)/(\d\d)/(\d\d).
avec : modle : le modle vrifier, chaine : la chane comparer au modle. Le rsultat est le boolen true si chaine correspond modle, false sinon. Voici un exemple :
import java.io.*; import java.util.regex.*; // gestion d'expression rgulires public class regex1 { public static void main(String[] args){ // une expression rgulire modle String modle1="^\\s*\\d+\\s*$"; // comparer un exemplaire au modle String exemplaire1=" 123 "; if (Pattern.matches(modle1,exemplaire1)){ affiche("["+exemplaire1 + "] correspond au }else{ affiche("["+exemplaire1 + "] ne correspond }//if String exemplaire2=" 123a "; if (Pattern.matches(modle1,exemplaire2)){ affiche("["+exemplaire2 + "] correspond au }else{ affiche("["+exemplaire2 + "] ne correspond }//if }//main public static void affiche(String msg){ System.out.println(msg); }//affiche }//classe
- 106 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On notera que dans le modle "^\s*\d+\s*$" le caractre \ doit tre doubl cause de l'interprtation particulire que fait Java de ce caractre. On crit donc :
String modle1="^\\s*\\d+\\s*$";
Elle prend pour paramtre la chane du modle et rend un objet Pattern. Pour comparer le modle d'un objet Pattern une chane de caractres on utilise la classe Matcher. Celle-ci permet la comparaison d'un modle une chane de caractres. A partir d'un objet Pattern, il est possible d'obtenir un objet de type Matcher avec la mthode matcher :
public Matcher matcher(CharSequence input)
input est la chane de caractres qui doit tre compare au modle. Ainsi pour comparer le modle "\d+" la chane " 123 456 789 ", on pourra crer un objet Matcher de la faon suivante :
Pattern regex=Pattern.compile("\\d+"); Matcher rsultats=regex.matcher(" 123 456 789 ");
A partir de l'objet rsultats prcdent, on va pouvoir rcuprer les diffrentes occurrences du modle dans la chane. Pour cela, on utilise les mthodes suivantes de la classe Matcher :
public boolean find() public String group() public int start() public Matcher reset()
La mthode find recherche dans la chane explore la premire occurence du modle. Un second appel find recherchera l'occurrence suivante. Et ainsi de suite. La mthode rend true si elle trouve le modle, false sinon. La portion de chaine correspondant la dernire occurence trouve par find est obtenue avec la mthode group et sa position avec la mthode start. Ainsi, si on poursuit l'exemple prcdent et qu'on veuille afficher toutes les occurences du modle "\d+" dans la chane " 123 456 789 " on crira :
while(rsultats.find()){ System.out.println("squence " + rsultats.group() + " trouve en position " + rsultats.start()); }//while
La mthode reset permet de rinitialiser l'objet Matcher sur le dbut de la chane compare au modle. Ainsi la mthode find trouvera ensuite de nouveau la premire occurence du modle Voici un exemple complet :
import java.io.*; import java.util.regex.*; // gestion d'expression rgulires public class regex2 { public static void main(String[] args){ // plusieurs occurrences du modle dans l'exemplaire
- 107 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String modle2="\\d+"; Pattern regex2=Pattern.compile(modle2); String exemplaire3=" 123 456 789"; // recherche des occurrences du modle dans l'exemplaire Matcher matcher2=regex2.matcher(exemplaire3); while(matcher2.find()){ affiche("squence " + matcher2.group() + " trouve en position " + matcher2.start()); }//while }//Main public static void affiche(String msg){ System.out.println(msg); }//affiche }//classe
La chane exemplaire4 est compare au modle regex3 au travers de la mthode find. Une occurence du modle regex3 est alors trouve dans la chane exemplaire4. Si le modle comprend des sous-ensembles entours de parenthses ceux-ci sont disponibles grce diverses mthodes de la classe Matcher :
public int groupCount() public String group(int group) public int start(int group)
La mthode groupCount donne le nombre de sous-ensembles trouvs dans le modle et group(i) le sous-ensemble n i. Celui est trouv dans la chane une position donne par start(i). Ainsi dans l'exemple :
L'exemplaire [Il est 18:05:49] correspond au modle [(\d\d):(\d\d):(\d\d)] groupes[0]=[18:05:49] en position 7 groupes[1]=[18] en position 7 groupes[2]=[05] en position 10 groupes[3]=[49] en position 13
Le premier appel la mthode find va trouver la chane 18:05:49 et automatiquement crer les trois sous-ensembles dfinis par les parenthses du modle, respectivement 18, 05 et 49.
- 109 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
while(true){ // flux d'entre IN=new BufferedReader(new InputStreamReader(System.in)); // on demande le modle System.out.print("Tapez le modle tester ou fin pour arrter :"); modle=IN.readLine(); // fini ? if(modle.trim().toLowerCase().equals("fin")) break; // on cre l'expression rgulire regex=Pattern.compile(modle); // on demande l'utilisateur les exemplaires comparer au modle while(true){ System.out.print("Tapez la chane comparer au modle ["+modle+"] ou fin pour arrter :"); chaine=IN.readLine(); // fini ? if(chaine.trim().toLowerCase().equals("fin")) break; // on cre l'objet matcher rsultats=regex.matcher(chaine); // on recherche les occurrences du modle nbOccurrences=0; while(rsultats.find()){ // on a une occurrence nbOccurrences++; // on l'affiche System.out.println("J'ai trouv la correspondance ["+rsultats.group() +"] en position "+rsultats.start()); // affichage des sous-lments if(rsultats.groupCount()!=1){ for(int j=1;j<=rsultats.groupCount();j++){ System.out.println("\tsous-lment ["+rsultats.group(j)+"] en position "+ rsultats.start(j)); }//for j }//if // chane suivante }//while(rsultats.find()) // a-t-on trouv au moins une occurrence ? if(nbOccurrences==0){ System.out.println("Je n'ai pas trouv de correspondance au modle ["+modle+"]"); }//if // modle suivant }//while(true) }//while(true) }catch(Exception ex){ // erreur System.err.println("Erreur : "+ex.getMessage()); // fin avec erreur System.exit(1); }//try-catch // fin System.exit(0); }//Main }//classe
- 110 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Tapez la chane comparer au modle [(\d\d):(\d\d)] ou fin pour arrter :fin Tapez le modle tester ou fin pour arrter :^\s*\d+\s*$ Tapez la chane comparer au modle [^\s*\d+\s*$] ou fin pour arrter : 1456 J'ai trouv la correspondance [ 1456] en position 0 Tapez la chane comparer au modle [^\s*\d+\s*$] ou fin pour arrter :fin Tapez le modle tester ou fin pour arrter :^\s*(\d+)\s*$ Tapez la chane comparer au modle [^\s*(\d+)\s*$] ou fin pour arrter :1456 J'ai trouv la correspondance [1456] en position 0 sous-lment [1456] en position 0 Tapez la chane comparer au modle [^\s*(\d+)\s*$] ou fin pour arrter :abcd 1 456 Je n'ai pas trouv de correspondances Tapez la chane comparer au modle [^\s*(\d+)\s*$] ou fin pour arrter :fin Tapez le modle tester ou fin pour arrter :fin
La chane input est dcompose en champs, ceux-ci tant spars par un sparateur correspondant au modle de l'objet Pattern courant. Pour rcuprer les champs d'une ligne dont le sparateur de champs est la virgule prcde ou suivie d'un nombre quelconque d'espaces, on crira :
// une ligne String ligne="abc ,, def , ghi"; // un modle Pattern modle=Pattern.compile("\\s*,\\s*"); // dcomposition de ligne en champs String[] champs=modle.split(ligne);
- 111 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
optionsInvalides
optionsSans erreur
Un objet options pourra tre construit de 4 faons diffrentes : public options (String arguments, String optionsAcceptables) arguments optionsAcceptables la ligne d'arguments -o1 v1 v2 ... -o2 v3 v4 # analyser la liste des options oi acceptables
Ici, les deux arguments sont des chanes de caractres. On acceptera les cas o ces chanes ont t dcoupes en mots mis dans un tableau de chanes de caractres. Cela ncessite trois autres constructeurs :
public options (String[] arguments, String optionsAcceptables) public options (String arguments, String[] optionsAcceptables) public options (String[] arguments, String[] optionsAcceptables)
La classe options prsentera l'interface suivante (accesseurs) : public Hashtable getOptionsValides() rend la rfrence du tableau optionsValides construit lors de la cration de l'objet options public Hashtable getOptionsInvalides() rend la rfrence du tableau optionsInvalides construit lors de la cration de l'objet options public String getOptionsSans() rend la rfrence de la chane optionsSans construite lors de la cration de l'objet options public int getErreur() rend la valeur de l'attribut erreur construite lors de la cration de l'objet options public String toString() s'il n'y a pas d'erreur, affiche les valeurs des attributs optionsValides, optionsInvalides, optionsSans ou sinon affiche le numro de l'erreur. Voici un programme d'exemple :
import java.io.*; //import options; public class test1{ public static void main (String[] arg){ // ouverture du flux d'entre String ligne; BufferedReader IN=null; try{ IN=new BufferedReader(new InputStreamReader(System.in)); } catch (Exception e){ affiche(e); System.exit(1); } // lecture des arguments du constructeur options(String, string) String options=null; String optionsAcceptables=null; while(true){ System.out.print("Options : "); try{ options=IN.readLine(); } catch (Exception e){ affiche(e); System.exit(2); } if(options.length()==0) break; System.out.print("Options acceptables: "); try{ optionsAcceptables=IN.readLine();
- 113 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} catch (Exception e){ affiche(e); System.exit(2); } System.out.println(new options(options,optionsAcceptables)); }// fin while }//fin main public static void affiche(Exception e){ System.err.println("Erreur : "+e); } }//fin classe
Quelques rsultats :
C:\Serge\java\options>java test1 Options : 1 2 3 -a a1 a2 -b b1 -c c1 c2 c3 -b b2 b3 Options acceptables: -a -b Erreur 6 Options valides :(-b,b1,b2,b3) (-a,a1,a2) Options invalides : (-c,c1,c2,c3) Sans options : 1 2 3
III-L-2 - Exercice 2
On dsire crer une classe stringtovector permettant de transfrer le contenu d'un objet String dans un objet Vector. Cette classe serait drive de la classe Vector : class stringtovector extends Vector et aurait le constructeur suivant :
private void stringtovector(String S, String separateur, int[] tChampsVoulus, boolean strict){ // cre un vecteur avec les champs de la chane S // celle-ci est constitue de champs spars par separateur // si sparateur=null, la chane ne forme qu'un seul champ // seuls les champs dont les index sont dans le tableau tChampsVoulus // sont dsirs. Les index commencent 1 // si tChampsvoulus=null ou de taille nulle, on prend tous les champs // si strict=vrai, tous les champs dsirs doivent tre prsents
La classe aurait l'attribut priv suivant : private int erreur; Cet attribut est positionn par le constructeur prcdent avec les valeurs suivantes : 0 : la construction s'est bien passe 4 : certains champs demands sont absents alors que strict=true
La classe aura galement deux mthodes : public int getErreur() qui rend la valeur de l'attribut priv erreur. public String identite(){
- 114 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
qui affiche la valeur de l'objet sous la forme (erreur, lment 1, lment 2, #) o lments i sont les lments du vecteur construit partir de la chane. Un programme de test pourrait tre le suivant :
import java.io.*; //import stringtovector; public class essai2{ public static void main(String arg[]){ int[] T1={1,3}; System.out.println(new stringtovector("a int[] T2={1,3,7}; System.out.println(new stringtovector("a int [] T3={1,4,7}; System.out.println(new stringtovector("a System.out.println(new stringtovector("a System.out.println(new stringtovector("a int[] T4={1}; System.out.println(new stringtovector("a int[] T5=null; System.out.println(new stringtovector("a System.out.println(new stringtovector("a int[] T6=new int[0]; System.out.println(new stringtovector("a int[] T7={1,3,4}; System.out.println(new stringtovector("a } }
: b : c :d:e",":",T1,true).identite()); : b : c :d:e",":",T2,true).identite()); : b : c :d:e",":",T3,false).identite()); : b : c :d:e","",T1,false).identite()); : b : c :d:e",null,T1,false).identite()); : b : c :d:e","!",T4,true).identite()); : b : c :d:e",":",T5,true).identite()); : b : c :d:e",null,T5,true).identite()); : b : c :d:e","",T6,true).identite()); b c d e"," ",T6,true).identite());
Les rsultats :
(0,a,c) (4,a,c) (0,a,d) (0,a : b : c :d:e) (0,a : b : c :d:e) (0,a : b : c :d:e) (0,a,b,c,d,e) (0,a : b : c :d:e) (0,a : b : c :d:e) (0,a,b,c,d,e)
Quelques conseils : 1 2 3 Pour dcouper la chane S en champs, utiliser la mthode split de la classe String. Mettre les champs de S dans un dictionnaire D index par le numro du champ Rcuprer dans le dictionnaire D les seuls champs ayant leur cl (index) dans le tableau tChampsVoulus.
III-L-3 - Exercice 3
On dsire ajouter la classe stringtovector le constructeur suivant :
public stringtovector(String S, String separateur, String sChampsVoulus,boolean strict){ // cre un vecteur avec les champs de la chane S // celle-ci est constitue de champs spars par separateur // si sparateur=null, la chane ne forme qu'un seul champ // seuls les champs dont les index sont dans sChampsVoulus sont dsirs // les index commencent 1 // si sChampsvoulus=null ou "", on prend tous les champs // si strict=vrai, tous les champs dsirs doivent tre prsents
La liste des champs dsirs est donc dans une chane (String) au lieu d'un tableau d'entiers (int[]). L'attribut priv erreur de la classe peut se voir attribuer une nouvelle valeur :
- 115 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
:d:e ",":","1 3",true).identite()); :d:e ",":","1 3 7",true).identite()); :d:e ",":","1 4 7",false).identite()); :d:e ","","1 3",false).identite()); :d:e ",null,"1 3",false).identite()); :d:e ","!","1",true).identite()); :d:e ",":","",true).identite()); :d:e ",":",champs,true).identite()); :d:e ",null,champs,true).identite()); :d:e ","","",true).identite()); :d:e ",":","1 !",true).identite()); e "," ","1 3",false).identite());
Quelques rsultats :
(0,a,c) (4,a,c) (0,a,d) (0,a: b :c :d:e) (0,a: b :c :d:e) (0,a: b :c :d:e) (0,a,b,c,d,e) (0,a,b,c,d,e) (0,a: b :c :d:e) (0,a: b :c :d:e) (2) (0,a,c)
Quelques conseils : Il faut se ramener au cas du constructeur prcdent en transfrant les champs de la chane sChampsVoulus dans un tableau d'entiers. Pour cela, dcouper sChampsVoulus en champs avec un objet StringTokenizer dont l'attribut countTokens donnera le nombre de champs obtenus. On peut alors crer un tableau d'entiers de la bonne dimension et le remplir avec les champs obtenus. Pour savoir si un champ est entier, utiliser la mthode Integer.parseInt pour transformer le champ en entier et grer l'exception qui sera gnre lorsque cette conversion sera impossible.
III-L-4 - Exercice 4
On dsire crer une classe filetovector permettant de transfrer le contenu d'un fichier texte dans un objet Vector. Cette classe serait drive de la classe Vector :
class filetovector extends Vector
- 116 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// // // // // // // // //
si sparateur=null, la ligne ne forme qu'un seul champ seuls les champs dont les index sont dans tChampsVoulus sont dsirs les index commencent 1 si tChampsvoulus=null ou vide, on prend tous les champs si strict=vrai, tous les champs dsirs doivent tre prsents si ce n'est pas le cas, la ligne n'est pas mmorise et son index est plac dans le vecteur lignesErronees les lignes blanches sont ignores ainsi que les lignes commenant par tagCommentaire si tagCommentaire != null
L'attribut erreur est positionn par le constructeur prcdent avec les valeurs suivantes : 0 : la construction s'est bien passe 1 : le fichier exploiter n'a pas pu tre ouvert 4 : certains champs demands sont absents alors que strict=true 8 : il y a eu une erreur d'E/S lors de l'exploitation du fichier
L'attribut lignesErronees est un vecteur dont les lments sont les numros des lignes errones sous forme de chane de caractres. Une ligne est errone si elle ne peut fournir les champs demands alors que strict=true. La classe aura galement deux mthodes :
public int getErreur()
qui affiche la valeur de l'objet sous la forme (erreur, lment 1 lment 2 #,(l1,l2,#)) o lments i sont les lments du vecteur construit partir du fichier et li les numros des lignes errones. Voici un exemple de test :
import java.io.*; //import filetovector; public class test2{ public static void main(String arg[]){ int[] T1={1,3}; System.out.println(new filetovector("data.txt",":",T1,false,"#").identite()); System.out.println(new filetovector("data.txt",":",T1,true,"#").identite()); System.out.println(new filetovector("data.txt","",T1,false,"#").identite()); System.out.println(new filetovector("data.txt",null,T1,false,"#").identite()); int[] T2=null; System.out.println(new filetovector("data.txt",":",T2,false,"#").identite()); System.out.println(new filetovector("data.txt",":",T2,false,"").identite()); int[] T3=new int[0]; System.out.println(new filetovector("data.txt",":",T3,false,null).identite()); } }
- 117 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
(0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)] (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)] (0,1,2,3,4,5) (0,azerty,1,cvf,fff,qqqq) (0,s)] (0,1,2,3,4,5) (0,# commentaire) (0,azerty,1,cvf,fff,qqqq) (0,s)] (0,1,2,3,4,5) (0,# commentaire) (0,azerty,1,cvf,fff,qqqq) (0,s)]
Quelques conseils 1 2 3 Le fichier texte est trait ligne par ligne. La ligne est dcoupe en champs grce la classe stringtovector tudie prcdemment. Les lments du vecteur consitu partir du fichier texte sont donc des objets de type stringtovector. La mthode identite de filetovector pourra s'appuyer sur la mthode stringtovector.identite() pour afficher ses lments ainsi que sur la mthode Vector.toString() pour afficher les numros des ventuelles lignes errones.
III-L-5 - Exercice 5
On dsire ajouter la classe filetovector le constructeur suivant :
public filetovector(String nomFichier, String separateur, String sChampsVoulus, boolean strict, String tagCommentaire){ // // // // // // // // // // // cre un vecteur avec les lignes du fichier texte nomFichier les lignes sont faites de champs spars par separateur si sparateur=null, la ligne ne forme qu'un seul champ seuls les champs dont les index sont dans tChampsVoulus sont dsirs les index commencent 1 si sChampsvoulus=null ou vide, on prend tous les champs si strict=vrai, tous les champs dsirs doivent tre prsents si ce n'est pas le cas, la ligne n'est pas mmorise et son index est plac dans le vecteur lignesErronees les lignes blanches sont ignores ainsi que les lignes commenant par tagCommentaire si tagCommentaire != null
La liste des index des champs dsirs est maintenant dans une chane de caractres (String) au lieu d'tre dans un tableau d'entiers. L'attribut priv erreur peut avoir une valeur supplmentaire : 2 : la chanes des index des champs dsirs est incorrecte
- 118 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les rsultats :
[0,(0,a,c) (0,1,3) (0,azerty,cvf) (0,s)][4,(0,a,c) (0,1,3) (0,azerty,cvf),[5]] [0,(0,a:b:c:d:e) (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)] [0,(0,a:b:c:d:e) (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)] [0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,azerty,1,cvf,fff,qqqq) (0,s)] [0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# commentaire) (0,azerty,1,cvf,fff,qqqq) (0,s)] [0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# commentaire) (0,azerty,1,cvf,fff,qqqq) (0,s)]
Quelques conseils 1 On transformera la chane sChampsVoulus en tableau d'entiers tChampVoulus pour se ramener au cas du constructeur prcdent.
- 119 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IV - Interfaces graphiques
Nous nous proposons ici de montrer comment construire des interfaces graphiques avec JAVA. Nous voyons tout d'abord quelles sont les classes de base qui nous permettent de construire une interface graphique. Nous n'utilisons dans un premier temps aucun outil de gnration automatique. Puis nous utiliserons JBuilder, un outil de dveloppement de Borland/Inprise facilitant le dveloppement d'applications Java et notamment la construction des interfaces graphiques.
IV-A - Les bases des interfaces graphiques IV-A-1 - Une fentre simple
Considrons le code suivant :
// classes importes import javax.swing.*; import java.awt.*; // la classe formulaire public class form1 extends JFrame { // le constructeur public form1() { // titre de la fentre this.setTitle("Mon premier formulaire"); // dimensions de la fentre this.setSize(new Dimension(300,100)); }//constructeur // fonction de test public static void main(String[] args) { // on affiche le formulaire new form1().setVisible(true); } }//classe
La classe de base JFrame dfinit une fentre de base avec des boutons de fermeture, agrandissement/rduction, une taille ajustable, etc ... et gre les vnements sur ces objets graphiques. Ici nous spcialisons la classe de base en lui fixant un titre et ses largeur (300 pixels) et hauteur (100 pixels). Ceci est fait dans son constructeur :
// le constructeur public form1() { // titre de la fentre this.setTitle("Mon premier formulaire"); // dimensions de la fentre this.setSize(new Dimension(300,100)); }//constructeur
- 120 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le titre de la fentre est fixe par la mthode setTitle et ses dimensions par la mthode setSize. Cette mthode accepte pour paramtre un objet Dimension(largeur,hauteur) o largeur et hauteur sont les largeur et hauteur de la fentre exprimes en pixels. La mthode main lance l'application graphique de la faon suivante :
new form1().setVisible(true);
Un formulaire de type form1 est alors cr (new form1()) et affich (setVisible(true)), puis l'application se met l'coute des vnements qui se produisent sur le formulaire (clics, dplacements de souris, ...) et fait excuter ceux que le formulaire gre. Ici, notre formulaire ne gre pas d'autres vnements que ceux grs par la classe de base JFrame (clics sur boutons fermeture, agrandissement/rduction, changement de taille de la fentre, dplacement de la fentre, ...). Lorsqu'on teste ce programme en le lanant partir d'une fentre Dos par :
java form1
pour excuter le fichier form1.class, on constate que lorsqu'on ferme la fentre qui a t affiche, on ne "rcupre pas la main" dans la fentre Dos, comme si le programme n'tait pas termin. C'est effectivement le cas. L'excution du programme se fait de la faon suivante : au dpart, un premier thread d'excution est lanc pour excuter la mthode main lorsque celle-ci cre le formulaire et l'affiche, un second thread est cr pour grer spcifiquement les vnements lis au formulaire aprs cette cration et dans notre exemple, le thread de la mthode main se termine et seul reste alors le thread d'excution de l'interface graphique. lorsqu'on ferme la fentre, celle-ci disparat mais n'interrompt pas le thread dans lequel elle s'excutait on est oblig pour l'instant d'arrter ce thread en faisant Ctrl-C dans la fentre Dos d'o a t lance l'excution du programme.
Vrifions l'existence de deux threads spars, l'un dans lequel s'excute la mthode main, l'autre dans lequel s'excute la fentre graphique :
// classes importes import javax.swing.*; import java.awt.*; import java.io.*; // la classe formulaire public class form1 extends JFrame { // le constructeur public form1() { // titre de la fentre this.setTitle("Mon premier formulaire"); // dimensions de la fentre this.setSize(new Dimension(300,100)); }//constructeur // fonction de test public static void main(String[] args) { // suivi System.out.println("Dbut du thread main"); // on affiche le formulaire new form1().setVisible(true); // suivi System.out.println("Fin du thread main"); }//main }//classe
- 121 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On peut constater que le thread main est termin alors que la fentre est, elle, encore affiche. Le fait de fermer la fentre ne termine pas le thread dans laquelle elle s'excutait. Pour arrter ce thread, on fait de nouveau CtrlC dans la fentre Dos. Pour terminer cet exemple, on notera les paquetages imports : javax.swing pour la classe JFrame java.awt pour la classe Dimension
Il y a donc sept vnements qui peuvent tre grs. Les gestionnaires reoivent tous en paramtre un objet de type WindowEvent que nous ignorons pour l'instant. L'vnement qui nous intresse ici est la fermeture de la fentre, vnement qui devra tre trait par la mthode windowClosing. Pour grer cet vnement, on pourra crer un objet Windowlistener l'aide d'une classe anonyme de la faon suivante :
// cration d'un gestionnaire d'vnements WindowListener win=new WindowListener(){ public void windowActivated(WindowEvent e){} public void windowClosed(WindowEvent e){} public void windowClosing(WindowEvent e){System.exit(0);} public void windowDeactivated(WindowEvent e){}
- 122 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public void windowDeiconified(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowOpened(WindowEvent e){} };//dfinition win
Notre gestionnaire d'vnements implmentant l'interface WindowListener doit dfinir les sept mthodes de cette interface. Comme nous ne voulons grer que la fermeture de la fentre, nous ne dfinissons du code que pour la mthode windowClosing. Lorsque les autres vnements se produiront, nous en serons avertis mais nous ne ferons rien. Que ferons-nous lorsqu'on sera averti que la fentre est en cours de fermeture (windowClosing) ? Nous arrterons l'application :
public void windowClosing(WindowEvent e){System.exit(0);}
Nous avons l un objet capable de grer les vnements d'une fentre en gnral. Comment l'associe-t-on une fentre particulire ? La classe JFrame a une mthode addWindowListener(WindowListener win) qui permet d'associer un gestionnaire d'vnements "fentre" une fentre donne. Ainsi ici, dans le constructeur de la fentre nous crirons :
// cration d'un gestionnaire d'vnements WindowListener win=new WindowListener(){ public void windowActivated(WindowEvent e){} public void windowClosed(WindowEvent e){} public void windowClosing(WindowEvent e){System.exit(0);} public void windowDeactivated(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowOpened(WindowEvent e){} };//dfinition win // ce gestionnaire d'vnements va grer les vts de la fentre courante this.addWindowListener(win);
- 123 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}//classe
Le paquetage java.awt.event contient l'interface WindowListener. Lorsqu'on excute ce programme et qu'on ferme la fentre qui s'est afiche on constate dans la fentre Dos o a t lanc le programme, la fin d'excution du programme ce qu'on n'avait pas auparavant. Dans notre programme, la cration de l'objet charg de grer les vnements de la fentre est un peu lourde dans la mesure o on est oblig de dfinir des mthodes mme pour des vnements qu'on ne veut pas grer. Dans ce cas, au lieu d'utiliser l'interface WindowListener on peut utiliser la classe WindowAdapter. Celle-ci implmente l'interface WindowListener, avec sept mthodes vides. En drivant la classe WindowAdapter et en redfinissant les seules mthodes qui nous intressent, nous arrivons au mme rsultat qu'avec l'interface WindowListener mais sans avoir besoin de dfinir les mthodes qui ne nous intressent pas. La squence dfinition du gestionnaire d'vnements association du gestionnaire la fentre
Nous utilisons ici une classe anonyme qui drive la classe WindowAdapter et redfinit sa mthode windowClosing. Le programme devient alors :
// classes importes import javax.swing.*; import java.awt.*; import java.io.*; import java.awt.event.*; // la classe formulaire public class form2 extends JFrame { // le constructeur public form2() { // titre de la fentre this.setTitle("Mon premier formulaire"); // dimensions de la fentre this.setSize(new Dimension(300,100)); // cration d'un gestionnaire d'vnements WindowAdapter win=new WindowAdapter(){ public void windowClosing(WindowEvent e){System.exit(0);} };//dfinition win // ce gestionnaire d'vnements va grer les vts de la fentre courante this.addWindowListener(win); }//constructeur // fonction de test public static void main(String[] args) { // on affiche le formulaire new form2().setVisible(true); }//main }//classe
Il donne les mmes rsultats que le prcdent programme mais est plus simple d'criture.
- 124 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Une fentre JFrame a un conteneur dans lequel on peut dposer des composants graphiques (bouton, cases cocher, listes droulantes, ...). Ce conteneur est disponible via la mthode getContentPane de la classe JFrame :
Container conteneur=null; .......... // on rcupre le conteneur de la fentre conteneur=this.getContentPane();
Tout composant est plac dans le conteneur par la mthode add de la classe Container . Ainsi pour dposer le composant C dans l'objet conteneur prcdent, on crira :
conteneur.add(C)
O ce composant est-il plac dans le conteneur ? Il existe divers gestionnaires de disposition de composants portant le nom XXXLayout, avec XXX gal par exemple Border, Flow, ... Chaque gestionnaire de disposition a ses particularits. Par exemple, le gestionnaire FlowLayout dispose les composants en ligne en commenant par le haut du formulaire. Lorsqu'une ligne a t remplie, les composants sont placs sur la ligne suivante. Pour associer un
- 125 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
gestionnaire de mise en forme une fentre JFrame, on utilise la mthode setLayout de la classe JFrame sous la forme :
setLayout(objet XXXLayout);
Ainsi dans notre exemple, pour associer un gestionnaire de type FlowLayout la fentre, on a crit :
// on choisit un gestionnaire de mise en forme des composants dans ce conteneur conteneur.setLayout(new FlowLayout());
Dans ce cas, on devra donner les coordonnes prcises du composant dans le conteneur sous la forme (x,y,largeur,hauteur) o (x,y) sont les coordonnes du coin suprieur gauche du composant dans le conteneur. C'est cette mthode que nous utiliserons le plus souvent par la suite. On sait maintenant comment sont dposs les composants au conteneur (add) et o (setLayout). Il nous reste connatre les composants qu'on peut placer dans un conteneur. Ici nous plaons un bouton modlis par la classe javax.swing.JButton :
JButton btnTest=null; .......... // on cre un bouton btnTest=new JButton(); // on fixe son libell btnTest.setText("Test"); // on ajoute le bouton au conteneur conteneur.add(btnTest);
Si on redimensionne le formulaire ci-dessus, le gestionnaire de disposition du conteneur est automatiquement appel pour replacer les composants :
C'est le principal intrt des gestionnaires de disposition : celui de maintenir une disposition cohrente des composants au fil des modifications de la taille du conteneur. Utilisons le gestionnaire de disposition null pour voir la diffrence. Le bouton est maintenant plac dans le conteneur par les instructions suivantes :
// on choisit un gestionnaire de mise en forme des composants dans ce conteneur conteneur.setLayout(null); // on cre un bouton btnTest=new JButton(); // on fixe son libell btnTest.setText("Test"); // on fixe son emplacement et ses dimensions btnTest.setBounds(10,20,100,20);
- 126 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ici, on place explicitement le bouton au point (10,20) du formulaire et on fixe ses dimensions 100 pixels pour la largeur et 20 pixels pour la hauteur. La nouvelle fentre devient la suivante :
Si on clique sur le bouton Test, il ne se passe rien. En effet, nous n'avons pas encore associ de gestionnaire d'vnements au bouton. Pour connatre le type de gestionnaires d'vnements disponibles pour un composant donn, on peut chercher dans la dfinition de sa classe des mthodes addXXXListener qui permettent d'associer au composant un gestionnaire d'vnements. La classe javax.swing.JButton drive de la classe javax.swing.AbstractButton dans laquelle on trouve les mthodes suivantes : Method Summary void void void
Ici, il faut lire la documentation pour savoir quel gestionnaire d'vnements gre le clic sur le bouton. C'est l'interface ActionListener. Celle-ci ne dfinit qu'une mthode : Method Summary void
actionPerformed(Ac
La mthode reoit un paramtre ActionEvent que nous ignorerons pour le moment. Pour grer le clic sur le bouton btntest de notre programme on lui associe d'abord un gestionnaire d'vnements :
btnTest.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt){ btnTest_clic(evt); } }//classe anonyme );//gestionnaire d'evt
Ici, la mthode actionPerformed renvoie la mthode btnTest_clic que nous dfinissons de la faon suivante :
public void btnTest_clic(ActionEvent evt){ // suivi console System.out.println("clic sur bouton"); }//btnTest_click
A chaque fois que l'utilisateur clique sur le bouton Test, on crit un message sur la console. C'est ce que montre l'excution suivante :
- 127 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 128 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 129 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
JTextArea JTextField
Mthode d'enregistrement des gestionnaires d'venements public void addActionListener(ActionListener) public void addItemListener(ItemListener) public void addItemListener(ItemListener) public void addItemListener(ItemListener) public void addActionListener(ActionListener) public void addContainerListener(ContainerListener) public void addComponentListener(ComponentListener) public void addFocusListener(FocusListener) public void addKeyListener(KeyListener) public void addMouseListener(MouseListener) public void addMouseMotionListener(MouseMotionListener) public void addWindowlistener(WindowListener) public void addItemListener(ItemListener) public void addActionListener(ActionListener) comme Container comme Container public void addAdjustmentListener(AdjustmentListener) public void addInputMethodListener(InputMethodListener) public void addCaretListener(CaretListener) comme JTextComponent comme JTextComponent public void addActionListener(ActionListener)
Tous les composants, sauf ceux du type TextXXX, tant drivs de la classe JComponent, possdent galement les mthodes associes cette classe.
- 130 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
ContainerListener
MouseListener
CaretLisetner WindowListener
Mthodes public void actionPerformed(ActionEvent) public void adjustmentValueChanged(AdjustmentEvent) public void componentHidden(ComponentEvent) public void componentMoved(ComponentEvent) public void componentResized(ComponentEvent) public void componentShown(ComponentEvent) public void componentAdded(ContainerEvent) public void componentRemoved(ContainerEvent) public void focusGained(FocusEvent) public void focusLost(FocusEvent) public void itemStateChanged(ItemEvent) public void keyPressed(KeyEvent) public void keyReleased(KeyEvent) public void keyTyped(KeyEvent) public void mouseClicked(MouseEvent) public void mouseEntered(MouseEvent) public void mouseExited(MouseEvent) public void mousePressed(MouseEvent) public void mouseReleased(MouseEvent) public void mouseDragged(MouseEvent) public void mouseMoved(MouseEvent) public void textValueChanged(TextEvent) public void InputMethodTextChanged(InputMethodEvent) public void caretPositionChanged(InputMethodEvent) public void caretUpdate(CaretEvent) public void windowActivated(WindowEvent) public void windowClosed(WindowEvent) public void windowClosing(WindowEvent) public void windowDeactivated(WindowEvent) public void windowDeiconified(WindowEvent) public void windowIconified(WindowEvent) public void windowOpened(WindowEvent)
- 131 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Supposons qu'on veuille grer les clics de souris sur un composant Frame f1. On pourrait lui associer un gestionnaire d'vnements par :
f1.addMouseListener(new gestionnaireSouris());
et crire :
public class gestionnaireSouris implements MouseListener{ // on crit les 5 mthodes de l'interface MouseListener // mouseClicked, ..., mouseReleased) }// fin classe
Comme on ne souhaite grer que les clics de souris, il est cependant prfrable d'crire :
public class gestionnaireSouris extends MouseAdapter{ // on crit une seule mthode, celle qui gre les clics de souris public void mouseClicked(MouseEvent evt){ # } }// fin classe
Le tableau suivant donne les classes adapteurs des diffrents gestionnaires d'vnements : Gestionnaire d'vnements ComponentListener ContainerListener FocusListener KeyListener MouseListener MouseMotionListener WindowListener Adaptateur ComponentAdapter ContainerAdapter FocusAdapter KeyAdapter MouseAdapter MouseMotionAdapter WindowAdapter
IV-A-7 - Conclusion
Nous venons de prsenter les concepts de base de la cration d'interfaces graphiques en Java : cration d'une fentre cration de composants association des composants la fentre avec un gestionnaire de disposition association de gestionnaires d'vneemnts aux composants
Maintenant, plutt que de construire des interfaces graphiques " la main" comme il vient d'tre fait nous allons utiliser Jbuilder, un outil de dveloppement Java de Borland/Inprise dans sa version 4 et suprieure.Nous utiliserons les composants de la bibliothque java.swing actuellement prconise par Sun, crateur de Java.
IV-B - Construire une interface graphique avec JBuilder IV-B-1 - Notre premier projet Jbuilder
Afin de nous familiariser avec Jbuilder, construisons une application trs simple : une fentre vide. 1. Lancez Jbuilder et prendre l'option Fichier/nouveau projet. La 1re page d'un assistant s'affiche alors :
- 132 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
2. Remplir les champs suivants : Nom du projet dbut provoquera la cration d'un fichier projet dbut.jpr sous le dossier indiqu dans le champ "Nom du rpertoire du projet" indiquez le dossier sous lequel sera cr le dossier du projet que vous allez crer. indiquez le nom du dossier o seront placs tous les fichiers du projet. Ce dossier sera cr sous le rpertoire indiqu dans le champ "Chemin racine"
Les fichiers source (.java, .html, ...), les fichiers destinations (.class,..), les fichiers de sauvegarde pourraient aller dans des rpertoires diffrents. En laissant leurs champs vides, ils seront placs dans le mme rpertoire que le projet. Faites [suivant] 3. Un cran confirme les choix de l'tape prcdente
- 133 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Faites [terminer] 5. Vrifier que l'option Voir/projet est coche. Vous devriez voir la structure de votre projet dans la fentre de gauche.
6. Maintenant construisons une interface graphique dans ce projet. Choisissez l'option Fichier/Nouveau/Application :
- 134 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Dans le champ classe, on met le nom de la classe qui va tre cre. Ici on a repris le mme nom que le projet. Faites [suivant] 7. L'cran suivant apparat :
Classe
Titre
interfaceDbut : C'est le nom de la classe correspondant la fentre qui va tre construite C'est le texte qui apparatra dans la barre de titre de la fentre
Notez que ci-dessus, nous avons demand que la fentre soit centre sur l'cran au dmarrage de l'application. Faites [Terminer] 8. C'est maintenant que Jbuilder s'avre utile.
- 135 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
il gnre les fichiers source .java des deux classes dont on a donn les noms : la classe de l'application et celle de l'interface graphique. On voit apparatre ces deux fichiers dans la structure du projet dans la fentre de gauche
pour avoir accs au code gnr pour les deux classes, il suffit de double-cliquer sur le fichier .java correspondant. Nous reviendrons ultrieurement sur le code gnr. Vrifiez que l'option Voir/Structure est coche. Elle permet de voir la structure de la classe actuellement slectionne (double clic sur le .java). Voici par exemple la structure de la classe dbut :
On apprend ici : les bibliothques importes (imports) qu'il y a un constructeur dbut() qu'il y a une mthode statique main() qu'il y a un attribut packFrame
Quel est l'intrt d'avoir accs la structure d'une classe ? vous avez une vue d'ensemble de celle-ci. C'est utile si votre classe est complexe. vous pouvez accder au code d'une mthode en cliquant dessus dans la fentre de structure de la classe. De nouveau c'est utile si votre classe a des centaines de lignes. Vous n'tes pas oblig de passer toutes les lignes en revue pour trouver le code que vous cherchez.
Le code gnr par Jbuilder est dj utilisable. Faites Excuter/Excuter le projet ou F9 et vous obtiendrez la fentre demande :
De plus, elle se ferme proprement lorsqu'on clique sur le bouton de fermeture de la fentre. Nous venons de construire notre premire interface graphique. Nous pouvons sauvegarder notre projet par l'option Fichier/Fermer les projets :
- 136 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
En appuyant sur Tous, tous les projets prsents dans la fentre ci-dessus seront cochs. OK les fermera. Si nous avons la curiosit d'aller, avec l'explorateur windows, dans le dossier de notre projet (celui qui a t indiqu l'assistant au dbut de la configuration du projet), nous y trouvons les fichiers suivants :
Dans notre exemple, nous avions demand ce que tous les fichiers (source .java, destination .class, sauvegarde .jpr~) soient dans le mme dossier que le projet .jpr.
IV-B-2 - Les fichiers gnrs par Jbuilder pour une interface graphique
Ayons maintenant la curiosit de regarder ce que Jbuilder a gnr comme fichiers source .java. Il est important de savoir lire ce qui est gnr puisque la plupart du temps nous sommes amens ajouter du code ce qui a t gnr. Commenons par rcuprer notre projet : Fichier/Ouvrir un projet et slectionnons le projet dbut.jpr. Nous retrouvons le projet construit prcdemment.
- 137 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
else { frame.validate(); } //Centrer la fentre Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); if (frameSize.height > screenSize.height) { frameSize.height = screenSize.height; } if (frameSize.width > screenSize.width) { frameSize.width = screenSize.width; } frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height frameSize.height) / 2); frame.setVisible(true); } /**Mthode principale*/ public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { e.printStackTrace(); } new dbut(); } }
Commentons le code gnr : 1 2 3 la fonction main fixe l'aspect de la fentre (setLookAndFeel) et cre une instance de la classe dbut. le constructeur dbut() est alors excut. Il cre une instance frame de la classe de la fentre (new interfaceDbut()). Celle-ci est construite mais pas affiche. La fentre est alors dimensionne selon les informations disponibles pour chacun des composants de la fentre (frame.validate). Elle commence alors son existence spare en s'affichant et en rpondant aux sollicitations de l'utilisateur. La fentre est centre sur l'cran ceci parce qu'on l'avait demand lors de la configuration de la fentre avec l'assistant.
Voyons ce qui serait obtenu si on rduisait le code dbut.java son strict minimum telle que nous l'avons fait en dbut de chapitre. Crons une nouvelle classe. Prenez l'option Fichier/Nouvelle classe :
- 138 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nommez la nouvelle classe dbut2 et faites [Terminer]. Un nouveau fichier apparat dans le projet :
La fonction main cre une instance de la fentre interfaceDbut et l'affiche (show). Avant d'excuter notre projet, il nous faut signaler que la classe contenant la fonction main excuter est maintenant la classe dbut2. Cliquez droit sur le projet dbut.jpr et choisissez l'option proprits puis l'onglet Excution :
- 139 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ici, il est indiqu que la classe principale est dbut (1). Appuyez sur le bouton (2) pour choisir une autre classe principale :
Faites [OK] pour valider ce choix puis demandez l'excution du projet par Excuter/Excuter projet ou F9. Vous obtenez la mme fentre qu'avec la classe dbut si ce n'est qu'elle n'est pas centre puisqu'ici cela n'a pas t
- 140 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
demand. Par la suite, nous ne prsenterons plus la classe principale gnre par Jbuilder car elle fait toujours la mme chose : crer une fentre. C'est sur la classe de cette dernire que dsormais nous nous concentrerons.
Il s'agit des bibliothques java.awt, java.awt.event et javax.swing. Les deux premires taient les seules disponibles pour construire des interfaces graphiques avec les premires versions de Java. La bibliothque javax.swing est plus rcente. Ici, elle est ncessaire pour la fentre de type JFrame qui est utilise ici. Les attributs
JPanel contentPane; BorderLayout borderLayout1 = new BorderLayout();
JPanel est un type conteneur dans lequel on peut mettre des composants. BorderLayout est l'un des types de gestionnaire de mise en forme disponibles pour placer les composants dans le conteneur. Dans tous nos exemples, nous n'utiliserons pas de gestionnaire de mise en forme et placerons nous-mmes les composants un endroit prcis du conteneur. Pour cela, nous utiliserons le gestionnaire de mise en forme null.
- 141 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le constructeur de la fentre
/**Construire le cadre*/ public interfaceDbut() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Initialiser le composant*/ private void jbInit() throws Exception { contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(borderLayout1); this.setSize(new Dimension(400, 300)); this.setTitle("Ma premire interface graphique avec Jbuilder"); }
1 2 3 4 5
Le constructeur commence par dire qu'il va grer les vnements sur la fentre (enableEvents), puis il lance la mthode jbInit. Le conteneur (JPanel) de la fentre (JFrame) est obtenu (getContentPane) Le gestionnaire de mise en forme est fix (setLayout) La taille de la fentre est fixe (setSize) Le titre de la fentre est fix (setTitle)
Le gestionnaire d'vnements
/**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); }
Le constructeur avait indiqu que la classe traiterait les vnements de la fentre. C'est la mthode processWindowEvent qui fait ce travail. Elle commence par transmettre sa classe parent (JFrame) l'vnement WindowEvent reu puis si celui-ci est l'vnement WINDOW_CLOSING provoqu par le clic sur le bouton de fermeture de la fentre, l'application est arrte. Conclusion Le code de la classe de la fentre est diffrent de celui prsent dans l'exemple de dbut de chapitre. Si nous utilisions un autre outil de gnration Java que Jbuilder nous aurions sans doute un code encore diffrent. Dans la pratique, nous accepterons le code produit par Jbuilder pour construire la fentre afin de nous concentrer uniquement sur l'criture des gestionnaires d'vnements de l'interface graphique.
- 142 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les champs sont les suivants : n 1 2 3 nom lblSaisie txtSaisie cmdAfficher type JLabel JTextField JButton rle un libell une zone de saisie pour afficher dans une bote de dialogue le contenu de la zone de saisie txtSaisie
En procdant comme pour le projet prcdent, construisez le projet interface2.jpr sans mettre pour l'instant de composants dans la fentre.
Dans la fentre ci-dessus, slectionnez la classe interface2.java de la fentre. A droite de cette fentre, se trouve un classeur onglets : L'onglet Source donne accs au code source de la classe interface2.java. L'onglet Conception permet de construire visuellement la fentre. Slectionnez cet onglet. Vous avez devant vous le conteneur de la fentre, qui va recevoir les composants que vous allez y dposer. Il est pour l'instant vide. Dans la fentre de gauche est montre la structure de la classe :
this contentPane
borderLayout1
reprsente la fentre son conteneur dans lequel on va dposer des composants ainsi que le mode de mise en forme de ces composants dans le conteneur (BorderLayout par dfaut) une instance du gestionnaire de mise en forme
Slectionnez l'objet this. Sa fentre de proprits apparat alors sur la droite : Certaines de ces proprits sont noter :
- 143 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
pour fixer la couleur de fond de la fentre pour fixer la couleur des dessins sur la fentre pour associer un menu la fentre pour donner un titre la fentre pour fixer le type de fentre pour fixer la police de caractres des critures dans la fentre
L'objet this tant toujours slectionn, on peut redimensionner le conteneur affich l'cran en tirant sur les points d'ancrage situs autour du conteneur :
Nous sommes maintenant prts dposer des composants dans le conteneur ci-dessus. Auparavant, nous allons changer le gestionnaire de mise en forme. Slectionnez l'objet contentPane dans la fentre de structure :
Puis dans la fentre de proprits de cet objet, slectionnez la proprit layout et choisissez parmi les valeurs possibles, la valeur null :
- 144 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cette absence de gestionnaire de mise en forme va nous permettre de placer librement les composants dans le conteneur. Il est temps maintenant de choisir ceux-ci. Lorsque le volet Conception est slectionn, les composants sont disponibles dans un classeur onglets en haut de la fentre de conception :
Pour construire l'interface graphique, nous disposons de composants swing (1) et de composants awt (2). Nous allons utiliser ici les composants swing. Dans la barre de composants ci-dessus, choisissez un composant JLabel (3), un composant JTextField (4) et un composant JButton (5) et placez-les dans le conteneur de la fentre de conception.
Maintenant personnalisons chacun de ces 3 composants : l'tiquette (JLabel) jLabel1 Slectionnez le composant pour avoir sa fentre de proprits. Dans celle-ci, modifiez les proprits suivantes : name : lblSaisie, text : Saisie le champ de saisie (JTextField) jTextfield1 Slectionnez le composant pour avoir sa fentre de proprits. Dans celle-ci, modifiez les proprits suivantes : name : txtSaisie, text : ne rien mettre le bouton (JButton) : name : cmdAfficher, text : Afficher
- 145 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
et la structure suivante :
Nous pouvons excuter (F9) notre projet pour avoir un premier aperu de la fentre en action :
Fermez la fentre. Il nous reste crire la procdure lie un clic sur le bouton Afficher. Slectionnez le bouton pour avoir accs sa fentre de proprits. Celle-ci a deux onglets : proprits et vnements. Choisissez vnements.
- 146 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La colonne de gauche de la fentre liste les vnements possibles sur le bouton. Un clic sur un bouton correspond l'vnement actionPerformed. La colonne de droite contient le nom de la procdure appele lorsque l'vnement correspondant se produit. Cliquez sur la cellule droite de l'vnement actionPerformed :
Jbuilder gnre un nom par dfaut pour chaque gestionnaire d'vnement de la forme nomComposant_nomEvnement ici cmdAfficher_actionPerformed. On pourrait effacer le nom propos par dfaut et en inscrire un autre. Pour avoir accs au code du gestionnaire cmdAfficher_actionPerformed il suffit de double-cliquer sur son nom ci-dessus. On passe alors automatiquement au volet source de la classe positionn sur le squelette du code du gestionnaire d'vnement :
void cmdAfficher_actionPerformed(ActionEvent e) { }
Il ne nous reste plus qu' complter ce code. Ici, nous voulons prsenter une bote de dialogue avec dedans le contenu du champ txtSaisie :
void cmdAfficher_actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vrification de la saisie",JOptionPane.INFORMATION_MESSAGE); }
JOptionPane est une classe de la bibliothque javax.swing. Elle permet d'afficher des messages accompagns d'une icne ou de demander des informations l'utilisateur. Ici, nous utilisons une mthode statique de la classe :
l'objet conteneur "parent" de la bote de dialogue : ici this. un objet afficher. Ici le contenu du champ de saisie le titre de la bote de dialogue le type du message afficher. Conditionne l'icne qui sera affiche dans la bote ct du message. Les valeurs possibles : INFORMATION_MESSAGE, QUESTION_MESSAGE, ERROR_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE
- 147 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public class interface2 extends JFrame { JPanel contentPane; JLabel lblSaisie = new JLabel(); JTextField txtSaisie = new JTextField(); JButton cmdAfficher = new JButton(); /**Construire le cadre*/ public interface2() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Initialiser le composant*/ private void jbInit() throws Exception { lblSaisie.setText("Saisie"); lblSaisie.setBounds(new Rectangle(25, 23, 71, 21)); contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(null); this.setSize(new Dimension(304, 129)); this.setTitle("Saisies & boutons - 1"); txtSaisie.setBounds(new Rectangle(120, 21, 138, 24)); cmdAfficher.setText("Afficher"); cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20)); cmdAfficher.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdAfficher_actionPerformed(e); } }); contentPane.add(lblSaisie, null); contentPane.add(txtSaisie, null); contentPane.add(cmdAfficher, null); } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } - 148 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les attributs
JPanel contentPane; JLabel lblSaisie = new JLabel(); JTextField txtSaisie = new JTextField(); JButton cmdAfficher = new JButton();
On trouve le conteneur des composants de type JPanel et les trois composants. Le constructeur
/**Construire le cadre*/ public interface2() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Initialiser le composant*/ private void jbInit() throws Exception { lblSaisie.setText("Saisie"); lblSaisie.setBounds(new Rectangle(25, 23, 71, 21)); contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(null); this.setSize(new Dimension(304, 129)); this.setTitle("Saisies & boutons - 1"); txtSaisie.setBounds(new Rectangle(120, 21, 138, 24)); cmdAfficher.setText("Afficher"); cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20)); cmdAfficher.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdAfficher_actionPerformed(e); } }); contentPane.add(lblSaisie, null); contentPane.add(txtSaisie, null); contentPane.add(cmdAfficher, null); }
Le constructeur interface2 est semblable au constructeur de la prcdente interface graphique tudie. C'est dans la mthode jbInit qu'on trouve des diffrences : le code de construction de la fentre dpend des composants qu'on y a placs. On peut reprendre le code de jbInit en y mettant nos propres commentaires :
private void jbInit() throws Exception { // la fentre elle-mme (taille, titre) this.setSize(new Dimension(304, 129)); this.setTitle("Saisies & boutons - 1"); // le conteneur des composants contentPane = (JPanel) this.getContentPane(); // pas de gestionnaire de mise en forme pour ce conteneur contentPane.setLayout(null); // l'tiquette lblSaisie (libell, position, taille) lblSaisie.setText("Saisie"); lblSaisie.setBounds(new Rectangle(25, 23, 71, 21)); // le champ de saisie (position, taille) txtSaisie.setBounds(new Rectangle(120, 21, 138, 24)); // le bouton Afficher (libell, position, taille) cmdAfficher.setText("Afficher");
- 149 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20)); // le gestionnaire d'vt du bouton cmdAfficher.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdAfficher_actionPerformed(e); } }); // ajout des 3 composants au conteneur contentPane.add(lblSaisie, null); contentPane.add(txtSaisie, null); contentPane.add(cmdAfficher, null); }//jbInit
On notera deux points : ce code aurait pu tre crit la main. Cela veut dire qu'on peut se passer de Jbuilder pour construire une interface graphique. la faon dont le gestionnaire d'vnement du bouton cmdAfficher est fix. Le gestionnaire d'vnement du composant cmdAfficher aurait pu tre dclar par cmdAfficher.addActionListener(new gestionnaire()) o gestionnaire serait une classe avec une mthode publique actionPerformed charge de grer le clic sur le bouton Afficher. Ici, Jbuilder utilise comme gestionnaire, une instance d'une classe anonyme :
new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdAfficher_actionPerformed(e); }
Une nouvelle instance de l'interface ActionListener est cre avec sa mthode actionPerformed dfinie dans la foule. Celle-ci se contente d'appeler une mthode de la classe interface2. Tout ceci n'est qu'un artifice pour dfinir dans la mme classe que la fentre les procdures de traitement des vnements des composants de cette fentre. On pourrait procder autrement :
cmdAfficher.addActionListener(this)
qui fait que la mthode actionPerformed sera cherche dans this c'est dire dans la classe de la fentre. Cette seconde mthode semble plus simple mais la premire a sur elle un avantage : elle permet d'avoir des gestionnaires diffrents pour des boutons diffrents alors que la seconde mthode ne le permet pas. Dans de dernier cas, en effet, l'unique mthode actionPeformed doit traiter les clics de diffrents boutons et donc commencer par identifier lequel est l'origine de l'vnement avant de commencer travailler. Les gestionnaires d'vnements On retrouve ceux dj tudis :
/**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } // clic sur bouton Afficher void cmdAfficher_actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vrification de la saisie",JOptionPane.INFORMATION_MESSAGE); }
- 150 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IV-B-3-c - Conclusion
Des deux projets tudis, nous pouvons conclure qu'une fois l'interface graphique construite avec Jbuilder, le travail du dveloppeur consiste crire les gestionnaires des vnements qu'il veut grer pour cette interface graphique.
L'cran d'aide a gnralement deux fentres : celle de gauche o l'on dit ce qu'on cherche. Elle a trois onglets : Sommaire, Index et Chercher. celle de droite qui prsente le rsultat de la recherche
On dispose d'une aide sur la faon d'utiliser l'aide de Jbuilder. Choisissez dans l'aide de Jbuilder, l'option Aide/ Utilisation de l'aide. On vous explique alors comment utiliser l'aide. On vous indique par exemple les diffrentes composantes du visualisateur d'aide :
- 151 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Sommaire : Introduction Java On trouvera ici des lments de base de Java mais pas seulement comme le montre la liste des thmes voqus dans cette option :
- 152 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Sommaire : Tutoriels Si nous slectionnons l'option Tutoriels dans le sommaire ci-dessus, la fentre de droite nous prsente une liste de tutoriels disponibles :
Les tutoriels de base sont particulirement intressants pour commencer prendre en main Jbuilder. Il en existe beaucoup d'autres que ceux prsents ci-dessus et lorsqu'on veut dvelopper une application il peut tre utile de vrifier auparavant s'il n'y a pas un tutoriel qui pourrait nous aider. Sommaire : le JDK En slectionnant l'option Java 2 JDK 1.3, on a accs toutes les bibliothques du JDK. Gnralement ce n'est pas l qu'il faut chercher si on a besoin d'informations sur une classe prcise et qu'on ne sait pas dans quelle bibliothque elle se trouve. Par contre, cette option prsente de l'intrt si on est intress par avoir une vue globale des bibliothques de Java.
- 153 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Il vous reste double-cliquer sur l'entre qui vous intresse, ici JTextField class. L'aide sur cette classe s'affiche alors dans la fentre de droite :
- 154 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
signale que l'utilisateur a valid (touche Entre) le texte saisi signale que l'utilisateur boug le curseur de saisie signale que l'utilisateur modifi le champ de saisie
Voici un exemple qui utilise l'vnement caretUpdate pour suivre les volutions d'un champ de saisie :
n 1 2 3 4
rle champ de saisie affiche le texte de 1 en temps rel pour effacer les champs 1 et 2 pour quitter l'application
- 155 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}); ... CmdEffacer.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { CmdEffacer_actionPerformed(e); } }); ... CmdQuitter.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { CmdQuitter_actionPerformed(e); } }); .... } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ... } void txtSaisie_caretUpdate(CaretEvent e) { // le curseur de saisie a boug txtControle.setText(txtSaisie.getText()); } void CmdQuitter_actionPerformed(ActionEvent e) { // on quitte l'application System.exit(0); } void CmdEffacer_actionPerformed(ActionEvent e) { // on efface le contenu du champ de saisie txtSaisie.setText(""); } }
- 156 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Un composant JComboBox est une liste droulante double d'une zone de saisie : l'utilisateur peut soit choisir un lment dans (2) soit taper du texte dans (1). Par dfaut, les JComboBox ne sont pas ditables. Il faut appeler explicitement la mthode setEditable(true) pour qu'ils le deviennent. Pour dcouvrir la classe JComboBox, tapez JComboBox dans l'index de l'aide. L'objet JComboBox peut tre construit de diffrentes faons : new JComboBox() new JComboBox (Object[] items) new JComboBox(Vector items) cre un combo vide cre un combo contenant un tableau d'objets idem avec un vecteur d'objets
On peut s'tonner qu'un combo puisse contenir des objets alors qu'habituellement il contient des chanes de caractres. Au niveau visuel, ce sera le cas. Si un JComboBox contient un objet obj, il affiche la chane obj.toString(). On se rappelle que tout objet a une mthode toString hrite de la classe Object et qui rend une chane de caractres "reprsentative" de l'objet. Les mthodes utiles de la classe JCombobox sont les suivantes : void addItem(Object unObjet) int getItemCount() Object getItemAt(int i) void insertItemAt(Object unObjet, int i) int getSelectedIndex() Object getSelectedItem() void setSelectedIndex(int i) void setSelectedItem(Object unObjet) void removeAllItems() void removeItemAt(int i) void removeItem(Object unObjet) void setEditable(boolean val) ajoute un objet au combo donne le nombre d'lments du combo donne l'objet n i du combo insre unObjet en position i du combo donne le n de l'lment slectionn dans le combo donne l'objet slectionn dans le combo slectione l'lment i du combo slectionne l'objet spcifi dans le combo vide le combo enlve l'lment n i du combo enlve l'objet spcifi du combo rend le combo ditable (val=true) ou non (val=false)
Lors du choix d'un lment dans la liste droulante se produit l'vnement actionPerformed qui peut tre alors utilis pour tre averti du changement de slection dans le combo. Dans l'application suivante, nous utilisons cet vnement pour afficher l'lment qui a t slectionn dans la liste.
- 157 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
le contenu de la liste est gr par un objet diffrent de la liste elle-mme. Ici nous prendrons un objet DefaultListModel objet qui s'utilise comme un Vector mais qui de plus avertit l'objet JList ds que son contenu change afin que l'affichage visuel de la liste change aussi. la liste n'est pas dfilante par dfaut. Il faut mettre la liste dans un conteneur ScrollPane qui lui, permet ce dfilement.
Dans le code source, la dfinition d'une liste peut se faire de la faon suivante :
// le vecteur des valeurs de la liste DefaultlistModel valeurs=new DefaultListModel(); // la liste elle-mme laquelle on associe le vecteur de ses valeurs JList jList1 = new JList(valeurs); // le conteneur dfilant dans lequel on place la liste pour avoir une liste dfilante JScrollPane jScrollPane1 = new JScrollPane(jList1);
Pour inclure la liste jList1 dans le conteneur jScrollPane1, le code gnr par JBuilder procde diffremment : dclaration du conteneur dans les attributs de la fentre
JScrollPane jScrollPane1 = new JScrollPane();
Pour ajouter des valeurs la liste JList1 ci-dessus, il suffit de les ajouter son vecteur de valeurs valeurs :
// init liste for(int i=0;i<10;i++) valeurs.addElement(""+i);
Comment cette interface est-elle construite ? on choisit un composant JScrollPane dans la page "Conteneurs swing" des composants et on le dpose dans la fentre en le dimensionnant la taille dsire on choisit un composant JList dans la page "swing" des composants et on le dpose dans le conteneur JScrollPane dont il occupe alors toute la place.
Le code gnr par Jbuilder doit tre lgrement remani pour obtenir le code suivant :
public class interfaceAppli extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); DefaultListModel valeurs=new DefaultListModel();
- 159 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
JList jList1 = new JList(valeurs); JScrollPane jScrollPane1 = new JScrollPane(); JLabel jLabel2 = new JLabel(); /**Construire le cadre*/ public interfaceAppli() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } // traitement // on inclut la liste dans le scrollPane // init liste for(int i=0;i<10;i++) valeurs.addElement(""+i); } /**Initialiser le composant*/ private void jbInit() throws Exception { .... // la liste jList1 est associ au conteneur jcrollPane1 jScrollPane1.getViewport().add(jList1, null); } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { .... } }
Dcouvrons maintenant les principales mthodes de la classe JList en cherchant JList dans l'index de l'aide. L'objet JList peut tre construit de diffrentes faons :
Une mthode simple est celle que nous avons utilise : crer un DefaultListModel V vide puis l'associer la liste crer par new JList(V). Le contenu de la liste n'est pas gr par l'objet JList mais par l'objet contenant les valeurs de la liste. Si le contenu a t construit l'aide d'un objet DefaultListModel qui repose sur la classe Vector, ce sont les mthodes de la classe Vector qui pourront tre utilises pour ajouter, insrer et supprimer des lments de la liste. Une liste peut tre slection simple ou multiple. Ceci est fix par la mthode setSelectionMode :
- 160 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le ou les lments slectionns peuvent tre obtenus via les mthodes suivantes :
Nous savons associer un vecteur de valeurs une liste avec le constructeur JList(DefaultListModel). Inversement nous pouvons obtenir l'objet DefaultListModel d'une liste JList par :
- 161 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les composants de cette fentre sont les suivants : n 1 2 type JTextField JList nom txtSaisie jList1 rle champ de saisie liste contenue dans un conteneur jScrollPane1 liste contenue dans un conteneur jScrollPane2 transfre les lments slectionns de liste 1 vers liste 2 fait l'inverse vide la liste 1 vide la liste 2
JList
jList2
JButton
cmd1To2
5 6 7
L'utilisateur tape du texte dans le champ (1) qu'il valide. Se produit alors l'vnement actionPerformed sur le champ de saisie qui est utilis pour ajouter le texte saisi dans la liste 1. Voici le code utile pour cette premire fonction :
public class interfaceAppli extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); JLabel jLabel2 = new JLabel(); JLabel jLabel3 = new JLabel(); JTextField txtSaisie = new JTextField(); JButton cmd1To2 = new JButton(); JButton cmd2To1 = new JButton(); DefaultListModel v1=new DefaultListModel(); DefaultListModel v2=new DefaultListModel(); JList jList1 = new JList(v1); JList jList2 = new JList(v2); JScrollPane jScrollPane1 = new JScrollPane(); JScrollPane jScrollPane2 = new JScrollPane(); JButton cmdRaz1 = new JButton(); JButton cmdRaz2 = new JButton(); JLabel jLabel4 = new JLabel(); /**Construire le cadre*/ public interfaceAppli() {
- 162 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } }//interfaceAppli /**Initialiser le composant*/ private void jbInit() throws Exception { ... txtSaisie.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { txtSaisie_actionPerformed(e); } }); ... // Jlist1 est plac dans le conteneur jScrollPane1 jScrollPane1.getViewport().add(jList1, null); // Jlist2 est plac dans le conteneur jScrollPane2 jScrollPane2.getViewport().add(jList2, null); ... } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ... } void txtSaisie_actionPerformed(ActionEvent e) { // le texte de la saisie a t valid // on le rcupre dbarrass de ses espaces de dbut et fin String texte=txtSaisie.getText().trim(); // s'il est vide, on n'en veut pas if(texte.equals("")){ // msg d'erreur JOptionPane.showMessageDialog(this,"Vous devez taper un texte", "Erreur",JOptionPane.WARNING_MESSAGE); // fin return; }//if // s'il n'est pas vide, on l'ajoute aux valeurs de la liste 1 v1.addElement(texte); // et on vide le champ de saisie txtSaisie.setText(""); }/// txtSaisie_actionperformed }//classe
Le code de transfert des lments slectionns d'une liste vers l'autre est le suivant :
void cmd1To2_actionPerformed(ActionEvent e) { // transfert des lments slectionns dans la liste 1 vers la liste 2 transfert(jList1,jList2); }//cmd1To2 void cmd2To1_actionPerformed(ActionEvent e) { // transfert des lments slectionns dans jList2 vers jList1 transfert(jList2,jList1); }//cmd2TO1 private void transfert(JList L1, JList L2){ // transfert des lments slectionns dans la liste 1 vers la liste 2 // on rcupre le tableau des indices des lments slectionns dans L1 int[] indices=L1.getSelectedIndices(); // qq chose faire ? if (indices.length==0) return; // on rcupre les valeurs de L1 DefaultListModel v1=(DefaultListModel)L1.getModel(); // et celles de L2 DefaultListModel v2=(DefaultListModel)L2.getModel(); for(int i=indices.length-1;i>=0;i--){ // on ajoute L2 les valeurs slectionnes dans L1 v2.addElement(v1.elementAt(indices[i]));
- 163 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// les lments de L1 copis dans L2 doivent tre supprims de L1 v1.removeElementAt(indices[i]); }//for }//transfert
Les composants de la fentre sont les suivants : n 1 type JButtonRadio nom jButtonRadio1 rle 3 boutons radio faisant partie du groupe buttonGroup1
JCheckBox
JList
3 cases cocher
ButtonGroup
buttonGroup1
une liste dans un conteneur jScrollPane1 composant non visible - sert regrouper les 3 boutons radio afin que lorsque l'un d'eux s'allume, les autres s'teignent.
- 164 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Un groupe de boutons radio peut se construire de la faon suivante : on place chacun des boutons radio sans se soucier de les regrouper on place dans le conteneur, un composant swing ButtonGroup. Ce composant est non visuel. Il n'apparat donc pas dans le concepteur de la fentre. Il apparat cependant dans sa structure :
On voit ci-dessus dans la branche Autre les attributs non visuels de la fentre. Une fois un groupe de boutons radio cr, on peut lui associer chacun des boutons radio. Pour ce faire, on slectionne les proprits du bouton radio :
et dans la proprit buttonGroup du bouton radio, on met le nom du groupe dans lequel on veut mettre le bouton radio, ici buttonGroup1. On rpte cette opration pour les 3 boutons radio. La principale mthode des boutons radio et cases cocher est la mthode isSelected() qui indique si la case ou le bouton est coch. Le texte associ au composant peut tre connu avec getText() et fix avec setText(String unTexte). La case/bouton radio peut tre coch avec la mthode setSelected(boolean value). Lors d'un clic sur un bouton radio ou case cocher, c'est l'vnement actionPerformed qui est dclench. Dans le code qui suit, nous utilisons cet vnement pour suivre les changements de valeurs des boutons radio et cases cocher :
public class interfaceAppli extends JFrame { JPanel contentPane; JRadioButton jRadioButton1 = new JRadioButton(); JRadioButton jRadioButton2 = new JRadioButton(); JRadioButton jRadioButton3 = new JRadioButton(); JCheckBox jCheckBox1 = new JCheckBox(); JCheckBox jCheckBox2 = new JCheckBox(); JCheckBox jCheckBox3 = new JCheckBox(); ButtonGroup buttonGroup1 = new ButtonGroup(); JScrollPane jScrollPane1 = new JScrollPane(); DefaultListModel valeurs=new DefaultListModel(); JList jList1 = new JList(valeurs); /**Construire le cadre*/ public interfaceAppli() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { - 165 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Initialiser le composant*/ private void jbInit() throws Exception { jRadioButton1.setSelected(true); jRadioButton1.setText("un"); jRadioButton1.setBounds(new Rectangle(57, 31, 49, 23)); jRadioButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { afficheRadioButtons(e); } }); jRadioButton2.setBounds(new Rectangle(113, 30, 49, 23)); jRadioButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { afficheRadioButtons(e); } }); jRadioButton2.setText("deux"); jRadioButton3.setBounds(new Rectangle(168, 30, 49, 23)); jRadioButton3.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { afficheRadioButtons(e); } }); jRadioButton3.setText("trois"); // les boutons radio sont regroups buttonGroup1.add(jRadioButton1); buttonGroup1.add(jRadioButton2); buttonGroup1.add(jRadioButton3); // cases cocher jCheckBox1.setText("A"); jCheckBox1.setBounds(new Rectangle(58, 69, 32, 17)); jCheckBox1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { afficheCases(e); } }); jCheckBox2.setBounds(new Rectangle(112, 69, 40, 17)); jCheckBox2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { afficheCases(e); } }); jCheckBox2.setText("B"); jCheckBox3.setText("C"); jCheckBox3.setBounds(new Rectangle(170, 69, 37, 17)); jCheckBox3.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { afficheCases(e); } }); .... } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ... } private void afficheRadioButtons(ActionEvent e){ // affiche les valeurs des 3 boutons radio valeurs.addElement("boutons radio=("+jRadioButton1.isSelected()+","+ jRadioButton2.isSelected()+","+jRadioButton3.isSelected()+")");
- 166 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}//afficheRadioButtons void afficheCases(ActionEvent e) { // affiche les valeurs des cases cocher valeurs.addElement("cases cocher=["+jCheckBox1.isSelected()+","+ jCheckBox2.isSelected()+","+jCheckBox3.isSelected()+")"); }//afficheCases }//classe
n 1 2 3
JTextField
txtvaleurVS
rle un variateur horizontal un variateur vertical affiche la valeur du variateur horizontal 1 - permet aussi de fixer cette valeur affiche la valeur du variateur vertical 2 permet aussi de fixer cette valeur
Un variateur JScrollBar permet l'utilisateur de choisir une valeur dans une plage de valeurs entires symbolise par la "bande" du variateur sur laquelle se dplace un curseur. Pour un variateur horizontal, l'extrmit gauche reprsente la valeur minimale de la plage, l'extrmit droite la valeur maximale, le curseur la valeur actuelle choisie. Pour un variateur vertical, le minimum est reprsent par l'extrmit haute, le maximum par l'extrmit basse. Le couple (min,max) vaut par dfaut (0,100). Un clic sur les extrmits du variateur fait varier la valeur d'un incrment (positif ou ngatif) selon l'extrmit clique appele unitIncrement qui est par dfaut 1.
- 167 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Un clic de part et d'autre du curseur fait varier la valeur d'un incrment (positif ou ngatif) selon l'extrmit clique appele blockIncrement qui est par dfaut 10. Ces cinq valeurs (min, max, valeur, unitIncrement, blockIncrement) peuvent tre connues avec les mthodes getMinimum(), getMaximum(), getValue(), getUnitIncrement(), getBlockIncrement() qui toutes rendent un entier et peuvent tre fixes par les mthodes setMinimum(int min), setMaximum(int max), setValue(int val), setUnitIncrement(int uInc), setBlockIncrement(int bInc)
Il y a quelques points connatre dans l'utilisation des composants JScrollBar. Tout d'abord, on le trouve dans la barre des composants swing :
Lorsqu'on le dpose sur le conteneur, il est par dfaut vertical. On le rend horizontal avec la proprit orientation ci-dessous: Sur la feuille de proprits ci-dessus on voit qu'on a accs aux proprits minimum, maximum, value, unitIncrement, blockIncrement du JScrollbar. On peut donc les fixer la conception. Lorsqu'on place un scrollbar sur le conteneur sa "bande de variation" n'apparat pas : On peut rgler ce problme en donnant une bordure au composant. Cela se fait avec sa proprit border qui peut avoir diffrentes valeurs :
Lorsqu'on clique sur l'extrmit suprieure d'un variateur vertical, sa valeur diminue. Cela peut surprendre l'utilisateur moyen qui s'attend normalement voir la valeur "monter". On rgle ce problme en donnant une valeur ngative unitIncrement et blockIncrement.
- 168 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Comment suivre les volutions d'un variateur ? Lorsque la valeur de celui-ci change, l'vnement adjustmentValueChanged se produit. Il suffit d'associer une procdure cet vnement pour tre inform de chaque variation de la valeur du scrollbar.
- 169 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
txtValeurVS_actionPerformed(e); } }); ...... } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ... } void jScrollBar1_adjustmentValueChanged(AdjustmentEvent e) { // la valeur du scrollbar 1 a chang txtValeurHS.setText(""+jScrollBar1.getValue()); } void jScrollBar2_adjustmentValueChanged(AdjustmentEvent e) { // la valeur du scrollbar 2 a chang txtValeurVS.setText(""+jScrollBar2.getValue()); } void txtValeurHS_actionPerformed(ActionEvent e) { // on fixe la valeur du scrollbar horizontal setValeur(jScrollBar1,txtValeurHS); } void txtValeurVS_actionPerformed(ActionEvent e) { // on fixe la valeur du scrollbar vertical setValeur(jScrollBar2,txtValeurVS); } private void setValeur(JScrollBar jS, JTextField jT){ // fixe la valeur du scrollbar jS avec le texte du champ jT int valeur=0; try{ valeur=Integer.parseInt(jT.getText()); jS.setValue(valeur); } catch (Exception e){ // on affiche l'erreur afficher(""+e); }//try-catch }//setValeur void afficher(String message){ // affiche un message dans une bote JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE); }//afficher }
Les mthodes usuelles sont String getText() pour connatre le contenu de la zone de texte, setText(String unTexte) pour mettre unTexte dans la zone de texte, append(String unTexte) pour ajouter unTexte au texte dj prsent dans la zone de texte. Considrons l'application suivante :
n 1 2
3 4
JButton JTextField
cmdEffacer txtAjout
JScrollPane
jScrollPane1
rle une zone de texte multilignes affiche le contenu de 1 dans une bote de dialogue efface le contenu de 1 texte ajout au texte de 1 lorsqu'il est valid par la touche Entre. conteneur dfilant dans lequel on a plac la zone de texte 1 afin d'avoir une zone de texte dfilante.
- 171 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
/**Initialiser le composant*/ private void jbInit() throws Exception { cmdAfficher.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdAfficher_actionPerformed(e); } }); txtAjout.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { txtAjout_actionPerformed(e); } }); cmdEffacer.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdEffacer_actionPerformed(e); } }); ....... jScrollPane1.getViewport().add(txtTexte, null); } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ........ } void cmdAfficher_actionPerformed(ActionEvent e) { // affiche le contenu du TextArea afficher(txtTexte.getText()); } void afficher(String message){ // affiche un message dans une bote JOptionPane.showMessageDialog(this,message,"Suivi",JOptionPane.INFORMATION_MESSAGE); }// afficher void cmdEffacer_actionPerformed(ActionEvent e) { txtTexte.setText(""); }//cmdEffacer_actionPerformed void txtAjout_actionPerformed(ActionEvent e) { // ajout de texte txtTexte.append(txtAjout.getText()); // raz ajout txtAjout.setText(""); }// }
- 172 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
clic de souris la souris se dplace, bouton gauche appuy la souris vient d'entrer dans la surface du conteneur la souris vient de quitter la surface du conteneur la souris bouge Pression sur le bouton gauche de la souris Relchement du bouton gauche de la souris
Voici un programme permettant de mieux apprhender quels moments se produisent les diffrents vnements souris :
n 1
type JTextField
nom txtPosition
JList
lstAffichage
JButton
cmdEffacer
rle pour afficher la position de la souris dans le conteneur (vt MouseMoved) pour afficher les vts souris autres que MouseMoved pour effacer le contenu de 2
Les vnements sont empils par le haut dans la liste. Aussi la copie d'cran ci-dessus indique qu'un clic provoque trois vnements, dans l'ordre : MousePressed lorsqu'on appuie sur le bouton MouseReleased lorsqu'on le lche
- 173 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
MouseClicked qui indique que la succession des deux vnements prcdents est considre comme un clic. Ce pourrait tre un double clic. Mais ci-dessus, l'information clickCount=1 indiqe que c'est un simple clic.
On voit l les trois vnements : MousePressed lorsqu'on appuie initialement sur le bouton MouseDragged lorsqu'on dplace la souris, bouton appuy MouseReleased lorsqu'on lche le bouton
Dans les deux exemples ci-dessus, on voit qu'un vnement souris ramne avec lui diverses informations dont les coordonnes (x,y) de la souris, par exemple (408,65) dans la premire ligne ci-dessus. Si on continue ainsi, on dcouvre que l'vnement MouseExited est dclench ds que la souris quitte le conteneur ou passe sur l'un des composants de celui-ci. Dans ce dernier cas, le conteneur reoit l'vnement MouseExited et le composant l'vnement MouseEntered. L'inverse se produira lorsque la souris quittera le composant pour revenir sur le conteneur. Que se passe-t-il lors d'un double clic ? On a exactement les mmes vnements que pour un clic simple. Seulement l'vnement rapporte avec lui l'information clickCount=2 (cf ci-dessus) indiquant qu'il y a eu en fait un double clic. Le code utile de cette application est le suivant :
public class Cadre1 extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); JTextField txtPosition = new JTextField(); JScrollPane jScrollPane1 = new JScrollPane(); DefaultListModel valeurs=new DefaultListModel(); JList lstAffichage = new JList(valeurs); JButton cmdEffacer = new JButton(); /**Construire le cadre*/ public Cadre1() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Initialiser le composant*/ private void jbInit() throws Exception { contentPane.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(MouseEvent e) { contentPane_mouseMoved(e); }
- 174 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public void mouseDragged(MouseEvent e) { contentPane_mouseDragged(e); } }); contentPane.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(MouseEvent e) { contentPane_mouseEntered(e); } public void mouseExited(MouseEvent e) { contentPane_mouseExited(e); } public void mousePressed(MouseEvent e) { contentPane_mousePressed(e); } public void mouseClicked(MouseEvent e) { contentPane_mouseClicked(e); } public void mouseReleased(MouseEvent e) { contentPane_mouseReleased(e); } }); cmdEffacer.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { cmdEffacer_actionPerformed(e); } }); jScrollPane1.getViewport().add(lstAffichage, null); ............... } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ......... } void contentPane_mouseMoved(MouseEvent e) { txtPosition.setText("("+e.getX()+","+e.getY()+")"); } void contentPane_mouseDragged(MouseEvent e) { afficher(e); } void contentPane_mouseEntered(MouseEvent e) { afficher(e); } void afficher(MouseEvent e){ // affiche l'vt e dans la liste lstAffichage valeurs.insertElementAt(e,0); } void contentPane_mouseExited(MouseEvent e) { afficher(e); } void contentPane_mousePressed(MouseEvent e) { afficher(e); } void contentPane_mouseClicked(MouseEvent e) { afficher(e); } void contentPane_mouseReleased(MouseEvent e) { afficher(e); } void cmdEffacer_actionPerformed(ActionEvent e) { // efface la liste valeurs.removeAllElements();
- 175 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} }
Crez un nouveau projet avec au dpart une fentre vide. Choisissez dans la liste des composants "Conteneurs Swing" le composant JMenuBar (cf 1 ci-dessous) et dposez-le sur la fentre en cours de conception.
Rien n'apparat dans la fentre de conception mais le composant JMenuBar apparat dans la panneau de structure de votre fentre :
Double-cliquez sur l'lment jMenuBar1 ci-dessus pour avoir accs au menu en mode conception :
Une barre d'outils est disponible pour construire l'ensemble des options du menu : 1 2 3 4 5 insrer un lment de menu insrer un sparateur insrer un menu imbriqu supprimer un lment de menu dsactiver un lment de menu
- 176 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
6 7
Pour crer votre premier lment de menu, tapez "Options A" dans la case A ci-dessus, puis dessous dans l'ordre : A1, A2, sparateur, A3, A4.
Puis ct :
Utilisez l'outil 3 pour indiquer que B3 est un sous-menu imbriqu. Au fur et mesure de la conception du menu, la structure logique de notre fentre volue :
Si nous excutons notre application maintenant, nous verrons une fentre vide sans menu. Il nous faut associer le menu cr notre fentre. Pour ce faire, dans la structure de la fentre, slectionnez l'objet this :
- 177 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'une de celles-ci est JMenuBar qui sert fixer le menu qui sera associ la fentre. Cliquez dans la cellule droite de JMenuBar. Tous les menus crs vous seront alors proposs. Ici, nous n'aurons que jMenuBar1. Slectionnez-le. Lancez l'excution de l'application (F9) :
Maintenant, on a un menu mais les options ne font, pour l'instant, rien. Les options de menu sont traites comme des composants : elles ont des proprits et des vnements. Dans la structure du menu, slectionnez l'option jMenuItem1 :
- 178 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Slectionnez la page des vnements et cliquez sur la cellule droite de l'vnement actionPerformed : c'est l'vnement qui se produit lorsqu'on clique sur un lment de menu. Une procdure de traitement vous est propose par dfaut. Double-cliquez dessus pour avoir accs son code :
void jMenuItem1_actionPerformed(ActionEvent e) { afficher("L'option A1 a t slectionne"); } void afficher(String message){ // affiche un message dans une bote JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE); }//afficher
- 179 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
BorderLayout borderLayout1 = new BorderLayout(); JMenuBar jMenuBar1 = new JMenuBar(); JMenu jMenu1 = new JMenu(); JMenuItem jMenuItem1 = new JMenuItem(); JMenuItem jMenuItem2 = new JMenuItem(); JMenuItem jMenuItem3 = new JMenuItem(); JMenuItem jMenuItem4 = new JMenuItem(); JMenu jMenu2 = new JMenu(); JMenuItem jMenuItem5 = new JMenuItem(); JMenuItem jMenuItem6 = new JMenuItem(); JMenu jMenu3 = new JMenu(); JMenuItem jMenuItem7 = new JMenuItem(); JMenuItem jMenuItem8 = new JMenuItem(); JMenuItem jMenuItem9 = new JMenuItem(); /**Construire le cadre*/ public Cadre1() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } /**Initialiser le composant*/ private void jbInit() throws Exception { // la fentre est associe un menu this.setJMenuBar(jMenuBar1); jMenu1.setText("Options A"); jMenuItem1.setText("A1"); jMenuItem1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { jMenuItem1_actionPerformed(e); } }); jMenuItem2.setText("A2"); jMenuItem3.setText("A3"); jMenuItem4.setText("A4"); jMenu2.setText("Options B"); jMenuItem5.setText("B1"); jMenuItem6.setText("B2"); jMenu3.setText("B3"); jMenuItem7.setText("B31"); jMenuItem8.setText("B32"); jMenuItem9.setText("B4"); jMenuBar1.add(jMenu1); jMenuBar1.add(jMenu2); jMenu1.add(jMenuItem1); jMenu1.add(jMenuItem2); jMenu1.addSeparator(); jMenu1.add(jMenuItem3); jMenu1.add(jMenuItem4); jMenu2.add(jMenuItem5); jMenu2.add(jMenuItem6); jMenu2.add(jMenu3); jMenu2.add(jMenuItem9); jMenu3.add(jMenuItem7); jMenu3.add(jMenuItem8); } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { .... } void jMenuItem1_actionPerformed(ActionEvent e) { afficher("L'option A1 a t slectionne"); } void afficher(String message){ // affiche un message dans une bote
- 180 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE); }//afficher }
Lorsqu'on ferme cette fentre, elle disparat mais le thread d'excution dans laquelle elle s'excutait lui n'est pas arrt. Ce phnomne ne se produit normalement pas. Les botes de dialogue sont utilises au sein d'une application qui un moment ou un autre utilise une instruction System.exit(n) pour arrter tous les threads. On s'en souviendra dans les exemples venir tous btis sur le mme modle. Sous Dos, l'application peut tre interrompue par Ctrl-C. Avec JBuilder, on utilisera l'option Excuter/Rinitialiser le programme (Ctrl-F2). Par ailleurs, le premier argument de showMessageDialog est ici null. En gnral ce n'est pas le cas. C'est plutt this o this dsigne la fentre principale de l'application.
La mthode setLookAndFeel de la classe UIManager (UI=User Interface) permet de fixer l'apparence des interfaces graphiques. La classe UIManager dispose d'une mthode permettant de connatre les "apparences" possibles pour les interfaces : static UIManager.LookAndFeelInfo[] getInstalledLookAndFeels()
La mthode rend un tableau d'lments de type LookAndFeelInfo. Cette classe a une mthode : String getClassName()
- 181 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
qui donne le nom de la classe "implmentant" une apparence donne. Essayons le programme suivant :
import javax.swing.*; public class LookAndFeels { // affiche les look and feels disponibles public static void main(String[] args) { // iste des look and feels installs UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels(); // affichage for(int i=0;i<lf.length;i++){ System.out.println(lf[i].getClassName()); }//for }//main }//classe
Il semble donc y avoir trois "apparences "diffrentes". Reprenons notre programme d'affichage de messages en essayant les diffrentes apparences possibles :
import javax.swing.*; public class LookAndFeel2 { // affiche les look and feels disponibles public static void main(String[] args) { // liste des look and feels installs UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels(); // affichage for(int i=0;i<lf.length;i++){ // gestionnaire d'apparence try{ UIManager.setLookAndFeel(lf[i].getClassName()); }catch(Exception ex){ System.err.println(ex.getMessage()); }//catch // message JOptionPane.showMessageDialog(null,"Un message",lf[i].getClassName(),JOptionPane.INFORMATION_MESSAGE); }//for }//main }//classe
- 182 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
parentComponent message title optionType JOptionPane.YES_NO_CANCEL_OPTION : boutons oui, non, annuler Le rsultat rendu par la mthode est : JOptionPane.YES_OPTION JOptionPane.NO_OPTION JOptionPane.CANCEL_OPTION JOptionPane.CLOSED_OPTION Voici un exemple :
import javax.swing.*;
l'utilisateur a cliqu sur oui l'utilisateur a cliqu sur non l'utilisateur a cliqu sur annuler l'utilisateur a ferm la bote
public class confirm1 { public static void main(String[] args) { // affiche des botes de confirmation int rponse; affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_OPTION)); affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_CANCEL_OPTION)); }//main private static void affiche(int rponse){ // indique quel type de rponse on a eu switch(rponse){ case JOptionPane.YES_OPTION : System.out.println("Oui"); break; case JOptionPane.NO_OPTION : System.out.println("Non"); break; case JOptionPane.CANCEL_OPTION : System.out.println("Annuler"); break; case JOptionPane.CLOSED_OPTION : System.out.println("Fermeture"); break; }//switch }//affiche }//classe
- 183 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les arguments sont ceux dj rencontrs plusieurs fois. La mthode rend la chane de caractres tape par l'utilisateur. Voici un exemple :
import javax.swing.*; public class input1 { public static void main(String[] args) { // saisie System.out.println("Chane saisie ["+ JOptionPane.showInputDialog(null,"Quel est votre nom","Saisie du nom",JOptionPane.QUESTION_MESSAGE ) + "]"); }//main }//classe
L'affichage console :
Chane saisie [dupont]
Les contrles sont les suivants : N 0 type JScrollPane nom jScrollPane1 rle Conteneur dfilant pour la bote de texte 1 texte tap par l'utilisateur ou charg partir d'un fichier permet de sauvegarder le texte de 1 dans un fichier texte permet de charger le contenu d'un fichier texte dans 1 efface le contenu de 1
txtTexte
btnSauvegarder
JButton
btnCharger
JButton
btnEffacer
Un contrle non visuel est utilis : jFileChooser1. Celui-ci est pris dans la palette des conteneurs swing de JBuilder :
Nous dposons le composant dans la fentre de conception mais en-dehors du formulaire. Il apparat dans la liste des composants :
- 185 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous donnons maintenant le code utile du programme pour en avoir une vue d'ensemble :
import import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.filechooser.FileFilter; java.io.*;
public class dialogues extends JFrame { // les composants du cadre JPanel contentPane; JButton btnSauvegarder = new JButton(); JButton btnCharger = new JButton(); JButton btnEffacer = new JButton(); JScrollPane jScrollPane1 = new JScrollPane(); JTextArea txtTexte = new JTextArea(); JFileChooser jFileChooser1 = new JFileChooser(); // les filtres de fichiers javax.swing.filechooser.FileFilter filtreTxt = null; //Construire le cadre public dialogues() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); // autres initialisations moreInit(); } catch(Exception e) { e.printStackTrace(); } } // moreInit private void moreInit(){ // initialisations la construction de la fentre // filtre *.txt filtreTxt = new javax.swing.filechooser.FileFilter(){ public boolean accept(File f){ // accepte-t-on f ? return f.getName().toLowerCase().endsWith(".txt"); }//accept public String getDescription(){ // description du filtre return "Fichiers Texte (*.txt)"; }//getDescription }; // on ajoute le filtre jFileChooser1.addChoosableFileFilter(filtreTxt); // on veut aussi le filtre de tous les fichiers jFileChooser1.setAcceptAllFileFilterUsed(true); // on fixe le rpertoire de dpart de la bote FileChooser au rpertoire courant jFileChooser1.setCurrentDirectory(new File(".")); } //Initialiser le composant private void jbInit() throws Exception { .......................
- 186 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} //Remplac, ainsi nous pouvons sortir quand la fentre est ferme protected void processWindowEvent(WindowEvent e) { ...................... } } void btnCharger_actionPerformed(ActionEvent e) { // choix d'un fichier l'aide d'un objet JFileChooser // on fixe le filtre initial jFileChooser1.setFileFilter(filtreTxt); // on affiche la bote de slection int returnVal = jFileChooser1.showOpenDialog(this); // l'utilisateur a-t-il choisi qq chose ? if(returnVal == JFileChooser.APPROVE_OPTION) { // on met le fichier dans le champ texte lireFichier(jFileChooser1.getSelectedFile()); }//if }//btnCharger_actionPerformed // lireFichier private void lireFichier(File fichier){ // affiche le contenu du fichier texte fichier dans le champ texte // on efface le champ texte txtTexte.setText(""); // qqs donnes BufferedReader IN=null; String ligne=null; try{ // ouverture fichier en lecture IN=new BufferedReader(new FileReader(fichier)); // on lit le fichier ligne par ligne while((ligne=IN.readLine())!=null){ txtTexte.append(ligne+"\n"); }//while // fermeture fichier IN.close(); }catch(Exception ex){ // une erreur s'est produite txtTexte.setText(""+ex); }//catch } // effacer void btnEffacer_actionPerformed(ActionEvent e) { // on efface la bote de texte txtTexte.setText(""); } // sauvegarder void btnSauvegarder_actionPerformed(ActionEvent e) { // sauvegarde le contenu de la bote de texte dans un fichier // on fixe le filtre initial jFileChooser1.setFileFilter(filtreTxt); // on affiche la bote de slection de sauvegarde int returnVal = jFileChooser1.showSaveDialog(this); // l'utilisateur a-t-il choisi qq chose ? if(returnVal == JFileChooser.APPROVE_OPTION) { // on crit le contenu de la bote de texte dans fichier crireFichier(jFileChooser1.getSelectedFile()); }//if } // lireFichier private void crireFichier(File fichier){ // crit le contenu de la bote de texte dans fichier // qqs donnes PrintWriter PRN=null; try{ // ouverture fichier en criture PRN=new PrintWriter(new FileWriter(fichier)); // on crit le contenu de la bote de texte PRN.print(txtTexte.getText());
- 187 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// fermeture fichier PRN.close(); }catch(Exception ex){ // une erreur s'est produite txtTexte.setText(""+ex); }//catch }
Nous ne commenterons pas le code des mthodes btnEffacer_Click, lireFichier et crireFichier qui n'amnent rien qui n'a dj t vu. Nous nous attarderons sur la classe JFileChooser et son utilisation. Cette classe est complexe, du genre "usine gaz". Nous n'utilisons ici que les mthodes suivantes : addChoosableFilter(FileFilter) setAcceptAllFileFilterUsed(boolean) File getSelectedFile() int showSaveDialog() fixe les types de fichiers proposs la slection indique si le type 'Tous les fichiers" doit tre propos la slection ou non le fichier (File) choisi par l'utilisateur mthode qui affiche la bote de slection de sauvegarde. Rend un rsultat de type int. La valeur jFileChooser.APPROVE_OPTION indique que l'utilisateur a fait un choix valide. Sinon, il a soit annul le choix, soit une erreur s'est produite. pour fixer le rpertoire initial partir duquel l'utilisateur va commencer explorer le systme de fichiers pour fixer le filtre actif
setCurrentDirectory
setFileFilter(FileFilter)
liste droulante construite avec la mthode addChoosableFilter. Elle contient ce qu'on appelle des filtres de slection reprsents par la classe FileFilter. C'est au dveloppeur de dfinir ces filtres et de les ajouter la liste 1.
- 188 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
2 3 4
dossier courant, fix par la mthode setCurrentDirectory si cette mthode a t utilise, sinon le rpertoire courant sera le dossier "Mes Documents" sous windows ou le home Directory sous Unix. nom du fichier choisi ou tap directement par l'utilisateur. Sera disponible avec la mthode getSelectedFile() boutons Enregistrer/Annuler. Si le bouton Enregistrer est utilis, la mthode showSaveDialog rend le rsultat jFileChooser.APPROVE_OPTION
Comment les filtres de fichiers de la liste droulante 1 sont-ils construits ? Les filtres sont ajouts la liste 1 l'aide de la mthode : addChoosableFilter(FileFilter) fixe les types de fichiers proposs la slection
de la classe JFileChooser. Il nous reste connatre la classe FileFilter. C'est en fait la classe javax.swing.filechooser.FileFilter qui est une classe abstraite, c.a.d. une classe qui ne peut tre instantie mais seulement drive. Elle est dfinie comme suit : FileFilter() boolean accept(File) String getDescription() constructeur indique si le fichier f appartient au filtre ou non chane de description du filtre
Prenons un exemple. Nous voulons que la liste droulante 1 offre un filtre pour slectionner les fichiers *.txt avec la description "Fichiers texte (*.txt)". il nous faut crer une classe drive de la classe FileFilter utiliser la mthode boolean accept(File f) pour rendre la valeur true si le nom du fichier f se termine par .txt utiliser la mthode String getDescription() pour rendre la description "Fichiers texte (*.txt)"
Ce filtre serait ajout la liste des filtres de l'objet jFileChooser1 par l'instruction :
// on ajoute le filtre *.txt jFileChooser1.addChoosableFileFilter(filtretxt);
Tout ceci et quelques autres initialisations sont faites dans la mthode moreInit excute la construction de la fentre (cf programme complet ci-dessus). Le code du bouton Sauvegarder est le suivant :
void btnSauvegarder_actionPerformed(ActionEvent e) { // sauvegarde le contenu de la bote de texte dans un fichier // on fixe le filtre initial jFileChooser1.setFileFilter(filtreTxt); // on affiche la bote de slection de sauvegarde int returnVal = jFileChooser1.showSaveDialog(this); // l'utilisateur a-t-il choisi qq chose ? if(returnVal == JFileChooser.APPROVE_OPTION) { // on crit le contenu de la bote de texte dans fichier crireFichier(jFileChooser1.getSelectedFile()); - 189 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}//if }
La squence des oprations est la suivante : on fixe le filtre actif au filtre *.txt afin de permettre l'utilisateur de chercher de prfrence ce type de fichiers. Le filtre "Tous les fichiers" est galement prsent. Il a t ajout dans la procdure moreInit. On a donc deux filtres. la bote de slection de sauvegarde est affiche. Ici on perd la main, l'utilisateur utilisant la bote de slection pour dsigner un fichier du systme de fichiers. lorsqu'il quitte la bote de slection, on teste la valeur de retour pour voir si on doit ou non sauvegarder la bote de texte. Si oui, elle doit l'tre dans le fichier obtenu par la mthode getSelectedFile.
Il y a deux diffrences : pour afficher la bote de slection de fichiers, on utilise la mthode showOpenDialog au lieu de la mthode showSaveDialog. La bote de slection affiche est analogue celle affiche par la mthode showSaveDialog. si l'utilisateur a bien slectionn un fichier, on appelle la mthode lireFichier plutt que la mthode crireFichier.
- 190 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
N 6 JButton
type
nom btnCouleur
JButton
btnPolice
rle pour fixer la couleur des caractres du TextBox pour fixer la police de caractres du TextBox
Le composant JColorChooser permettant d'afficher une bote de slection de couleur peut tre trouve dans la liste des composants swing de JBuilder :
Nous dposons ce composant dans la fentre de conception, mais en-dehors du formulaire. Il est non visible dans le formulaire mais nanmoins prsent dans la liste des composants de la fentre :
La classe JColorChooser est trs simple. On affiche la bote de slection des couleurs avec la mthode int showDialog : static Color showDialog(Component component, String title, Color initialColor) le composant parent de la bote de slection, gnralement une fentre JFrame le titre dans la barre de titre de la bote de slection couleur initialement slectionne dans la bote de slection
Si l'utilisateur choisit une couleur, la mthode rend une couleur sinon la valeur null. Le code li au bouton Couleur est le suivant :
void btnCouleur_actionPerformed(ActionEvent e) { // choix d'une couleur de texte l'aide du composant JColorChooser Color couleur; if((couleur=jColorChooser1.showDialog(this,"Choix d'une couleur",Color.BLACK))!=null){ // on fixe la couleur des caractres de la bote de texte txtTexte.setForeground(couleur); }//if
- 191 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La classe Color est dfinie dans java.awt.Color. Diverses constantes y sont dfinies dont Color.BLACK pour la couleur noire. La bote de slection affiche est la suivante
Assez curieusement, la bibliothque swing n'offre pas de classe pour slectionner une police de caractres. Heureusement, il y a les ressources Java d'internet. En effectuant une recherche sur le mot cl "JFontChooser" qui semble un nom possible pour une telle classe on en trouve plusieurs. L'exemple qui va suivre va nous donner l'occasion de configurer JBuilder pour qu'il utilise des paquetages non prvus dans sa configuration initiale. Le paquetage rcupr s'appelle swingextras.jar et a t plac dans le dossier <jdk>\jre\lib\perso o <jdk> dsigne le rpertoire d'installation du jdk utilis par JBuilder. Il aurait pu tre plac n'importe o ailleurs.
- 192 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On y trouve le code source java des composants proposs dans le paquetage. On y trouve galement les classes elles-mmes :
- 193 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
De cette archive, on retiendra que la classe JFontChooser s'appelle en ralit com.lamatek.swingextras.JFontChooser. Si on ne souhaite pas crire le nom complet, il nous faudra crire en dbut de programme :
import com.lamatek.swingextras.*;
Comment feront le compilateur et la machine virtuelle Java pour trouver ce nouveau paquetage ? Dans le cas d'une utilisation directe du JDK cela a dj t expliqu et le lecteur pourra retrouver les explications dans le paragraphe sur les paquetages Java. Nous dtaillons ici la mthode utiliser avec JBuilder. Les paquetages sont configurs dans le menu Options/Configurer les JDK :
Le bouton Modifier (1) permet d'indiquer JBuilder quel JDK utilis. Dans cet exemple, JBuilder avait amen avec lui le JDK 1.3.1. Lorsque le JDK 1.4 est sorti, il a t install sparment de JBuilder et on a utilis le bouton Modifier pour indiquer JBuilder d'utiliser dsormais le JDK 1.4 en dsignant le rpertoire d'installation de ce dernier
- 194 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
2 3 4
rpertoire de base du JDK actuellement utilis par JBuilder liste des archives java (.jar) utilises par JBuilder. On peut en ajouter d'autres avec le bouton Ajouter (4) Le bouton Ajouter (4) permet d'ajouter de nouveaux paquetages que JBuilder utilisera la fois pour la compilation et l'excution des programmes. On l'a utilis ici pour ajouter le paquetage SwingExtras.jar (5)
Maintenant JBuilder est correctement configur pour pouvoir utiliser la classe JFontChooser. Cependant, il nous faudrait avoir accs la dfinition de cette classe pour l'utiliser correctement. L'archive swingextras.jar contient des fichiers html qu'on pourrait extraire pour les exploiter. C'est inutile. La documentation java incluse dans les fichiers .jar est directement accessible de JBuilder. Il faut pour cela configurer l'onglet Documentation (6) ci-dessus. On obtient la nouvelle fentre suivante :
Le bouton Ajouter nous permet d'indiquer que le fichier SwingExtras.jar doit tre explor pour la documentation. Cette dmarche valide, on peut constater qu'on a effectivement accs la documentation de SwingExtras.jar. Cela se traduit par diverses facilits : si on commence crire l'instruction d'importation
import com.lamatek.swingextras.*;
on fait F1 sur le mot cl JFontChooser, on obtient une aide sur cette classe :
- 195 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On voit dans la barre d'tat 1 que c'est bien un fichier html du paquetage swingextras.jar qui est utilis. L'exemple prsent ci-dessus est suffisament explicite pour qu'on puisse crire le code du bouton Police de notre application :
void btnPolice_actionPerformed(ActionEvent e) { // choix d'une police de texte l'aide du composant JFontChooser jFontChooser1 = new JFontChooser(new Font("Arial", Font.BOLD, 12)); if (jFontChooser1.showDialog(this, "Choix d'une police") == JFontChooser.ACCEPT_OPTION) { // on change la police des caractres de la bote de texte txtTexte.setFont(jFontChooser1.getSelectedFont()); }//if }
- 196 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les contrles sont les suivants n 1 2 3 type JRadioButton JRadioButton JSpinner nom rdOui rdNon spinEnfants rle coch si mari coch si pas mari nombre d'enfants du contribuable Minimum=0, Maximum=20, Increment=1 salaire annuel du contribuable en F montant de l'impt payer champ de messages d'tat - pas modifiable
4 5 6
Le menu est le suivant : option principale Impots option secondaire Initialiser nom mnuInitialiser rle charge les donnes ncessaires au calcul partir d'un fichier texte calcule l'impt payer lorsque toutes les donnes ncessaires sont prsentes et correctes remet le formulaire dans son tat initial termine l'application
Calculer
mnuCalculer
mnuEffacer mnuQuitter
le menu Calculer reste teint tant qu'il n'y a rien dans le champ du salaire
- 197 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
si lorsque le calcul est lanc, il s'avre que le salaire est incorrect, l'erreur est signale :
Le programme est donn ci-dessous. Il utilise la classe impots cre dans le chapitre sur les classes. Une partie du code produit automatiquement pas JBuilder n'a pas t ici reproduit.
import import import import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.filechooser.FileFilter; java.io.*; java.util.*; javax.swing.event.*;
public class frmImpots extends JFrame { // les composants de la fentre JPanel contentPane; JMenuBar jMenuBar1 = new JMenuBar(); JMenu jMenu1 = new JMenu(); JMenuItem mnuInitialiser = new JMenuItem(); JMenuItem mnuCalculer = new JMenuItem(); JMenuItem mnuEffacer = new JMenuItem(); JMenuItem mnuQuitter = new JMenuItem(); JLabel jLabel1 = new JLabel(); JFileChooser jFileChooser1 = new JFileChooser(); JTextField txtStatus = new JTextField(); JRadioButton rdOui = new JRadioButton(); JRadioButton rdNon = new JRadioButton(); JLabel jLabel2 = new JLabel(); JLabel jLabel3 = new JLabel(); JTextField txtSalaire = new JTextField(); JLabel jLabel4 = new JLabel(); JLabel jLabel5 = new JLabel(); JLabel lblImpots = new JLabel(); JLabel jLabel7 = new JLabel(); ButtonGroup buttonGroup1 = new ButtonGroup(); JSpinner spinEnfants=null; FileFilter filtreTxt=null; // les attributs de la classe double[] limites=null; double[] coeffr=null; double[] coeffn=null; impots objImpots=null; //Construire le cadre public frmImpots() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit();
- 198 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} catch(Exception e) { e.printStackTrace(); } // autres initialisations moreInit(); } // initialisation formulaire private void moreInit(){ // menu Calculer inhib mnuCalculer.setEnabled(false); // zones de saisie inhibes txtSalaire.setEditable(false); txtSalaire.setBackground(Color.WHITE); // champ d'tat txtStatus.setBackground(Color.WHITE); // spinner Enfants - entre 0 et 20 enfants spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1)); spinEnfants.setBounds(new Rectangle(137,60,40,27)); contentPane.add(spinEnfants); // filtre *.txt pour la bote de slection filtreTxt = new javax.swing.filechooser.FileFilter(){ public boolean accept(File f){ // accepte-t-on f ? return f.getName().toLowerCase().endsWith(".txt"); }//accept public String getDescription(){ // description du filtre return "Fichiers Texte (*.txt)"; }//getDescription }; // on ajoute le filtre *.txt jFileChooser1.addChoosableFileFilter(filtreTxt); // on veut aussi le filtre de tous les fichiers jFileChooser1.setAcceptAllFileFilterUsed(true); // on fixe le rpertoire de dpart de la bote FileChooser jFileChooser1.setCurrentDirectory(new File(".")); }//moreInit //Initialiser le composant private void jbInit() throws Exception { ................ } //Remplac, ainsi nous pouvons sortir quand la fentre est ferme protected void processWindowEvent(WindowEvent e) { ..................... } void mnuQuitter_actionPerformed(ActionEvent e) { // on quitte l'application System.exit(0); } void mnuInitialiser_actionPerformed(ActionEvent e) { // on charge le fichier des donnes // qu'on slectionne avec la bote de slection JFileChooser1 jFileChooser1.setFileFilter(filtreTxt); if (jFileChooser1.showOpenDialog(this)!=JFileChooser.APPROVE_OPTION) return; // on exploite le fichier slectionn try{ // lecture donnes lireFichier(jFileChooser1.getSelectedFile()); // cration de l'objet impots objImpots=new impots(limites,coeffr,coeffn); // confirmation txtStatus.setText("Donnes charges"); // le salaire peut tre modifi txtSalaire.setEditable(true); // plus de chgt possible mnuInitialiser.setEnabled(false);
- 199 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}catch(Exception ex){ // problme txtStatus.setText("Erreur : " + ex.getMessage()); // fin return; }//catch } private void lireFichier(File fichier) throws Exception { // les tableaux de donnes ArrayList aLimites=new ArrayList(); ArrayList aCoeffR=new ArrayList(); ArrayList aCoeffN=new ArrayList(); String[] champs=null; // ouverture fichier en lecture BufferedReader IN=new BufferedReader(new FileReader(fichier)); // on lit le fichier ligne par ligne // elles sont de la forme limite coeffr coeffn String ligne=null; int numLigne=0; // n de ligne courannte while((ligne=IN.readLine())!=null){ // une ligne de plus numLigne++; // on dcompose la ligne en champs champs=ligne.split("\\s+"); // 3 champs ? if(champs.length!=3) throw new Exception("ligne " + numLigne + "errone dans fichier des donnes"); // on rcupre les trois champs aLimites.add(champs[0]); aCoeffR.add(champs[1]); aCoeffN.add(champs[2]); }//while // fermeture fichier IN.close(); // transfert des donnes dans des tableaux borns int n=aLimites.size(); limites=new double[n]; coeffr=new double[n]; coeffn=new double[n]; for(int i=0;i<n;i++){ limites[i]=Double.parseDouble((String)aLimites.get(i)); coeffr[i]=Double.parseDouble((String)aCoeffR.get(i)); coeffn[i]=Double.parseDouble((String)aCoeffN.get(i)); }//for } void mnuCalculer_actionPerformed(ActionEvent e) { // calcul de l'impt // vrification salaire int salaire=0; try{ salaire=Integer.parseInt(txtSalaire.getText().trim()); if(salaire<0) throw new Exception(); }catch (Exception ex){ // msg d'erreur txtStatus.setText("Salaire incorrect. Recommencez"); // focus sur champ erron txtSalaire.requestFocus(); // retour l'interface return; } // nbre d'enfants Integer InbEnfants=(Integer)spinEnfants.getValue(); // calcul de l'impt lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),InbEnfants.intValue(),salaire)); // effacement msg d'tat txtStatus.setText(""); } void txtSalaire_caretUpdate(CaretEvent e) { // le salaire a chang - on met jour le menu calculer mnuCalculer.setEnabled(! txtSalaire.getText().trim().equals(""));
- 200 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} void mnuEffacer_actionPerformed(ActionEvent e) { // raz du formulaire rdNon.setSelected(true); spinEnfants.getModel().setValue(new Integer(0)); txtSalaire.setText(""); mnuCalculer.setEnabled(false); lblImpots.setText(""); } }
Nous avons utilis ici un composant disponible qu' partir du JDK 1.4, le JSpinner. C'est un incrmenteur, qui permet ici l'utilisateur de fixer le nombre d'enfants. Ce composant swing n'tait pas disponible dans la barre des composants swing de JBuilder 6 utilis pour le test. Cela n'empche pas son utilisation mme si les choses sont un peu plus compliques que pour les composants disponibles dans la barre des composants. En effet, on ne peut dposer le composant JSpinner sur le formulaire lors de la conception. Il faut le faire l'excution. Regardons le code qui le fait :
// spinner Enfants - entre 0 et 20 enfants spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1)); spinEnfants.setBounds(new Rectangle(137,60,40,27)); contentPane.add(spinEnfants);
La premire ligne cre le composant JSpinner. Ce composant peut servir diverses choses et pas seulement un incrmenteur d'entiers comme ici. L'argument du constructeur JSpinner est ici un modle d'incrmenteur de nombres acceptant quatre paramtres (valeur, min, max, incrment). Le composant a la forme suivante :
valeur initiale affiche dans le composant valeur minimale affichable dans le composant valeur maximale affichable dans le composant valeur d'incrment de la valeur affiche lorsqu'on utilise les flches haut/bas du composant
La valeur du composant est obtenue via sa mthode getValue qui rend un type Object. D'o quelques transtypages pour avoir l'entier dont on a besoin :
// nbre d'enfants Integer InbEnfants=(Integer)spinEnfants.getValue(); // calcul de l'impt lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(), InbEnfants.intValue(),salaire));
Avant toute chose, l'utilisateur doit utiliser l'option de menu Initialiser qui construit un objet impots avec le constructeur
public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception
de la classe impots. On rappelle que celle-ci a t dfinie en exemple dans le chapitre des classes. On s'y reportera si besoin est. Les trois tableaux ncessaires au constructeur sont remplis partir du contenu d'un fichier texte ayant la forme suivante :
- 201 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
12620.0 13190 15640 24740 31810 39970 48360 55790 92970 127860 151250 172040 195000 0
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.50 0.55 0.60 0.65
0 631 1290.5 2072.5 3309.5 4900 6898.5 9316.5 12106 16754.5 23147.5 30710 39312 49062
Chaque ligne comprend trois nombres spars par au moins un espace. Ce fichier texte est slectionn par l'utilisateur l'aide d'un composant JFileChooser. Une fois l'objet de type impots construit, il ne reste plus qu' laisser l'utilisateur donner les trois informations dont on a besoin : mari ou non, nombre d'enfants, salaire annuel, et appeler la mthode calculer de la classe impots. L'opration peut tre rpte plusieurs fois. L'objet de type impots n'est lui construit qu'une fois, lors de l'utilisation de l'option Initialiser.
Ce sont des restrictions fortes. Elles impliquent par exemple qu'une application ayant besoin de lire des informations dans un fichier ou une base de donnes devra les demander par une application relais situe sur le serveur d'o elle a t tlcharge. La structure gnrale d'une application Web simple est la suivante :
- 202 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
le client demande un document HTML au serveur Web gnralement avec un navigateur. Ce document peut contenir une applet qui fonctionnera comme une application graphique autonome au sein du document HTML affich par le navigateur du client. cette applet pourra avoir accs des donnes mais seulement celles situes sur le serveur web. Elle n'aura pas accs ni aux ressources de la machine cliente qui l'excute ni celles d'autres machines du rseau autres que celle partir de laquelle elle a t tlcharge.
- 203 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La classe JApplet a amen quelques amliorations la classe Applet, notamment la capacit contenir des composants JMenuBar c.a.d. des menus, ce qui n'tait pas possible avec la classe Applet.
start
stop
Pour beaucoup d'applets, seule la mthode init est ncessaire. Les mthodes start et stop ne sont ncessaires que si l'application lance des tches (threads) qui tournent en parallle et en continu souvent l'insu de l'utilisateur. Lorsque celui-ci quitte le document, la partie visible de l'application disparat, mais ces tches de fond continuent travailler. C'est souvent inutile. On profite alors de l'appel du navigateur la mthode stop pour les arrter. Si l'utilisateur revient sur le document, on profite de l'appel du navigateur la mthode start pour les relancer. Prenons par exemple une applet qui a une horloge dans son interface graphique. Celle-ci est maintenue par une tche de fond (thread). Lorsque dans le navigateur l'utilisateur quitte la page de l'applet, il est inutile de maintenir l'horloge qui est devenue invisible : dans la mthode stop de l'applet, on arrtera le thread qui gre l'horloge. Dans la mthode start, on le relancera afin que lorsque l'utilisateur revient sur la page de l'applet, il retrouve une horloge l'heure.
- 204 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On notera les points suivants : 1 2 la classe application drive maintenant de la classe JApplet la mthode main est remplace par la mthode init.
A titre d'exemple, nous revenons sur une application tudie : la gestion de listes.
Les composants de cette fentre sont les suivants : n 1 2 type JTextField JList nom txtSaisie jList1 rle champ de saisie liste contenue dans un conteneur jScrollPane1 liste contenue dans un conteneur jScrollPane2 transfre les lments slectionns de liste 1 vers liste 2 fait l'inverse vide la liste 1 vide la liste 2
JList
jList2
JButton
cmd1To2
5 6 7
- 205 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
JButton cmd2To1 = new JButton(); DefaultListModel v1=new DefaultListModel(); DefaultListModel v2=new DefaultListModel(); JList jList1 = new JList(v1); JList jList2 = new JList(v2); JScrollPane jScrollPane1 = new JScrollPane(); JScrollPane jScrollPane2 = new JScrollPane(); JButton cmdRaz1 = new JButton(); JButton cmdRaz2 = new JButton(); JLabel jLabel4 = new JLabel(); /**Construire le cadre*/ public interfaceAppli() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } }//interfaceAppli /**Initialiser le composant*/ private void jbInit() throws Exception { ... txtSaisie.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { txtSaisie_actionPerformed(e); } }); ... // Jlist1 est plac dans le conteneur jScrollPane1 jScrollPane1.getViewport().add(jList1, null); // Jlist2 est plac dans le conteneur jScrollPane2 jScrollPane2.getViewport().add(jList2, null); ... } /**Remplac, ainsi nous pouvons sortir quand la fentre est ferme*/ protected void processWindowEvent(WindowEvent e) { ... } void txtSaisie_actionPerformed(ActionEvent e) { ............. }//classe void cmd1To2_actionPerformed(ActionEvent e) { .......... }//transfert void cmdRaz1_actionPerformed(ActionEvent e) { // vide liste 1 v1.removeAllElements(); }//cmd Raz1 void cmdRaz2_actionPerformed(ActionEvent e) { // vide liste 2 v2.removeAllElements(); }///cmd Raz2
Pour transformer la classe appli en applet, il faut procder comme suit : modifier la classe interfaceAppli prcdente pour qu'elle drive non plus de JFrame mais de JApplet :
public class interfaceAppli extends JApplet {
supprimer l'instruction qui fixe le titre de la fentre JFrame. Une applet JApplet n'a pas de barre de titre
// this.setTitle("JList");
- 206 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
changer le constructeur en mthode init et dans cette mthode supprimer la gestion des vnements fentre (WindowListener, ...). Une applet est un conteneur qui ne peut tre redimensionn ou ferm.
/**Construire le cadre*/ public init() { // enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } }//interfaceAppli
On donne titre d'exemple le code complet de l'applet sauf la partie gnre automatiquement par JBuilder
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class interfaceAppli extends JApplet { JPanel contentPane; JLabel jLabel1 = new JLabel(); JLabel jLabel2 = new JLabel(); JLabel jLabel3 = new JLabel(); JTextField txtSaisie = new JTextField(); JButton cmd1To2 = new JButton(); JButton cmd2To1 = new JButton(); DefaultListModel v1=new DefaultListModel(); DefaultListModel v2=new DefaultListModel(); JList jList1 = new JList(v1); JList jList2 = new JList(v2); JScrollPane jScrollPane1 = new JScrollPane(); JScrollPane jScrollPane2 = new JScrollPane(); JButton cmdRaz1 = new JButton(); JButton cmdRaz2 = new JButton(); JLabel jLabel4 = new JLabel(); /**Construire le cadre*/ public void init() { // enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } }//interfaceAppli /**Initialiser le composant*/ private void jbInit() throws Exception { //setIconImage(Toolkit.getDefaultToolkit().createImage(interfaceAppli.class.getResource("[Votre icne]"))); contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(null); this.setSize(new Dimension(400, 308)); // this.setTitle("JList"); jScrollPane1.setBounds(new Rectangle(37, 133, 124, 101));
- 207 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
jScrollPane2.setBounds(new Rectangle(232, 132, 124, 101)); ............. } void txtSaisie_actionPerformed(ActionEvent e) { // le texte de la saisie a t valid // on le rcupre dbarrass de ses espaces de dbut et fin String texte=txtSaisie.getText().trim(); // s'il est vide, on n'en veut pas if(texte.equals("")){ // msg d'erreur JOptionPane.showMessageDialog(this,"Vous devez taper un texte", "Erreur",JOptionPane.WARNING_MESSAGE); // fin return; }//if // s'il n'est pas vide, on l'ajoute aux valeurs de la liste 1 v1.addElement(texte); // et on vide le champ de saisie txtSaisie.setText(""); } void cmd1To2_actionPerformed(ActionEvent e) { // transfert des lments slectionns dans la liste 1 vers la liste 2 transfert(jList1,jList2); }//cmd1To2 private void transfert(JList L1, JList L2){ // transfert des lments slectionns dans la liste 1 vers la liste 2 // on rcupre le tableau des indices des lments slectionns dans L1 int[] indices=L1.getSelectedIndices(); // qq chose faire ? if (indices.length==0) return; // on rcupre les valeurs de L1 DefaultListModel v1=(DefaultListModel)L1.getModel(); // et celles de L2 DefaultListModel v2=(DefaultListModel)L2.getModel(); for(int i=indices.length-1;i>=0;i--){ // on ajoute L2 les valeurs slectionnes dans L1 v2.addElement(v1.elementAt(indices[i])); // les lments de L1 copis dans L2 doivent tre supprims de L1 v1.removeElementAt(indices[i]); }//for }//transfert private void affiche(String message){ // affiche message JOptionPane.showMessageDialog(this,message, "Suivi",JOptionPane.INFORMATION_MESSAGE); }// affiche void cmd2To1_actionPerformed(ActionEvent e) { // transfert des lments slectionns dans jList2 vers jList1 transfert(jList2,jList1); }//cmd2TO1 void cmdRaz1_actionPerformed(ActionEvent e) { // vide liste 1 v1.removeAllElements(); }//cmd Raz1 void cmdRaz2_actionPerformed(ActionEvent e) { // vide liste 2 v2.removeAllElements(); }//cmd Raz2 }//classe
On peut compiler le source de cette applet. On le fait ici avec le JDK, sans JBuilder.
E:\data\serge\Jbuilder\interfaces\JApplets\1>javac.bat interfaceAppli.java E:\data\serge\Jbuilder\interfaces\JApplets\1>dir 12/06/2002 16:40 6 148 interfaceAppli.java
- 208 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
527 interfaceAppli$1.class 525 interfaceAppli$2.class 525 interfaceAppli$3.class 525 interfaceAppli$4.class 525 interfaceAppli$5.class 4 759 interfaceAppli.class
L'application peut tre teste avec le programme AppletViewer du JDK qui permet d'excuter des applets ou un navigateur. Pour cela, il faut crer le document HTML appli.htm qui aura en son sein l'applet :
<html> <head> <title>listes swing</title> </head> <body> <applet code="interfaceAppli.class" width="400" height="300"> </applet> </body> </html>
On a l, un document HTML classique si ce n'est la prsence du tag applet. Celui-ci a t utilis avec trois paramtres : code="interfaceAppli.class" width="400" height="300" nom de la classe JAVA compile charger pour excuter l'app largeur du cadre de l'applet dans le document hauteur du cadre de l'applet dans le document
Lorsque le fichier appli.htm a t crit, on peut le charger avec le programme appletviewer du JDK ou avec un navigateur. On tape dans une fentre Dos la commande suivante dans le dossier du fichier appli.htm : appletviewer appli.htm On suppose ici que le rpertoire de l'excutable appletviewer.exe est dans le PATH de la fentre Dos, sinon il faudrait donner le chemin complet de l'excutable appletviewer.exe. On obtient la fentre suivante :
- 209 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On arrte l'excution de l'applet avec l'option Applet/Quitter. Testons maintenant l'applet avec un navigateur. Celuici doit utiliser une machine virtuelle Java 2 pour pouvoir afficher les composants swing. Jusqu' rcemment (2001), cette contrainte posait problme car Sun produisait des JDK que les diteurs de navigateurs ne suivaient qu'avec beaucoup de retard. Finalement Sun a mis un terme cet obstacle en mettant disposition des utilisateurs une application appele "Java plugin" qui permet aux navigateurs Internet Explorer et Netscape Navigator d'utiliser les tout derniers JRE produits par Sun (JRE=Java Runtime Environment). Les tests qui suivent ont t faits avec IE 5.5 muni du plugin Java 1.4. Une premire faon de tester l'applet interfaceAppli.class est de charger le fichier HTML appli.htm directement dans le navigateur en double-cliquant dessus. Le navigateur affiche alors la page HTML et son applet sans l'aide d'un serveur Web :
- 210 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On voit d'aprs l'URL (1) que le fichier a t charg dans le navigateur directement. Dans l'exemple suivant, le fichier appli.htm a t demand un serveur Web Apache travaillant sur le port 81 de la machine locale :
- 211 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La signification des paramtres est la suivante : Paramtre code width height codebase Signification obligatoire - nom du fichier .class excuter obligatoire - largeur de l'applet dans le document obligatoire - hauteur # facultatif - URL du rpertoire contenant l'applet excuter. Si codebase n'est pas prcis, l'applet sera cherch dans le rpertoire du document html qui la rfrence facultatif - positionnement (LEFT, RiGHT, CENTER) de l'applet dans le document facultatif - marge horizontale entourant l'applet exprime en pixels facultatif - marge verticale entourant l'applet exprime en pixels facultatif - texte crit en lieu et place de l'applet si le navigateur ne peut le charger facultatif - paramtre pass l'applet prcisant son nom (name) et sa valeur (value). L'applet pourra rcuprer la valeur du paramtre nom1 par val1=getParameter("nom1") On peut utiliser autant de paramtres que l'on veut facultatif - sera affich par tout navigateur incapable d'excuter une applet, par exemple parce qu'il ne possde pas de machine virtuelle Java.
texte
- 212 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le code Java de l'applet interfaceParams a t gnr comme indiqu prcdemment. On a construit une application JBuilder puis on a fait les quelques transformations mentionnes plus haut :
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class interfaceParams extends JApplet { JPanel contentPane; JScrollPane jScrollPane1 = new JScrollPane(); JLabel jLabel1 = new JLabel(); DefaultListModel params=new DefaultListModel(); JList lstParams = new JList(params); //Construire le cadre public void init() { // enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } // autres initialisations moreInit(); } // initialisations public void moreInit(){ // affiche les valeurs des paramtres de l'applet params.addElement("nom=param1 valeur="+getParameter("param1")); params.addElement("nom=param2 valeur="+getParameter("param2")); }//more Init //Initialiser le composant private void jbInit() throws Exception { ............ this.setSize(new Dimension(205, 156)); //this.setTitle("Paramtres d'une applet"); jScrollPane1.setBounds(new Rectangle(19, 53, 160, 73)); ............ } }
- 213 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 214 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
cre une instance d'URL partir d'une chane du type "protocol:port//machine/ fichier" - lance une exception si la syntaxe de la chane ne correspond pas une URL permet d'avoir le champ fichier de la chane "protocole:port//machine/fichier" de l'URL permet d'avoir le champ machine de la chane "protocole:port//machine/fichier" de l'URL permet d'avoir le champ port de la chane "protocole:port//machine/fichier" de l'URL permet d'avoir le champ protocole de la chane "protocole:port//machine/fichier" de l'URL ouvre la connexion avec la machine distante getHost() sur son port getPort() selon le protocole getProtocol() en vue de lire le fichier getFile(). Lance une exception si la connexion n'a pu tre ouverte raccourci pour openConnection().getInputStream(). Permet d'obtenir un flux d'entre partir duquel le contenu du fichier getFile() va pouvoir tre lu. Lance une exception si le flux n'a pu tre obtenu affiche l'identit de l'instance d'URL
public URL(String spec) pour spcifier le fichier exploiter public final InputStream openStream() pour l'exploiter
- 215 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
URL url=new URL(arg[0]); // lecture du contenu try{ // cration du flux d'entre BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream())); try{ // lecture des lignes de texte dans le flux d'entre String ligne; while((ligne=is.readLine())!=null) System.out.println(ligne); } catch (Exception e){ System.err.println("Erreur lecture : " +e); } finally{ try { is.close(); } catch (Exception e) {} } } catch (Exception e){ System.err.println("Erreur openStream : " +e); } } catch (Exception e){ System.err.println("Erreur cration URL : " +e); } }// fin main }// fin classe
Aprs avoir vrifi qu'il y avait bien un argument, on tente de crer une URL avec celui-ci :
// cration de l'URL URL url=new URL(arg[0]);
Cette cration peut chouer si l'argument ne respecte pas la syntaxe des URL protocole:port//machine/fichier. Si on a une URL syntaxiquement correcte, on essaie de crer un flux d'entre partir duquel on pourra lire des lignes de texte. Le flux d'entre fourni par une URL URL.openStream() fournit un flux de type InputStream qui est un flux orient caractres : la lecture se fait caractre par caractre et il faut former les lignes soi-mme. Pour pouvoir lire des lignes de texte, il faut utiliser la mthode readLine des classes BufferedReader ou DataInputStream.On a choisi ici BufferedReader. Il ne nous reste qu' transformer le flux InputStream de l'URL en flux BufferedReader. Cela se fait en crant un flux intermdiaire InputStreamReader :
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
Cette cration de flux peut chouer. On gre l'exception correspondante. Une fois le flux obtenu, il ne nous reste plus qu' y lire les lignes de texte et afficher celles-ci l'cran.
String ligne; while((ligne=is.readLine())!=null) System.out.println(ligne);
L encore la lecture peut engendrer une exception qui doit tre gre. Voici un exemple d'excution du programme qui demande une URL locale :
E:\data\serge\Jbuilder\interfaces\JApplets\3>java urlcontenu http://localhost <html> <head>
<title>Bienvenue dans le Serveur Web personnel</title> </head> <body bgcolor="#FFFFFF" link="#0080FF" vlink="#0080FF" topmargin="0" leftmargin="0"> <table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#000000"> ............
- 216 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Numro 1 2 3 4
Rle URL lire bouton lanant la lecture de l'URL panneau dfilant liste affichant le contenu de l'URL demande
- 217 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public class interfaceURL extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); JTextField txtURL = new JTextField(); JButton btnCharger = new JButton(); JScrollPane jScrollPane1 = new JScrollPane(); DefaultListModel lignes=new DefaultListModel(); JList lstURL = new JList(lignes); //Construire le cadre public interfaceURL() { .............. } //Initialiser le composant private void jbInit() throws Exception { .............. } //Remplac, ainsi nous pouvons sortir quand la fentre est ferme protected void processWindowEvent(WindowEvent e) { ................... } void txtURL_caretUpdate(CaretEvent e) { // positionne l'tat du bouton Charger btnCharger.setEnabled(! txtURL.getText().trim().equals("")); } void btnCharger_actionPerformed(ActionEvent e) { // affiche le contenu de l'URL dans la liste try{ afficherURL(txtURL.getText().trim()); }catch(Exception ex){ // affichage erreur JOptionPane.showMessageDialog(this,"Erreur : " + ex.getMessage(),"Erreur",JOptionPane.ERROR_MESSAGE); }//try-catch } private void afficherURL(String strURL) throws Exception { - 218 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// affiche le contenu de l'URL strURL dans la liste // aucune exception n'est gre spcifiquement. On se contente de les remonter // cration de l'URL URL url=new URL(strURL); // cration du flux d'entre BufferedReader IN=new BufferedReader(new InputStreamReader(url.openStream())); // lecture des lignes de texte dans le flux d'entre String ligne; while((ligne=IN.readLine())!=null) lignes.addElement(ligne); // fermeture flux de lecture IN.close(); } }
- 219 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Dans l'exemple ci-dessus, le navigateur a demand l'URL http://localhost:81/Japplets/2/appliURL.htm un serveur web apache fonctionnant sur le port 81. L'applet a t alors affiche dans le navigateur. Dans celle-ci, on a demand de nouveau l'URL http://localhost:81/Japplets/2/appliURL.htm pour vrifier qu'on obtenait bien le fichier appliURL.htm qu'on avait construit. Maintenant essayons de charger une URL n'appartenant pas la machine qui a dlivr l'applet (ici localhost) :
Le chargement de l'URL a t refus. On retrouve ici la contrainte lie aux applets : elles ne peuvent accder qu'aux seules ressources rseau de la machine partir de laquelle elles ont t tlcharges. Il y un moyen pour l'applet de contourner cette contrainte qui est de dlguer les demandes rseau un programme serveur situ sur la machine d'o elle a t tlcharge. Ce programme fera les demandes rseau la place de l'applet et lui renverra les rsultats. On appelle cela un programme relais.
Il est vident que les donnes dfinissant les barmes de l'impt seront sur le serveur web et non pas sur chacune des machines clientes. Le fichier lire sur le serveur web sera ici plac dans le mme dossier que l'applet et l'option Initialiser devra aller le chercher l. Les exemples prcdents ont montr comment faire cela. Par ailleurs, pour slectionner le fichier des donnes localement, on avait utilis un composant JFileChooser qui n'a plus lieu d'tre ici.
- 220 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On notera la paramtre data dont la valeur est le nom du fichier contenant les donnes du barme de l'impt. Le document HTML, la classe appletImpots, la classe impots et le fichier impots.txt sont tous dans le mme dossier du serveur Web :
E:\data\serge\web\JApplets\impots>dir 12/06/2002 13:24 247 impots.txt 13/06/2002 10:17 654 appletImpots$2.class 13/06/2002 10:17 653 appletImpots$3.class 13/06/2002 10:17 653 appletImpots$4.class 13/06/2002 10:17 651 appletImpots$5.class 13/06/2002 10:06 651 appletImpots$6.class 13/06/2002 10:17 8 655 appletImpots.class 13/06/2002 10:17 657 appletImpots$1.class 13/06/2002 10:24 286 appletImpots.htm 13/06/2002 10:17 1 305 impots.class
Le code de l'applet est le suivant (nous n'avons mis en relief que les changements par rapport l'application graphique) :
........... import java.net.*; import java.applet.Applet; public class appletImpots extends JApplet { // les composants de la fentre JPanel contentPane; ............................ // les attributs de la classe double[] limites=null; double[] coeffr=null; double[] coeffn=null; impots objImpots=null; String urlDATA=null; //Construire le cadre public void init() { //enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } // autres initialisations moreInit(); } // initialisation formulaire private void moreInit(){ // menu Calculer inhib mnuCalculer.setEnabled(false);
- 221 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
................ // on rcupre le nom du fichier du barme des impts String nomFichier=getParameter("data"); // erreur ? if(nomFichier==null){ // msg d'erreur txtStatus.setText("Le paramtre data de l'applet n'a pas t initialis"); // on bloque l'option Initialiser mnuInitialiser.setEnabled(false); // fin return; }//if // on fixe l'URL des donnes urlDATA=getCodeBase()+"/"+nomFichier; }//moreInit //Initialiser le composant private void jbInit() throws Exception { ................... } void mnuQuitter_actionPerformed(ActionEvent e) { // on quitte l'application System.exit(0); } void mnuInitialiser_actionPerformed(ActionEvent e) { // on charge le fichier des donnes try{ // lecture donnes lireDATA(); // cration de l'objet impots objImpots=new impots(limites,coeffr,coeffn); ................ } private void lireDATA() throws Exception { // les tableaux de donnes ArrayList aLimites=new ArrayList(); ArrayList aCoeffR=new ArrayList(); ArrayList aCoeffN=new ArrayList(); String[] champs=null; // ouverture fichier en lecture BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream())); // on lit le fichier ligne par ligne .................... } void mnuCalculer_actionPerformed(ActionEvent e) { // calcul de l'impt ...................... } void txtSalaire_caretUpdate(CaretEvent e) { .......... } void mnuEffacer_actionPerformed(ActionEvent e) { ............... } }
Nous ne commentons ici que les modifications amenes par le fait que le fichier des donnes lire est maintenant sur une machine distante plutt que sur une machine locale : Le nom de l'URL du fichier des donnes lire est obtenu par le code suivant :
// on rcupre le nom du fichier du barme des impts String nomFichier=getParameter("data");
- 222 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// erreur ? if(nomFichier==null){ // msg d'erreur txtStatus.setText("Le paramtre data de l'applet n'a pas t initialis"); // on bloque l'option Initialiser mnuInitialiser.setEnabled(false); // fin return; }//if // on fixe l'URL des donnes urlDATA=getCodeBase()+"/"+nomFichier;
Rappelons-nous que le nom du fichier "impots.txt" est pass dans le paramtre data de l'applet :
<param name="data" value="impots.txt">
Le code ci-dessus commence donc par rcuprer la valeur du paramtre data en grant une ventuelle erreur. Si l'URL du document HTML contenant l'applet est http://localhost:81/JApplets/impots/appletImpots.htm, l'URL du fichier impots.txt sera http://localhost:81/JApplets/impots/impots.txt. Il nous faut construire le nom de cette URL. La mthode getCodeBase() de l'applet donne l'URL du dossier o a t rcupr le document HTML contenant l'applet, donc dans notre exemple http://localhost:81/JApplets/impots. L'instruction suivante permet donc de construire l'URL du fichier des donnes :
urlDATA=getCodeBase()+"/"+nomFichier;
On trouve dans la mthode lireFichier() qui lit le contenu de l'URL urlData, la cration du flux d'entre qui va permettre de lire les donnes :
// ouverture fichier en lecture BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
A partir de l, on ne peut plus distinguer le fait que les donnes viennent d'un fichier distant plutt que local. Voici un exemple d'excution de l'applet :
- 223 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IV-H - Conclusion
Ce chapitre a prsent une introduction la construction d'interfaces graphiques avec Jbuilder les composants swing les plus courants la construction d'applets
Nous retiendrons que le code gnr par JBuilder peut tre crit la main. Une fois ce code obtenu d'une manire ou d'une autre, un simple JDK suffit pour l'excuter et JBuilder n'est alors plus indispensable. l'utilisation d'un outil tel que JBuilder peut amener des gains de productivit importants : o s'il est possible d'crire la main le code gnr par JBuilder, cela peut prendre beaucoup de temps et ne prsente que peu d'intrt, la logique de l'application tant en gnral ailleurs. o le code gnr peut tre instructif. Le lire et l'tudier est une bonne faon de dcouvrir certaines mthodes et proprits de composants qu'on utilise pour la premire fois. o JBuilder est multi plate-formes. On conserve donc ses acquis en passant d'une plate-forme l'autre. Pouvoir crire des programmes fonctionnant la fois sous windows et Linux est bien sr un facteur de productivit trs important. Mais il est d Java lui-mme et non JBuilder.
- 224 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous prsentons ci-dessous l'installation de JBuilder 4 Foundation sur une machine Linux. Son installation sur une machine Win9x ne pose aucun problme et est analogue au processus qui va maintenant tre dcrit. L'installation des version sultrieures est sans doute diffrente mais ce document peut nanmoins quelques informations utiles. Jbuilder est disponible sur le site d''Inprise l'url http://www.inprise.com/jbuilder
On trouve sur cette page les liens pour notamment Windows et Linux. Nous dcrivons maintenant l'installation de JBuilder sur une machine Linux ayant l'interface graphique KDE. En suivant le lien Jbuilder 4 for Linux, un formulaire est prsent. On le remplit et au final on rcupre deux fichiers : jb4docs_fr.tar.gz jb4fndlinux_fr.tar.gz la documentation et les exemples de Jbuilder4 Jbuilder4 Foundation. C'est une version limite du Jbuilder4 commercial mais suffisant dans un contexte ducatif.
Une cl d'activation du logiciel vous est envoye par courrier lectronique. Elle vous permettra d'utiliser Jbuilder4 et vous sera demande ds la 1re utilisation. Si vous perdez cette cl, vous pouvez revenir l'url ci-dessus et suivre le lien "get your activation key". Nous supposons par la suite que vous tes root et que vous tes plac dans le rpertoire des deux fichiers tar.gz ci-dessus. On dcompresse les deux fichiers : [tar xvzf jb4fndlinux_fr.tar.gz] [tar xvzf jb4docs_fr.tar.gz]
[ls -l] drwxr-xr-x 3 nobody nobody 4096 oct 10 2000 docs drwxr-xr-x 3 nobody nobody 4096 dc 5 13:00 foundation [ls -l foundation] -rw-r--r-- 1 nobody -rwxr-xr-x 1 nobody drwxr-xr-x 2 nobody -rw-r--r-- 1 nobody -rw-r--r-- 1 nobody -rw-r--r-- 1 nobody -rw-r--r-- 1 nobody
1128 dc 5 13:00 deploy.txt 69035365 dc 5 13:00 fnd_linux_install.bin 4096 dc 5 13:00 images 15114 dc 5 13:00 index.html 23779 dc 5 13:00 license.txt 75739 dc 5 13:00 release_notes.html 31902 dc 5 13:00 whatsnew.html
- 225 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
1128 oct 10 2000 deploy.txt 40497874 oct 10 2000 doc_install.bin 4096 oct 10 2000 images 9210 oct 10 2000 index.html 23779 oct 10 2000 license.txt 75739 oct 10 2000 release_notes.html 31902 oct 10 2000 whatsnew.html
Dans les deux rpertoires gnrs, le fichier .bin est le fichier d'installation. Par ailleurs, avec un navigateur affichez le fichier index.html de chacun des rpertoires. Ils donnent la marche suivre pour installer les deux produits. Commenons par installer Jbuilder Foundation : [cd foundation] [./fnd_linux_install.bin] Arrive le 1er cran de l'installation. Vont suivre de nombreux autres :
Faites [suivant].
- 226 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Acceptez l'emplacement propos pour Jbuilder (notez le, vous en aurez besoin ultrieurement) et faites [suivant]. L'installation se fait rapidement.
Nous sommes prts pour un premier test. Dans KDE, lancez le gestionnaire de fichiers pour aller dans le rpertoire des excutables de Jbuilder : /opt/jbuilder4/bin (si vous avez install jbuilder dans /opt/jbuilder4) :
- 227 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cliquez sur l'icne jbuilder ci-dessus. Comme c'est la 1re fois que vous utilisez Jbuilder, vous allez devoir entrer votre cl d'activation :
Remplissez les champs Nom et Socit. Faites [Ajouter] pour entrer votre cl d'activation. On rappelle que celle-ci a du vous tre envoye par mail et que si vous l'avez perdue, vous pouvez l'avoir l'url o vous avez rcupr Jbuilder 4 (cf dbut de l'installation). Une fois votre cl d'activation accepte, on vous rappellera les conditions de licence :
- 228 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Faites OK pour terminer cette phase qui ne s'excute que lors de la 1re excution. Apparat ensuite, l'environnement de dveloppement de Jbuilder :
Quittez Jbuilder pour installer maintenant la documentation. Celle-ci va installer un certain nombre de fichiers qui seront utiliss dans l'aide de Jbuilder, aide qui pour l'instant est incomplte. Revenez dans le rpertoire o vous
- 229 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
avez dcompress les fichiers tar.gz de Jbuilder. Le programme d'installation est dans le rpertoire docs. Placezvous dedans : [cd docs] [ls -l]
-rw-r--r--rwxr-xr-x drwxr-xr-x -rw-r--r--rw-r--r--rw-r--r--rw-r--r-1 1 2 1 1 1 1 nobody nobody nobody nobody nobody nobody nobody nobody nobody nobody nobody nobody nobody nobody 1128 oct 10 2000 deploy.txt 40497874 oct 10 2000 doc_install.bin 4096 oct 10 2000 images 9210 oct 10 2000 index.html 23779 oct 10 2000 license.txt 75739 oct 10 2000 release_notes.html 31902 oct 10 2000 whatsnew.html
Le fichier d'installation est doc_install.bin mais on ne peut le lancer immdiatement. Si on le fait, l'installation choue sans qu'on comprenne pourquoi. Lisez le fichier index.html avec un navigateur pour une description prcise du mode d'installation. L'installateur a besoin d'une machine virtuelle java, en fait un programme appel java et celuici doit tre dans le PATH de votre machine. On rappelle que PATH est une variable Unix dont la valeur de la forme rep1:rep2:...:repn indique les rpertoires repi qui doivent tre explors dans la recherche d'un excutable. Ici, l'installateur demande l'excution d'un programme java. Vous pouvez avoir plusieurs versions de ce programme selon le nombre de machines virtuelles Java que vous avez installes ici ou l. Assez logiquement, nous utiliserons celui amen par Jbuilder4 et qui se trouve dans /opt/jbuilder4/jdk1.3/bin. Pour mettre ce rpertoire dans la variable PATH :
[echo $PATH] /usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/ usr/bin:/usr/X11R6/bin:/root/bin [export PATH=/opt/jbuilder4/jdk1.3/bin/:$PATH] [echo $PATH] /opt/jbuilder4/jdk1.3/bin/:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local /bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
Nous pouvons maintenant lancer l'installation de la documentation : [./doc_install.bin] Preparing to install... C'est une installation graphique qui va se faire :
Elle est trs analogue celle de Jbuilder Foundation. Aussi ne la dtaillerons-nous pas. Il y a un cran qu'il ne faut pas rater :
- 230 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'installateur doit normalement trouver tout seul o vous avez install Jbuilder Foundation. Ne changez donc pas ce qui vous est propos sauf bien sr si c'tait faux. Une fois la documentation installe, nous sommes prts pour un nouveau test de Jbuilder. Lancez l'application comme il a t montr plus haut. Une fois Jbuilder prsent, prenez l'option Aide/Rubrique d'aide. Dans le cadre de gauche, cliquez sur le lien Tutoriels :
Jbuilder est livr avec un ensemble de tutoriels qui vous permettront de dmarrer en programmation Java. Ci-dessous on a suivi le tutoriel "Construction d'une application" ci-dessus.
- 231 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous allons crer une simple fentre avec le titre "Bonjour tout le monde". Nous appelons ce projet coucou. L'exemple a t excut par root. Jbuilder propose alors de rassembler tous les projets dans un rpertoire jbproject du rpertoire
- 232 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
de connexion de root. Le projet coucou sera plac dans le rpertoire coucou (Champ Nom du rpertoire du projet) de jbproject. Faites [suivant].
Ce second cran est un rsum des diffrents chemins de votre projet. Il n'y a rien modifier. Faites [suivant].
Le 3ime cran vous demande de personnaliser votre projet. Compltez et faites [Terminer]. Faites maintenant Fichier/Nouveau :
- 233 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le champ paquet reprend le nom du projet. Le champ classe demande le nom qui sera donn la classe principale du projet. Prenez le nom ci-dessus et faites [suivant] :
Notre application comporte une seconde classe Java pour la fentre de l'application. Donnez un nom cette classe. Le champ Titre est le titre que vous voulez donner cette fentre. Le cadre options vous propose des options pour votre fentre. Prenez-les toutes et faites [Terminer]. Vous revenez alors l'environnement Jbuilder qui s'est enrichi des informations que vous avez donnes pour votre projet :
- 234 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Dans la fentre de gauche/haut (1), vous avez la liste des fichiers qui composent votre projet. On trouve notamment les deux classes .java dont nous venons de donner le nom. Dans la fentre de droite (2) vous avez le code Java de la classe coucouCadre. Dans la fentre de gauche/bas, vous avez la structure (classes, mthodes, attributs) de votre projet. Il est prt tre excut. Appuyez sur le bouton 4 ci-dessus ou faites Excuter/Excuter le projet ou faites F9. Vous devriez obtenir la fentre suivante :
En cliquant sur l'option Aide, vous devriez retrouver des informations que vous avez donnes aux assistants de cration. Nous n'irons pas plus loin. Il est temps maintenant de vous plonger dans les tutoriels. Avant de terminer, montrons simplement que vous pouvez utiliser non pas Jbuilder et son interface graphique mais le jdk qu'il a amen avec lui et qu'il a plac dans /opt/jbuilder4/jdk1.3. Construisez le fichier essai1.java suivant :
import java.io.*; public class essai1{ public static void main(String args[]){ System.out.println("coucou");
- 235 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
System.exit(0); } }
- 236 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Une application s'appuyant sur ces pilotes peut utiliser n'importe quelle bases de donnes ci-dessus sans r-criture.
Afin que les applications Java puissent tirer parti elles-aussi de l'interface ODBC, Sun a cr l'intervace JDBC (Java DataBase Connectivity) qui va s'intercaler entre l'application Java et l'interface ODBC :
- 237 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
V-B - Les tapes importantes dans l'exploitation des bases de donnes V-B-1 - Introduction
Dans une application JAVA utilisant une base de donnes avec l'interface JDBC, on trouvera gnralement les tapes suivantes : 1 2 3 4 Connexion la base de donnes mission de requtes SQL vers la base Rception et traitement des rsultats de ces requtes Fermeture de la connexion
Les tapes 2 et 3 sont ralises de faon rpte, la fermeture de connexion n'ayant lieu qu' la fin de l'exploitation de la base. C'est un schma relativement classique dont vous avez peut-tre l'habitude si vous avez exploit une base de donnes de faon interactive. Nous allons dtailler chacune de ces tapes sur un exemple. Nous considrons une base de donnes ACCESS appele ARTICLES et ayant la structure suivante : nom code nom prix stock_actu stock_mini type code de l'article sur 4 caractres son nom (chane de caractres) son prix (rel) son stock actuel (entier) le stock minimum (entier) en-dea duquel il faut rapprovisionner l'article
Cette base ACCESS est dfinie comme source de donnes utilisateur dans le gestionnaire des bases ODBC :
- 238 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 239 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cette configuration consiste essentiellement associer la base ARTICLES, le fichier Access articles.mdb correspondant cette base. Ceci fait, la base ARTICLES est accessible aux applications utilisant l'interface ODBC.
URL
id mdp
classe Java dtenant la liste des pilotes disponibles pour l'application classe Java tablissant un lien entre l'application et la base grce auquel l'application va transmettre des requtes SQL la base et recevoir des rsultats nom identifiant la base de donnes. Ce nom est analogue aux URL de l'Internet. C'est pourquoi il fait partie de la classe URL. Cependant l'Internet n'intervient aucunement ici. L'URL a la forme suivante : jdbc:nom_du_pilote:nom_de_la_source;param=val1;param2=v Dans nos exemples o l'on utilisera exclusivement des pilotes ODBC, le pilote s'appelle odbc. La troisime partie de l'URL est constitue du nom de la source avec d'ventuels paramtres. Dans nos exemples, il s'agira de sources ODBC connues du systme. Ainsi l'URL de la source de donnes Articles dfinie prcdemment sera jdbc:odbc:Articles Identit de l'utilisateur (login mot de passe de l'utilisateur (password)
- 240 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Pour rsumer, le programme se connecte une base de donnes : identifie par un nom (URL) sous l'identit d'un utilisateur (id, mdp)
Si ces trois paramtres sont corrects, et si le pilote capable d'assurer la connexion de l'application Java la base de donnes prcise existe, alors une connexion est ralise entre l'application Java et la base de donnes. Celle-ci est matrialise pour le programme par l'objet de type Connection rendu par la classe DriverManager. Comme cette connexion peut chouer pour diverses raisons, elle est susceptible de lancer une exception. On crira donc :
Connection connexion=null; URL base=...; String id=...; String mdp=...; try{ connexion=DriverManager.getConnection(base,id,mdp); } catch (Exception e){ // traiter l'exception }
Pour que la connexion une base de donnes soit possible, il faut disposer du pilote adquat. Dans nos exemples, il s'agira du pilote ODBC capable de grer la base de donnes demande. S'il faut que ce pilote soit disponible dans la liste des pilotes ODBC prsents sur la machine, il faut galement disposer de la classe JAVA qui fera l'interface avec lui. Pour ce faire, l'application va requrir la classe qui lui est ncessaire de la faon suivante :
Class.forName(String nomClasse)
La classe Class n'est en rien lie l'interface JDBC. C'est une classe gnrale de gestion des classes. Sa mthode statique forName permet de charger dynamiquement une classe et donc de bnficier de ses attributs et mthodes statiques. La classe faisant l'interface avec les pilotes ODBC de MS Windows s'appelle sun.jdbc.odbc.JdbcOdbcDriver . On crira donc (la mthode peut gnrer une exception) :
try{ Class.forName( sun.jdbc.odbc.JdbcOdbcDriver ) ; } catch (Exception e){ // traiter l'exception (classe inexistante) }
Les classes ncessaires l'interface JDBC se trouvent dans le package java.sql. On crira donc en dbut de programme :
import java.sql.*;
- 241 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String mdp=""; if(arg.length>=3) uid=arg[2]; if(arg.length==4) mdp=arg[3]; try{ Class.forName(arg[0]); connect=DriverManager.getConnection(arg[1],uid,mdp); System.out.println("Connexion avec la base " + arg[1] + " tablie"); } catch (Exception e){ erreur("Erreur " + e,2); } // fermeture de la base try{ connect.close(); System.out.println("Base " + arg[1] + " ferme"); } catch (Exception e){} }// main public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); } }// classe
Une fois obtenu un objet Statement, on peut mettre des requtes SQL. Cela se fera diffremment selon que la requte est une requte d'interrogation ou de mise jour de la base.
- 242 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Seuls les mots cls de la premire ligne sont obligatoires, les autres sont facultatifs. Il existe d'autres mots cls non prsents ici. Une jointure est faite avec toutes les tables qui sont derrire le mot cl from Seules les colonnes qui sont derrire le mot cl select sont conserves Seules les lignes vrifiant la condition du mot cl where sont conserves Les lignes rsultantes ordonnes selon l'expression du mot cl order by forment le rsultat de la requte.
Le rsultat d'un select est une table. Si on considre la table ARTICLES prcdente et qu'on veuille les noms des articles dont le stock actuel est au-dessous du seuil minimal, on crira : select nom from articles where stock_actu<stock_mini. Si on les veut par ordre alphabtique des noms, on crira : select nom from articles where stock_actu<stock_mini order by nom Pour excuter ce type de requte, la classe Statement offre la mthode executeQuery :
ResultSet executeQuery(String requte)
o requte est le texte de la requte SELECT mettre. Ainsi, si connexion est l'objet symbolisant la connexion avec la base de donnes Statement s=connexion.createStatement() cre l'objet Statement ncessaire pour l'mission des requtes SQL ResultSet rs=s.executeQuery( select nom from articles where stock_actu<stock_mini ) excute une requte select et affecte les lignes rsultats de la requte un objet de type ResultSet.
Cette mthode tente de passer la ligne suivante du ResultSet et rend true si elle russit, false sinon. En cas de russite, la ligne suivante devient la nouvelle ligne courante. La ligne prcdente est perdue et on ne pourra revenir en arrire pour la rcuprer. La table du ResultSet a des colonnes col1, col2,.... Pour exploiter les diffrents champs de la ligne courante, on dispose des mthodes suivantes :
Type getType("coli")
pour obtenir le champ coli de la ligne courante. Type dsigne le type du champ coli. On utilise assez souvent la mthode getString sur tous les champs, ce qui permet d'obtenir le contenu du champ en tant que chane de caractres. On convertit ensuite si ncessaire. Si on ne connat pas le nom de la colonne, on peut utiliser les mthodes
Type getType(i)
- 244 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On notera deux mthodes utiles dans la classe ResultSetMetaData : 1 2 int getColumnCount() qui donne le nombre de colonnes du ResultSet String getColumnLabel(int i) qui donne le nom de la colonne i du ResultSet (i>=1)
- 245 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
System.out.println("Rsultats obtenus\n\n"); while(RS.next()){ // tant qu'il y a une ligne exploiter // on l'affiche l'cran for(int i=1;i<nbColonnes;i++) System.out.print(RS.getString(i)+","); System.out.println(RS.getString(nbColonnes)); }// ligne suivante // requte suivante System.out.print("Requte : "); select=in.readLine(); }// while } catch (Exception e){ erreur("Erreur " + e,2); } // fermeture de la base et du flux d'entre try{ connect.close(); System.out.println("Base " + DB + " ferme"); in.close(); } catch (Exception e){} }// main public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); } }// classe
- 246 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 247 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Voici le rsultat de diverses excutions des programmes sql1 et sql2 : Liste des lignes de la base ARTICLES :
E:\data\java\jdbc\0>java sql1 Connexion avec la base ARTICLES tablie Requte : select nom,stock_actu from articles Rsultats obtenus arc,10 cano,12 fusil,10 skis nautiques,3 essai3,3 cachalot,0 lopard,1 panthre,1
Vrification :
E:\data\java\jdbc\0>java sql1 Connexion avec la base ARTICLES tablie Requte : select nom,stock_actu from articles Rsultats obtenus vlo,31 arc,10 cano,13 fusil,10 skis nautiques,3 essai3,3 cachalot,0 lopard,1 panthre,1
Vrification :
E:\data\java\jdbc\0>java sql1 Connexion avec la base ARTICLES tablie Requ_te : select nom,stock_actu from articles Rsultats obtenus vlo,31 arc,10 cano,13 fusil,10 skis nautiques,3 essai3,3 cachalot,0 lopard,1 panthre,1 nouveau,20
- 248 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Vrification :
E:\data\java\jdbc\0>java sql1 Connexion avec la base ARTICLES tablie Requte : select nom,stock_actu from articles Rsultats obtenus vlo,31 arc,10 cano_,13 fusil,10 skis nautiques,3 essai3,3 cachalot,0 lopard,1 panthre,1
Le rsultat rendu est le boolen true si la requte a rendu un ResultSet (executeQuery), false si elle a rendu un nombre (executeUpdate). Le ResultSet obtenu peut tre rcupr avec la mthode getResultSet et le nombre de lignes mises jour, par la mthode getUpdateCount. Ainsi on crira :
Statement S=...; ResultSet RS=...; int nbLignes; String requte=...; // excution d'une requte SQL if (S.execute(requte)){ // on a un resultset RS=S.getResultSet(); // exploitation du ResultSet ... } else { // c'tait une requte de mise jour nbLignes=S.getUpdateCount(); ... }
- 249 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// se connecte la base URL grce la classe JDBC PILOTE // l'utilisateur UID est identifi par un mot de passe MDP public class sql3{ static String syntaxe="pg PILOTE URL UID MDP"; public static void main(String arg[]){
// vrification du nb d'arguments if(arg.length<2 || arg.length>4) erreur(syntaxe,1); // init paramtres de la connexion Connection connect=null; String uid=""; String mdp=""; if(arg.length>=3) uid=arg[2]; if(arg.length==4) mdp=arg[3];
// autres donnes Statement S=null; ResultSet RS=null; String sqlText; int nbLignes; int nbColonnes;
// // // // //
d'mission des requtes rsultat d'une requte d'interrogation de la requte SQL excuter lignes affectes par une mise jour colonnes d'un ResultSet
// cration d'un flux d'entre clavier BufferedReader in=null; try{ in=new BufferedReader(new InputStreamReader(System.in)); } catch(Exception e){ erreur("erreur lors de l'ouverture du flux clavier ("+e+")",3); } try{ // connexion la base Class.forName(arg[0]); connect=DriverManager.getConnection(arg[1],uid,mdp); System.out.println("Connexion avec la base " + arg[1] + " tablie"); // cration d'un objet Statement S=connect.createStatement(); // boucle d'excution des requtes SQL tapes au clavier System.out.print("Requte : "); sqlText=in.readLine(); while(!sqlText.equals("fin")){ // excution de la requte try{ if(S.execute(sqlText)){ // on a obtenu un ResultSet - on l'exploite RS=S.getResultSet(); // nombre de colonnes nbColonnes=RS.getMetaData().getColumnCount(); // exploitation de la table des rsultats System.out.println("\nRsultats obtenus\n-----------------\n"); while(RS.next()){ // tant qu'il y a une ligne exploiter // on l'affiche l'cran for(int i=1;i<nbColonnes;i++) System.out.print(RS.getString(i)+","); System.out.println(RS.getString(nbColonnes)); }// ligne suivante du ResultSet } else { // c'tait une requte de mise jour nbLignes=S.getUpdateCount(); // suivi System.out.println(nbLignes + " ligne(s) ont t mises jour"); }//if } catch (Exception e){ System.out.println("Erreur " +e); }
- 250 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// requte suivante System.out.print("\nNouvelle Requte : "); sqlText=in.readLine(); }// while } catch (Exception e){ erreur("Erreur " + e,2); } // fermeture de la base et du flux d'entre try{ // on libre les ressources lies la base RS.close(); S.close(); connect.close(); System.out.println("Base " + arg[1] + " ferme"); // fermeture flux clavier in.close(); } catch (Exception e){} }// main public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); } }// classe
Le programme prend donc ses entres dans le fichier requetes et met ses sorties dans le fichier results. Les rsultats obtenus sont les suivants :
Connexion avec la base jdbc:odbc:articles tablie Requte : (requete 1 du fichier des requetes : select * from articles) Rsultats obtenus ----------------a300,vlo,1202,31,3 d600,arc,5000,10,3 d800,cano,1502,13,7 x123,fusil,3000,10,3 s345,skis nautiques,1800,3,3 f450,essai3,3,3,4 f807,cachalot,200000,0,1 z400,lopard,500000,1,2 g457,panthre,800000,1,2 Nouvelle Requte : (requete 2 du fichier des requetes : update articles set stock_mini=stock_mini+5 where stock_mini<5) 8 ligne(s) ont t mises jour Nouvelle Requte : (requete 3 du fichier des requetes : select nom,stock_mini from articles) Rsultats obtenus -----------------
- 251 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
vlo,8 arc,8 cano,7 fusil,8 skis nautiques,8 essai3,9 cachalot,6 lopard,7 panthre,7 Nouvelle Requte : (requete 4 du fichier des requetes : insert into articles (code,nom,prix,stock_actu,stock_mini) values ('x400','nouveau',100,20,10)) 1 ligne(s) ont t mises jour Nouvelle Requte : (requete 5 du fichier des requetes : select * from articles) Rsultats obtenus ----------------a300,vlo,1202,31,8 d600,arc,5000,10,8 d800,cano,1502,13,7 x123,fusil,3000,10,8 s345,skis nautiques,1800,3,8 f450,essai3,3,3,9 f807,cachalot,200000,0,6 z400,lopard,500000,1,7 g457,panthre,800000,1,7 x400,nouveau,100,20,10 Nouvelle Requte : (requete 6 du fichier des requtes : delete from articles where code='x400') 1 ligne(s) ont t mises jour Nouvelle Requte : (requete 7 du fichier des requtes : select * from articles) Rsultats obtenus ----------------a300,vlo,1202,31,8 d600,arc,5000,10,8 d800,cano,1502,13,7 x123,fusil,3000,10,8 s345,skis nautiques,1800,3,8 f450,essai3,3,3,9 f807,cachalot,200000,0,6 z400,lopard,500000,1,7 g457,panthre,800000,1,7
- 252 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
mysql> show tables; +--------------------+ | Tables_in_dbimpots | +--------------------+ | impots | +--------------------+ 1 row in set (0.00 sec) mysql> describe impots; +---------+--------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------+------+-----+---------+-------+ | limites | double | YES | | NULL | | | coeffR | double | YES | | NULL | | | coeffN | double | YES | | NULL | | +---------+--------+------+-----+---------+-------+ 3 rows in set (0.02 sec) mysql> select * from impots; +---------+--------+---------+ | limites | coeffR | coeffN | +---------+--------+---------+ | 12620 | 0 | 0 | | 13190 | 0.05 | 631 | | 15640 | 0.1 | 1290.5 | | 24740 | 0.15 | 2072.5 | | 31810 | 0.2 | 3309.5 | | 39970 | 0.25 | 4900 | | 48360 | 0.3 | 6898 | | 55790 | 0.35 | 9316.5 | | 92970 | 0.4 | 12106 | | 127860 | 0.45 | 16754 | | 151250 | 0.5 | 23147.5 | | 172040 | 0.55 | 30710 | | 195000 | 0.6 | 39312 | | 0 | 0.65 | 49062 | +---------+--------+---------+ 14 rows in set (0.00 sec) mysql>quit
- 253 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'interface graphique a subi quelques modifications : n 1 type JTextField nom txtConnexion rle chane de connexion la base de donnes ODBC conteneur pour le Textarea 3 affiche des messages d'tat notamment des messages d'erreurs
2 3
JScrollPane JTextArea
JScrollPane1 txtStatus
La chane de connexion tape dans (1) a la forme suivante : DSN;login;motdepasse avec DSN login motdepasse le nom DSN de la source de donnes ODBC identit d'un utilisateur ayant un droit de lecture sur la base son mot de passe
La base de donnes dbimpots a t cre la main avec MySQL. On la transforme en source de donnes ODBC de la faon suivante : on lance le gestionnaire des sources de donnes ODBC 32 bits
- 254 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
on utilise le bouton [Add] pour ajouter une nouvelle source de donnes ODBC
le pilote MySQL demande un certain nombre de renseignements : le nom DSN donner la source de donnes ODBC - peut-tre quelconque
- 255 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
3 4 5
la machine sur laquelle s'excute le SGBD MySQL - ici localhost. Il est intressant de noter que la base de donnes pourrait tre une base de donnes distante. Les applications locales utilisant la source de donnes ODBC ne s'en apercevraient pas. Ce serait le cas notamment de notre application Java. la base de donnes MySQL utiliser. MySQL est un SGBD qui gre des bases de donnes relationnelles qui sont des ensembles de tables relies entre-elles par des relations. Ici, on donne le nom de la base gre. le nom d'un utilisateur ayant un droit d'accs cette base son mot de passe
Une fois la source de donnes ODBC dfinie, on peut tester notre programme :
Examinons le code qui, compar la version graphique sans base de donnes a t modifi. Rappelons le code de la classe impots utilise jusqu'ici :
// cration d'une classe impots public class impots{ // les donnes ncessaires au calcul de l'impt // proviennent d'une source extrieure private double[] limites, coeffR, coeffN; // constructeur public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception{ // on vrifie que les 3 tableaux ont la mme taille boolean OK=LIMITES.length==COEFFR.length && LIMITES.length==COEFFN.length; if (! OK) throw new Exception ("Les 3 tableaux fournis n'ont pas la mme taille("+ LIMITES.length+","+COEFFR.length+","+COEFFN.length+")"); // c'est bon this.limites=LIMITES; this.coeffR=COEFFR; this.coeffN=COEFFN; }//constructeur
- 256 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// calcul de l'impt public long calculer(boolean mari, int nbEnfants, int salaire){ // calcul du nombre de parts double nbParts; if (mari) nbParts=(double)nbEnfants/2+2; else nbParts=(double)nbEnfants/2+1; if (nbEnfants>=3) nbParts+=0.5; // calcul revenu imposable & Quotient familial double revenu=0.72*salaire; double QF=revenu/nbParts; // calcul de l'impt limites[limites.length-1]=QF+1; int i=0; while(QF>limites[i]) i++; // retour rsultat return (long)(revenu*coeffR[i]-nbParts*coeffN[i]); }//calculer }//classe
Cette classe construit les trois tableaux limites, coeffR, coeffN partir de trois tableaux passs en paramtres son constructeur. On dcide de lui adjoindre un nouveau constructeur permettant de construire les trois mmes tableaux partir d'une base de donnes :
public impots(String dsnIMPOTS, String userIMPOTS, String mdpIMPOTS) throws SQLException,ClassNotFoundException{ // dsnIMPOTS : nom DSN de la base de donnes // userIMPOTS, mdpIMPOTS : login/mot de passe d'accs la base
Pour l'exemple, nous dcidons de ne pas implmenter ce nouveau constructeur dans la classe impots mais dans une classe drive impotsJDBC :
// paquetages imports import java.sql.*; import java.util.*; public class impotsJDBC extends impots{ // rajout d'un constructeur permettant de construire // les tableaux limites, coeffr, coeffn partir de la table // impots d'une base de donnes public impotsJDBC(String dsnIMPOTS, String userIMPOTS, String mdpIMPOTS) throws SQLException,ClassNotFoundException{ // dsnIMPOTS : nom DSN de la base de donnes // userIMPOTS, mdpIMPOTS : login/mot de passe d'accs la base // les tableaux de donnes ArrayList aLimites=new ArrayList(); ArrayList aCoeffR=new ArrayList(); ArrayList aCoeffN=new ArrayList(); // connexion la base Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection connect=DriverManager.getConnection("jdbc:odbc:"+dsnIMPOTS,userIMPOTS,mdpIMPOTS); // cration d'un objet Statement Statement S=connect.createStatement(); // requte select String select="select limites, coeffr, coeffn from impots"; // excution de la requte ResultSet RS=S.executeQuery(select); while(RS.next()){ // exploitation de la ligne courante aLimites.add(RS.getString("limites")); aCoeffR.add(RS.getString("coeffr")); aCoeffN.add(RS.getString("coeffn")); }// ligne suivante // fermeture ressources RS.close(); S.close(); connect.close(); // transfert des donnes dans des tableaux borns
- 257 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
int n=aLimites.size(); limites=new double[n]; coeffR=new double[n]; coeffN=new double[n]; for(int i=0;i<n;i++){ limites[i]=Double.parseDouble((String)aLimites.get(i)); coeffR[i]=Double.parseDouble((String)aCoeffR.get(i)); coeffN[i]=Double.parseDouble((String)aCoeffN.get(i)); }//for }//constructeur }//classe
Le constructeur lit le contenu de la table impots de la base qu'on lui a pass en paramtres et remplit les trois tableaux limites, coeffR, coeffN. Un certain nombre d'erreurs peuvent se produire. Le constructeur ne les gre pas mais les "remonte" au programme appelant :
public impotsJDBC(String dsnIMPOTS, String userIMPOTS, String mdpIMPOTS) throws SQLException,ClassNotFoundException{
Si on prte attention au code prcdent, on verra que la classe impotsJDBC utilise directement les champs limites, coeffR, coeffN de sa classe de base impots. Ceux-ci tant dclars privs :
private double[] limites, coeffR, coeffN;
la classe impotsJDBC n'a pas d'accs ces champs directement. Nous faisons donc une premire modification la classe de base en crivant :
protected double[] limites=null; protected double[] coeffR=null; protected double[] coeffN=null;
L'attribut protected permet aux classes drives de la classe impots d'avoir un accs direct aux champs dclars avec cet attribut. Il nous faut faire une seconde modification. Le constructeur de la classe fille impotsJDBC est dclare comme suit :
public impotsJDBC(String dsnIMPOTS, String userIMPOTS, String mdpIMPOTS) throws SQLException,ClassNotFoundException{
On sait qu'avant de construire un objet d'une classe fille, on doit d'abord construire un objet de la classe parent. Pour ce faire, le constructeur de la classe fille doit appeler explicitement le constructeur de la classe parent avec une instruction super(....). Ici ce n'est pas fait car on ne voit pas quel constructeur de la classe parent on pourrait appeler. Il n'y en a pour l'instant qu'un et il ne convient pas. Le compilateur va alors chercher dans la classe parent un constructeur sans paramtres qu'il pourrait appeler. Il n'en trouve pas et cela gnre une erreur la compilation. Nous ajoutons donc un constructeur sans arguments notre classe impots :
// constructeur vide protected impots(){}
Nous le dclarons "protected" afin qu'il ne puisse tre utilis que par des classes filles. Le squelette de la classe impots est devenu maintenant le suivant :
public class impots{ // les donnes ncessaires au calcul de l'impt // proviennent d'une source extrieure protected double[] limites=null; protected double[] coeffR=null; protected double[] coeffN=null; // constructeur vide
- 258 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
protected impots(){} // constructeur public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception{ ........... }//constructeur // calcul de l'impt public long calculer(boolean mari, int nbEnfants, int salaire){ ............. }//calculer }//classe
Une fois l'objet objImpots cr, l'application est identique l'application graphique dj crite. Le lecteur est invit s'y reporter.
V-D-2 - Exercice 2
Une applet Java ne peut accder une base de donnes que par l'intermdiaire du serveur partir duquel elle a t charge. En effet, une applet n'ayant pas accs au disque de la machine sur laquelle elle est excutz, la base de donnes ne peut tre sur la machine du client utilisant l'applet. On est donc dans la situation suivante :
- 259 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La machine qui excute l'applet, le serveur et la machine qui dtient la base de donnes peuvent tre trois machines diffrentes. On suppose ici que la base de donnes se trouve sur le serveur. Problme 1 crire en Java l'application serveur suivante : l'application serveur travaille sur un port qui lui est pass en paramtre lorsqu'un client se connecte, l'application serveur envoie le message
200 - Bienvenue - Envoyez votre requte le client envoie alors les paramtres ncessaires la connexion une base de donnes et la requte qu'il veut excuter sous la forme :
Pilote Java/URL base/UID/MDP/requte SQL Les paramtres sont spars par la barre oblique. Les quatre premiers paramtres sont ceux du programme sql3 dcrit dans ce chapitre. L'application serveur cre alors une connexion avec la base de donnes prcise qui doit se trouver sur la mme machine qu'elle et excute la requte SQL dessus. Les rsultats sont renvoys au client sous la forme :
100 - ligne1 100 - ligne2 ... s'il s'agit du rsultat d'une requte Select ou 101 - nbLignes
pour rendre le nombre de lignes affectes par une requte de mise jour. Si une erreur de connexion la base ou d'excution de la requte se produit, l'application renvoie 500 - Message d'erreur une fois, la requte excute, l'application serveur ferme la connexion.
Problme 2 Crez une applet Java permettant d'interroger le serveur prcdent. On pourra s'inspirer de l'interface graphique de l'exercice 1 prcdent. Comme le port du serveur peut varier, celui-ci fera l'objet d'une saisie dans l'interface de l'applet. Il en sera de mme pour tous les paramtres ncessaires l'envoi de la ligne : Pilote Java/URL base/UID/MDP/requte SQL que le client doit envoyer au serveur.
- 260 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
V-D-3 - Exercice 3
Le texte suivant expose un problme destin initialement tre trait en Visual Basic. Adaptez-le pour un traitement en Java dans une applet. Cette dernire s'appuiera sur le serveur de l'exercice 2. L'interface graphique pourra tre modifie pour tenir compte du nouveau contexte d'excution. On se propose de crer une application mettant en lumire les diffrentes oprations de mise jour possibles d'une table d'une base de donnes ACCESS. La base de donnes ACCESS s'appelle articles.mdb. Elle a une unique table nomme articles qui rpertorie les articles vendus par une entreprise. Sa structure est la suivante : nom code nom prix stock_actu stock_mini type code de l'article sur 4 caractres son nom (chane de caractres) son prix (rel) son stock actuel (entier) le stock minimum (entier) en-dea duquel il faut rapprovisioner l'article
- 261 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
n 1 textbox
type fiche
nom
2 3 4 5 6 7
8 9
HScrollBar button
position OK
10
button
Annuler
11 12
frame textbox
frame1 basename
13
textbox
sourcename
Fonction numro de la fiche visualise enabled est false code de l'article nom de l'article prix de l'article stock actuel de l'article stock minimum de l'article Contrle data associ la base de donnes databasename=chemin du fichier articles.mdb recordsource=articles connect=access permet de naviguer dans la table permet de valider une mise jour n'apparat que lors de celle-ci permet d'annuler une mise jour n'apparat que lors de celle-ci pour faire joli nom de la base ouverte enabled est false nom de la table ouverte enabled est false
- 262 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cration de la feuille sous VB contrle data1 Particularits les champs databasename et recordsource sont renseigns. databasename doit dsigner la base Access articles.mdb de votre rpertoire et recordsource la table articles. c'est un textbox qu'on veut lier au champ code de l'enregistrement courant de data1. Pour cela on renseigne deux champs : datasource : on met data1 pour indiquer que le textbox est li la table associe data1 datafield : on choisit le champ code de la table articles Aprs ces oprations, le textbox code contiendra toujours le champ code de l'enregistrement courant de data1. Inversement, modifier le contenu de ce textbox modifiera le champ code de la fiche courante. On fait de mme pour les autres textbox datasource : data1 datafield : nom datasource : data1 datafield : prix datasource : data1 datafield : stock_actu datasource : data1 datafield : stock_mini Les menus La structure des menus est la suivante Edition Ajouter Modifier Supprimer Parcourir Prcdent Suivant Premier Dernier Quitter
code
- 263 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
name
Supprimer
mnusupprimer
Modifier
mnumodifier
fonction pour ajouter un nouvel enregistrement la table articles pour supprimer de la table articles, l'enregistrement actuellement visualis pour modifier dans la table articles, l'enregistrement actuellement visualis pour passer l'enregistrement prcdent pour passer l'enregistrement suivant pour passer au premier enregistrement pour passer au dernier enregistrement pour quitter l'application
Lors de l'vnement form_load, la table associe data1 est ouverte (data1.refresh). Si l'ouverture choue, un message d'erreur est affich et le programme se termine (end). Sinon, le formulaire est affich avec visualis, le premier enregistrement de la table articles. Aucune saisie dans les champs n'est possible (proprit enabled false). Cette saisie n'est possible qu'avec les options Ajouter et Modifier. Les boutons OK et Annuler sont cachs (visible=false). Partie 1 On se propose de construire les procdures lies aux diffrentes options du menu ainsi qu'aux boutons OK et Annuler. Dans un premier temps, on ignorera les points suivants : l'autorisation/inhibition de certaines options du menu : par exemple, l'option Suivant doit tre inhibe si on est positionn sur le dernier enregistrement de la table la gestion du scroller horizontal
menu Parcourir/Suivant fait passer l'enregistrement suivant (data1.RecordSet.MoveNext) si on n'est pas en fin de fichier (data1.RecordSet.EOF). Met jour le textbox fiche (data1.recordset.absoluteposition/ data1.recordset.recordcount). menu Parcourir/Prcdent fait passer l'enregistrement prcdent (data1.RecordSet.MovePrevious) si on n'est pas en dbut de fichier (data1.RecordSet.BOF). Met jour le textbox fiche. menu Parcourir/Premier fait passer au premier enregistrement (data1.RecordSet.MoveFirst) (data1.recordset.recordcount=0). Met jour le textbox fiche. menu Parcourir/Dernier si le fichier n'est pas vide
- 264 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
fait passer au dernier enregistrement (data1.RecordSet.MoveLast) (data1.recordset.recordcount=0). Met jour le textbox fiche. menu Edition/Ajouter permet d'ajouter un enregistrement la table met en mode Ajout d'enregistrement (data1.recordset.addnew) autorise les saisies sur les 5 champs code, nom, prix,... (enabled=true) inhibe les menus Edition, Parcourir, Quitter (enabled=false) affiche les boutons OK et Annuler (visible=true)
si
le
fichier
n'est
pas
vide
bouton OK valide une modification d'enregistrement (data1.recordset.Update) cache les boutons OK et Annuler (visible=false) autorise les options Edition, Parcourir, Quitter (enabled=true) met jour le textbox fiche
bouton Annuler invalide une modification d'enregistrement (data1.recordset.CancelUpdate) cache les boutons OK et Annuler (visible=false) autorise les options Edition, Parcourir, Quitter (enabled=true) met jour le textbox fiche
menu Edition/Modifier permet de modifier l'enregistrement visualis sur le formulaire met en mode Edition d'enregistrement (data1.recordset.edit) autorise les saisies sur les 4 champs nom, prix,... (enabled=true) mais pas sur le champ code (enabled=false) inhibe les menus Edition, Parcourir, Quitter (enabled=false) affiche les boutons OK et Annuler (visible=true)
menu Edition/Supprimer permet de supprimer (data1.recordset.delete) l'enregistrement visualis de la table passe la fiche suivante (data1.recordset.movenext)
vnement form_unload (cancel as integer) activ par l'opration unload me ou la fermeture du formulaire par Alt-F4 ou un double-clic sur la case systme, donc pas forcment par l'option quitter. pose la question Voulez-vous vraiment quitter l'application avec deux boutons Oui/Non (msgbox avec style=vbyes+vbno)
- 265 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
si la rponse est Non (=vbno) on met cancel -1 et on quitte la procdure form_unload. cancel -1 indique que la fermeture de la fentre est refuse. si la rponse est oui (=vbyes), la base est ferme (data1.recordset.close, data1.database.close). Partie 2 - Gestion des menus
Ici, on s'intresse l'autorisation/inhibition des menus. Aprs chaque opration changeant la fiche courante on appellera une procdure qu'on pourra appeler Oueston. Celle-ci vrifiera les conditions suivantes : si le fichier est vide, on
inhibera les menus Parcourir, Edition/Supprimer, autorisera les autres si la fiche courante est la premire fiche, on
inhibera Parcourir/Suivant autorisera le reste Partie 3 - Gestion du variateur horizontal Un variateur horizontal a trois champs importants : min : sa valeur minimale max : sa valeur maximale value : sa valeur actuelle
Initialisation du variateur Au chargement (form_load), le variateur sera initialis ainsi : min=0 max=data1.recordset.recordcount-1 value=1
On notera que juste aprs l'ouverture de la base (data1.refresh), le nombre d'enregistrements de la table reprsent par data1.recordset.recordcount est faux. Il faut aller en fin de table (MoveLast), puis revenir en dbut de table (MoveFirst) pour qu'il soit correct. Action directe sur le variateur La position du curseur du variateur reprsente la position dans la table.
- 266 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Lorsque l'utilisateur modifie le variateur (nomm position ici), l'vnement position_change est dclench. Dans cet vnement, on changera l'enregistrement courant de la table pour que celui-ci reflte le dplacement opr sur le variateur. Pour cela, on utilisera le champ absoluteposition de data1.recordset. Lorsqu'on affecte la valeur i ce champ, la fiche n i de la table devient la fiche courante. Les fiches sont numrotes partir de 0 et ont donc un n dans l'intervalle [0,data1.recordset.recordcount-1]. Dans la procdure position_change, il nous suffit d'crire data1.recordset.absoluteposition=position.value pour que la fiche courante visualise sur le formulaire reflte le dplacement opr sur le variateur. Ceci fait, on appellera ensuite, la procdure Oueston pour mettre jour les menus. Mise jour du variateur Puisque la position du curseur du variateur doit reflter la position dans la table, il faut mettre jour la valeur du variateur chaque fois qu'il y a un changement de fiche courante dans la table, produit par l'un ou l'autre des menus. Comme chacun de ceux-ci appelle la procdure Oueston, le mieux est de placer cette mise jour galement dans cette procdure. Il suffit d'crire ici : position.value=data1.recordset.absoluteposition Partie 4 - Option Chercher On ajoute l'option Parcourir/Chercher qui a pour but de permettre l'utilisateur de visualiser un article dont il donne le code. Lorsque cette option est active, se passent les squences suivantes : on se met en Ajout de fiche (Addnew), ceci dans le seul but de ne pas modifier la fiche courante sur laquelle on tait lorsque l'option a t active, on autorise la saisie dans le champ code et on efface le contenu du champ fiche, on inhibe les menus et affiche les boutons OK et Annuler lorsque l'utilisateur appuie sur OK, il nous faut chercher la fiche correspondant au code tap par l'utilisateur. Or la procdure OK_click sert dj aux options Parcourir/Ajouter et Parcourir/Modifier. Pour distinguer entre ces cas, on est amens grer une variable globale qu'on appellera ici tat qui aura trois valeurs possibles : ajouter , modifier et chercher . Les procdures lies aux boutons OK et Annuler utiliseront cette variable pour savoir dans quel contexte elles sont appeles. si tat vaut chercher , dans la procdure lie OK, on . annule l'opration addnew (data1.recordset.cancelupdate) car on n'avait pas l'intention d'ajouter une fiche. Il faut noter, qu'alors la fiche courante redevient celle qui tait prsente l'cran avant l'opration Parcourir/ Chercher. . construit le critre de recherche li au code et on lance la recherche (data1.recordset.findfirst critre), . si la recherche choue (data1.recordset.nomatch=true), on le signale l'utilisateur, puis on se remet en mode ajout (addnew) et on quitte la procdure OK. L'utilisateur devra retaper un nouveau code ou prendre l'option Annuler. . si la recherche aboutit, la fiche trouve devient la nouvelle fiche courante. On remet les menus, cache les boutons OK/Annuler, inhibe la saisie dans le champ code et on quitte la procdure. si tat vaut chercher , dans la procdure lie Annuler, on . annule l'opration addnew (data1.recordset.cancelupdate). On reviendra alors automatiquement sur la fiche courante d'avant l'opration Parcourir/Chercher. . remet les menus, cache les boutons OK/Annuler, inhibe la saisie dans le champ code et on quitte la procdure.
- 267 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Partie 5 - Gestion du code Un article doit tre repr de faon unique par son code. Faites en sorte que dans l'option Parcourir/Ajouter, l'ajout soit refus si l'enregistrement ajouter a un code article qui existe dj dans la table.
V-D-4 - Exercice 4
On prsente ici une application Web s'appuyant sur le serveur de l'exercice 2. C'est un embryon d'application de commerce lectronique. Le client commande des articles grce l'interface Web suivante :
Il peut faire les oprations suivantes : il slectionne un article dans la liste droulante il prcise la quantit dsire il valide son achat avec le bouton Acheter son achat est affich dans la liste des articles achets il peut retirer des articles de cette liste, en slectionnant un article et en usant du bouton Retirer lorsqu'il actionne le bouton Bilan, il obtient le bilan suivant :
- 268 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le bilan permet l'utilisateur de connatre le dtail de sa facture. L'utilisateur a accs des dtails concernant un article slectionn dans la liste droulante avec le bouton Informations :
- 269 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Lorsque l'utilisateur a demand le bilan de sa facture, il peut la valider avec la page suivante. Pour cela, il doit donner son adresse lectronique et confirmer sa commande avec le bouton adquat.
Une fois la commande confirme, l'application la traite et envoie une page de confirmation :
- 270 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
En ralit, l'application ne traite pas la commande. Elle se contente d'envoyer un courrier lectronique l'utilisateur lui demandant de rgler le montant des achats : Cher client, Vous trouverez ci-dessous le dtail de votre commande au magasin SuperPrix. Elle vous sera livre aprs rception de votre chque tabli l'ordre de SuperPrix et envoyer l'adresse suivante : SuperPrix ISTIA 62 av Notre-Dame du Lac 49000 Angers France -------------------Nous vous remercions vivement de votre commande -------------------article, quantit, prix unitaire, total ======================================== vlo, 2, 1202.00 F, 2404.00 F skis nautiques, 3, 1800.00 F, 5400.00 F
- 271 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Total payer : 7804 F Question : Crer l'quivalent de cette application Web avec une applet Java.
- 272 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
sleep(n) join()
Les constructeurs les plus couramment utiliss sont les suivants : Thread() cre une rfrence sur une tche asynchrone. Celle-ci est encore inactive. La tche cre doit possder la mthode run : ce sera le plus souvent une classe drive de Thread qui sera utilise. idem mais c'est l'objet Runnable pass en paramtre qui implmente la mthode run.
Thread(Runnable object)
Regardons une premire application mettant en vidence l'existence d'un thread principal d'excution, celui dans lequel s'excute la fonction main d'une classe :
// utilisation de threads import java.io.*; import java.util.*; public class thread1{ public static void main(String[] arg)throws Exception { // init thread courant Thread main=Thread.currentThread(); // affichage System.out.println("Thread courant : " + main.getName()); // on change le nom main.setName("myMainThread"); // vrification System.out.println("Thread courant : " + main.getName()); // boucle infinie while(true){ // on rcupre l'heure Calendar calendrier=Calendar.getInstance(); String H=calendrier.get(Calendar.HOUR_OF_DAY)+":" +calendrier.get(Calendar.MINUTE)+":" +calendrier.get(Calendar.SECOND); // affichage System.out.println(main.getName() + " : " +H); // arrt temporaire - 273 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'exemple prcdent illustre les points suivants : la fonction main s'excute bien dans un thread on a accs aux caractristiques de ce thread par Thread.currentThread() le rle de la mthode sleep. Ici le thread excutant main se met en sommeil rgulirement pendant 1 seconde entre deux affichages.
1. Un thread T peut tre cr de diverses faons en drivant la classe Thread et en redfinissant la mthode run de celle-ci. en implmentant l'interface Runnable dans une classe et en utilisant le constructeur new Thread(Runnable). Runnable est une interface qui ne dfinit qu'une seule mthode : public void run(). L'argument du constructeur prcdent est donc toute instance de classe implmentant cette mthode run.
Dans l'exemple qui suit, les threads sont construits l'aide d'une classe anonyme drivant la classe Thread :
// on cre le thread i tches[i]=new Thread() { public void run() { affiche(); } };//df tches[i]
La mthode run se contente ici de renvoyer sur une mthode affiche. 2. L'excution du thread T est lanc par T.start() : cette mthode appartient la classe Thread et opre un certain nombre d'initialisations puis lance automatiquement la mthode run du Thread ou de l'interface Runnable. Le programme qui excute l'instruction T.start() n'attend pas la fin de la tche T : il passe aussitt l'instruction qui
- 274 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
suit. On a alors deux tches qui s'excutent en parallle. Elles doivent souvent pouvoir communiquer entre elles pour savoir o en est le travail commun raliser. C'est le problme de synchronisation des threads. 3. Une fois lanc, le thread s'excute de faon autonome. Il s'arrtera lorsque la fonction run qu'il excute aura fini son travail. 4. On peut attendre la fin de l'excution du Thread T par T.join(). On a l une instruction bloquante : le programme qui l'excute est bloqu jusqu' ce que la tche T ait termin son travail. C'est galement un moyen de synchronisation. Examinons le programme suivant :
// utilisation de threads import java.io.*; import java.util.*; public class thread2{ public static void main(String[] arg) { // init thread courant Thread main=Thread.currentThread(); // on donne un nom au thread courant main.setName("myMainThread"); // dbut de main System.out.println("dbut du thread " +main.getName()); // cration de threads d'excution Thread[] tches=new Thread[5]; for(int i=0;i<tches.length;i++){ // on cre le thread i tches[i]=new Thread() { public void run() { affiche(); } };//df tches[i] // on fixe le nom du thread tches[i].setName(""+i); // on lance l'excution du thread i tches[i].start(); }//for // fin de main System.out.println("fin du thread " +main.getName()); }//Main public static void affiche() { // on rcupre l'heure Calendar calendrier=Calendar.getInstance(); String H=calendrier.get(Calendar.HOUR_OF_DAY)+":" +calendrier.get(Calendar.MINUTE)+":" +calendrier.get(Calendar.SECOND); // affichage dbut d'excution System.out.println("Dbut d'excution de la mthode affiche dans le Thread " + Thread.currentThread().getName()+ " : " + H); // mise en sommeil pendant 1 s try{ Thread.sleep(1000); }catch (Exception ex){} // on rcupre l'heure calendrier=Calendar.getInstance(); H=calendrier.get(Calendar.HOUR_OF_DAY)+":" +calendrier.get(Calendar.MINUTE)+":" +calendrier.get(Calendar.SECOND); // affichage fin d'excution System.out.println("Fin d'excution de la mthode affiche dans le Thread " +Thread.currentThread().getName()+ " : " + H); }// affiche }//classe
- 275 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le thread principal, celui qui excute la fonction main, cre 5 autres threads chargs d'excuter la mthode statique affiche. Les rsultats sont les suivants :
dbut du thread myMainThread Dbut d'excution de la mthode affiche dans le Thread fin du thread myMainThread Dbut d'excution de la mthode affiche dans le Thread Dbut d'excution de la mthode affiche dans le Thread Dbut d'excution de la mthode affiche dans le Thread Dbut d'excution de la mthode affiche dans le Thread Fin d'excution de la mthode affiche dans le Thread 0 Fin d'excution de la mthode affiche dans le Thread 1 Fin d'excution de la mthode affiche dans le Thread 2 Fin d'excution de la mthode affiche dans le Thread 3 Fin d'excution de la mthode affiche dans le Thread 4
0 : 15:48:3 1 2 3 4 : : : : : : 15:48:3 : 15:48:3 : 15:48:3 : 15:48:3 15:48:4 15:48:4 15:48:4 15:48:4 15:48:4
Ces rsultats sont trs instructifs : on voit tout d'abord que le lancement de l'excution d'un thread n'est pas bloquante. La mthode main a lanc l'excution de 5 threads en parallle et a termin son excution avant eux. L'opration
// on lance l'excution du thread i tches[i].start();
lance l'excution du thread tches[i] mais ceci fait, l'excution se poursuit immdiatement avec l'instruction qui suit sans attendre la fin d'excution du thread. tous les threads crs doivent excuter la mthode affiche. L'ordre d'excution est imprvisible. Mme si dans l'exemple, l'ordre d'excution semble suivre l'ordre de lancement des threads, on ne peut en conclure de gnralits. Le systme d'exploitation a ici 6 threads et un processeur. Il va distribuer le processeur ces 6 threads selon des rgles qui lui sont propres on voit dans les rsultats une consquence de la mthode sleep. Dans l'exemple, c'est le thread 0 qui excute le premier la mthode affiche. Le message de dbut d'excution est affich puis il excute la mthode sleep qui le suspend pendant 1 seconde. Il perd alors le processeur qui devient ainsi disponible pour un autre thread. L'exemple montre que c'est le thread 1 qui va l'obtenir. Le thread 1 va suivre le mme parcours ainsi que les autres threads. Lorsque la seconde de sommeil du thread 0 va tre termine, son excution peut reprendre. Le systme lui donne le processeur et il peut terminer l'excution de la mthode affiche.
Modifions notre programme pour le terminer la mthode main par les instructions :
// fin de main System.out.println("fin du thread " +main.getName()); // arrt de l'application System.exit(0);
le le le le
0 1 2 3
: : : :
- 276 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
elle arrte tous les threads de l'application et non simplement le thread main. La mthode main pourrait vouloir attendre la fin d'excution des threads qu'elle a crs avant de se terminer elle-mme. Cela peut se faire avec la mthode join de la classe Thread :
// attente de tous les threads for(int i=0;i<tches.length;i++){ // on attend le thread i tches[i].join(); }//for // fin de main System.out.println("fin du thread " +main.getName()); // arrt de l'application System.exit(0);
0 1 2 3 4 : : : : :
: 16:11:9 : 16:11:9 : 16:11:9 : 16:11:9 : 16:11:9 16:11:10 16:11:10 16:11:10 16:11:10 16:11:10
Nous utilisons tous les jours des applications de l'internet correspondant ce schma : services Web, messagerie lectronique, consultation de forums, transfert de fichiers... Dans le schma ci-dessus, le serveur S1 doit servir les clients Ci de faon simultane. Si nous prenons l'exemple d'un serveur FTP (File Transfer Protocol) qui dlivre des fichiers ses clients, nous savons qu'un transfert de fichier peut prendre parfois plusieurs heures. Il est bien sr hors de question qu'un client monopolise tout seul le serveur une telle dure. Ce qui est fait habituellement, c'est que le serveur cre autant de threads d'excution qu'il y a de clients. Chaque thread est alors charg de s'occuper d'un client particulier. Le processeur tant partag cycliquement entre tous les threads actifs de la machine, le serveur passe alors un peu de temps avec chaque client assurant ainsi la simultanit du service.
- 277 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Pour que l'horloge vive, il faut qu'un processus s'occupe de changer l'heure toutes les secondes. En mme temps, il faut surveiller les vnements qui se produisent dans la fentre : lorsque l'utilisateur cliquera sur le bouton "Arrter", il faudra stopper l'horloge. On a l deux tches parallles et asynchrones : l'utilisateur peut cliquer n'importe quand. Considrons le moment o l'horloge n'a pas encore t lance et o l'utilisateur clique sur le bouton "Lancer". On a l un vnement classique et on pourrait penser qu'une mthode du thread dans lequel s'excute la fentre peut alors grer l'horloge. Seulement lorsqu'une mthode de l'application graphique s'excute, le thread de celle-ci n'est plus l'coute des vnements de l'interface graphique. Ceux-ci se produisent et sont mis dans une file d'attente pour tre traits par l'application lorsque la mthode actuellement en cours d'excution sera acheve. Dans notre exemple d'horloge, la mthode sera toujours en cours d'excution puisque seul le clic sur le bouton "Arrter" peut la stopper. Or cet vnement ne sera trait que lorsque la mthode sera acheve. On tourne en rond. La solution ce problme serait que lorsque l'utilisateur clique sur le bouton "Lancer", une tche soit lance pour grer l'horloge mais que l'application puisse continuer couter les vnements qui se produisent dans la fentre. On aurait alors deux tches distinctes qui s'excuteraient en parallle : gestion de l'horloge coute des vnements de la fentr
- 278 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
n 1 2
public class interfaceHorloge extends JFrame { JPanel contentPane; JTextField txtHorloge = new JTextField(); JButton btnGoStop = new JButton(); // attributs d'instance boolean finHorloge=true; //Construire le cadre public interfaceHorloge() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void runHorloge(){ // on boucle tant qu'on nous a pas dit d'arrter while( ! finHorloge){ // on rcupre l'heure Calendar calendrier=Calendar.getInstance(); String H=calendrier.get(Calendar.HOUR_OF_DAY)+":" +calendrier.get(Calendar.MINUTE)+":" +calendrier.get(Calendar.SECOND); // on l'affiche dans le champ T txtHorloge.setText(H); // attente d'une seconde try{ Thread.sleep(1000); } catch (Exception e){ // sortie avec erreur System.exit(1); }//try }// while }// runHorloge //Initialiser le composant private void jbInit() throws Exception { ................... } //Remplac, ainsi nous pouvons sortir quand la fentre est ferme protected void processWindowEvent(WindowEvent e) { ............. - 279 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
} void btnGoStop_actionPerformed(ActionEvent e) { // on lance/arrte l'horloge // on rcupre le libell du bouton String libell=btnGoStop.getText(); // lancer ? if(libell.equals("Lancer")){ // on cre le thread dans lequel s'excutera l'horloge Thread thHorloge=new Thread(){ public void run(){ runHorloge(); } };//df thread // on autorise le thread dmarrer finHorloge=false; // on change le libell du bouton btnGoStop.setText("Arrter"); // on lance le thread thHorloge.start(); // fin return; }//if // arrter if(libell.equals("Arrter")){ // on dit au thread de s'arrter finHorloge=true; // on change le libell du bouton btnGoStop.setText("Lancer"); // fin return; }//if } }
Lorsque l'utilisateur clique sur le bouton "Lancer", un thread est cr l'aide d'une classe anonyme :
Thread thHorloge=new Thread(){ public void run(){ runHorloge(); }
La mthode run du thread renvoie la mthode runHorloge de l'application. Ceci fait, le thread est lanc :
// on lance le thread thHorloge.start();
- 280 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le principe de la mthode est le suivant : 1 2 3 affiche l'heure courante dans la bote de texte txtHorloge s'arrte 1 seconde reprend l'tape 1 en ayant pris soin de tester auparavant le boolen finHorloge qui sera positionn vrai lorsque l'utilisateur cliquera sur le bouton Arrter.
Lorsque nous chargeons directement ce document dans IE en double-cliquant dessus, nous obtenons l'affichage suivant :
Tous les lments ncessaires l'applet sont dans cet exemple dans le mme dossier :
E:\data\serge\Jbuilder\horloge\1>dir 13/06/2002 12:17 3 174 appletHorloge.class 13/06/2002 12:17 658 appletHorloge$1.class 13/06/2002 12:17 512 appletHorloge$2.class 13/06/2002 12:20 245 appletHorloge.htm
Notre applet peut tre amliore. Nous avons dit qu'au chargement de l'applet, la mthode init tait excute puis ensuite la mthode start si elle existe. De plus, lorsque l'utilisateur quitte la page, la mthode stop est excute si elle existe. Lorsqu'il revient sur la page de l'applet, la mthode start est de nouveau appele. Lorsqu'une applet met en oeuvre des threads d'animation visuelle, on utilise souvent les mthodes start et stop de l'applet pour lancer et arrter les threads. Il est en effet inutile qu'un thread d'animation visuelle continue travailler en arrire-plan alors que l'animation est cache.
- 281 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous ajoutons donc notre applet les mthodes start et stop suivantes :
public void stop(){ // la page est cache // suivi System.out.println("Page stop"); // la page est cache - on arrte le thread finHorloge=true; } public void start(){ // la page rapparat // suivi System.out.println("Page start"); // on relance un nouveau thread horloge si ncessaire if(btnGoStop.getText().equals("Arrter")){ // on change le libell btnGoStop.setText("Lancer"); // et on fait comme si l'utilisateur avait cliqu dessus btnGoStop_actionPerformed(null); }//if }//start
Par ailleurs, nous avons ajout un suivi dans la mthode run du thread pour savoir quand il dmarre et s'arrte :
private void runHorloge(){ // suivi System.out.println("Thread horloge lanc"); // on boucle tant qu'on nous a pas dit d'arrter while( ! finHorloge){ // on rcupre l'heure Calendar calendrier=Calendar.getInstance(); String H=calendrier.get(Calendar.HOUR_OF_DAY)+":" +calendrier.get(Calendar.MINUTE)+":" +calendrier.get(Calendar.SECOND); // on l'affiche dans le champ T txtHorloge.setText(H); // attente d'une seconde try{ Thread.sleep(1000); } catch (Exception e){ // sortie avec erreur return; }//try }// while // suivi System.out.println("Thread horloge termin"); }// runHorloge
Avec AppletViewer, l'vnement start se produit lorsque la fentre d'AppletViewer est visible et l'vnement stop lorsqu'on la met en icne. Les rsultats ci-dessus montrent que lorsque le document HTML est cach, le thread est bien arrt s'il tait actif.
- 282 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La coordination entre les deux tches tait assure par la tche principale qui positionnait un boolen pour arrter le thread de l'horloge. Nous abordons maintenant le problme de l'accs concurrent de tches des ressource communes, problme connu aussi sous le nom de "partage de ressources". Pour l'illustrer, nous allons d'abord tudier un exemple.
JButton
btnGnrer
Le fonctionnement de l'application est le suivant : l'utilisateur indique le nombre de threads gnrer dans le champ 1 il lance la gnration de ces threads avec le bouton 4 les threads lisent la valeur du champ 2, l'incrmentent et affichent la nouvelle valeur. Au dpart ce champ contient la valeur 0.
Les threads gnrs se partagent une ressource : la valeur du champ 2. Nous cherchons montrer ici les problmes que l'on rencontre dans une telle situation. Voici un exemple d'excution :
- 283 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On voit qu'on a demand la gnration de 1000 threads et qu'il en a t compt que 7. Le code utile de l'application est le suivant :
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class interfaceSynchro extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); JTextField txtAGnrer = new JTextField(); JButton btnGnrer = new JButton(); JTextField txtStatus = new JTextField(); JTextField txtGnrs = new JTextField(); JLabel jLabel2 = new JLabel(); // variables d'instance Thread[] tches=null; // les threads int[] compteurs=null; // les compteurs //Construire le cadre public interfaceSynchro() { .......... } //Initialiser le composant private void jbInit() throws Exception { ...................... } //Remplac, ainsi nous pouvons sortir quand la fentre est ferme protected void processWindowEvent(WindowEvent e) { .................. } void btnGnrer_actionPerformed(ActionEvent e) { //gnration des threads // on lit le nombre de threads gnrer int nbThreads=0; try{ // lecture du champ contenant le nbre de threads nbThreads=Integer.parseInt(txtAGnrer.getText().trim()); // positif > if(nbThreads<=0) throw new Exception(); }catch(Exception ex){ //erreur txtStatus.setText("Nombre invalide"); // on recommnece txtAGnrer.requestFocus(); return; }//catch // au dpart pas de threads gnrs txtGnrs.setText("0"); // cpteur de tches 0 // on gnre et on lance les threads tches=new Thread[nbThreads]; compteurs=new int[nbThreads]; for(int i=0;i<tches.length;i++){ // on cre le thread i tches[i]=new Thread() { public void run() { incrmente(); } };//thread i // on dfinit son nom tches[i].setName(""+i); // on lance son excution tches[i].start(); }//for
- 284 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}//gnrer // incremente private void incrmente(){ // on rcupre le n du thread int iThread=0; try{ iThread=Integer.parseInt(Thread.currentThread().getName()); }catch(Exception ex){} // on lit la valeur du compteur de tches try{ compteurs[iThread]=Integer.parseInt(txtGnrs.getText()); } catch (Exception e){} // on l'incrmente compteurs[iThread]++; // on patiente 100 millisecondes - le thread va alors perdre le processeur try{ Thread.sleep(100); } catch (Exception e){ System.exit(0); } // on affiche le nouveau compteur txtGnrs.setText(""); txtGnrs.setText(""+compteurs[iThread]); // suivi System.out.println("Thread " + iThread + " : " + compteurs[iThread]); }// incremente }// classe
Le tableau tches sera le tableau des threads gnrs. Le tableau compteurs sera associ au tableau tches. Chaque tche aura un compteur propre pour rcuprer la valeur du champ txtGnrs de l'interface graphique. lors d'un clic sur le bouton Gnrer, la mthode btnGnrer_actionPerformed est excute. celle-ci commence par rcuprer le nombre de threads gnrer. Au besoin, une erreur est signale si ce nombre n'est pas exploitable. Elle gnre ensuite les threads demands en prenant soin de noter leurs rfrences dans un tableau et en donnant chacun d'eux un numro. La mthode run des threads gnrs renvoie sur la mthode incrmente de la classe. Les threads sont tous lancs (start). Le tableau des compteurs associs aux threads est galement cr. la mthode incrmente : lit la valeur actuelle du champ txtGnrs et la stocke dans le compteur appartenant au thread en cours d'excution s'arrte 100 ms, ceci afin de perdre volontairement le processeur affiche la nouvelle valeur dans le champ txtGnrs
Expliquons maintenant pourquoi le comptage des threads est incorrect. Supposons qu'il y ait 2 threads gnrer. Ils s'excutent dans un ordre imprvisible. L'un d'entre-eux passe le premier et lit la valeur 0 du compteur. Il la passe alors 1 mais il ne l'crit pas dans la fentre : il s'interrompt volontairement pendant 100 ms. Il perd alors le processeur qui est alors donn un autre thread. Celui-ci opre de la mme faon que le prcdent : il lit le compteur de la fentre et rcupre le 0 qui s'y trouve toujours. Il passe le compteur 1 et comme le prcdent s'interrompt 100 ms. Le processeur est alors de nouveau accord au premier thread : celui-ci va crire la valeur 1 dans le compteur de la fentre et se terminer. Le processeur est maintenant accord au second thread qui lui aussi va crire 1. On a un rsultat incorrect.
- 285 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
D'o vient le problme ? Le second thread a lu une mauvaise valeur du fait que le premier avait t interrompu avant d'avoir termin son travail qui tait de mettre jour le compteur dans la fentre. Cela nous amne la notion de ressource critique et de section critique d'un programme: une ressource critique est une ressource qui ne peut tre dtenue que par un thread la fois. Ici la ressource critique est le compteur 2 de la fentre. une section critique d'un programme est une squence d'instructions dans le flux d'excution d'un thread au cours de laquelle il accde une ressource critique. On doit assurer qu'au cours de cette section critique, il est le seul avoir accs la ressource.
Le mot cl synchronized signifie qu'un seul thread la fois peut excuter la mthode incrmente. Considrons les notations suivantes : l'objet fentre F qui cre les threads dans btnGnrer_actionPerformed deux threads T1 et T2 crs par F
Les deux threads sont crs par F puis lancs. Ils vont donc tous deux excuter la mthode F.run. Supposons que T1 arrive le premier. Il excute F.run puis F.incremente qui est une mthode synchronise. Il lit la valeur 0 du compteur, l'incrmente puis s'arrte 100 ms. Le processeur est alors donn T2 qui son tour excute F.run puis F.incremente. Et l il est bloqu car le thread T1 est en cours d'excution de F.incremente et le mot cl synchronized assure qu'un seul thread la fois peut excuter F.incremente. T2 perd alors le processeur son tour sans avoir pu lire la valeur du compteur. Au bout des 100 ms, T1 rcupre le processeur, affiche la valeur 1 du compteur, quitte F.incremente puis F.run et se termine. T2 rcupre alors le processeur et peut cette fois excuter F.incremente car T1 n'est plus en cours d'excution de cette mthode. T2 lit alors la valeur 1 du compteur, l'incrmente et s'arrte 100 ms. Au bout de 100 ms, il rcupre le processeur, affiche la valeur 2 du compteur et se termine lui aussi. Cette fois, la valeur obtenue est correcte. Voici un exemple test :
- 286 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On pourrait aussi dire que la ressource critique est l'objet F lui-mme. C'est plus strict que dans le cas o la ressource critique est F.incremente. En effet, dans ce dernier cas, si un thread T1 execute F.incremente, un thread T2 ne pourra pas excuter F.incremente mais pourra excuter une autre mthode de l'objet F qu'elle soit synchronise ou non. Dans le cas ou l'objet F est lui-mme la ressource critique, lorsque un thread T1 excute une section synchronise de cet objet, toutre autre section synchronise de l'objet devient inaccessible pour les autres threads. Ainsi si un thread T1 excute la mthode synchronise F.incremente, un thread T2 ne pourra pas excuter non seulement F.incremente mais galement toute autre section synchronise de F, ceci mme si aucun thread ne l'utilise. C'est donc une mthode plus contraignante. Supposons donc que la fentre devienne la ressource critique. On crira alors :
// incremente private void incrmente(){ // section critique synchronized(this){ // on rcupre le n du thread int iThread=0; try{ iThread=Integer.parseInt(Thread.currentThread().getName()); }catch(Exception ex){} // on lit la valeur du compteur de tches try{ compteurs[iThread]=Integer.parseInt(txtGnrs.getText()); } catch (Exception e){} // on l'incrmente compteurs[iThread]++; // on patiente 100 millisecondes - le thread va alors perdre le processeur try{ Thread.sleep(100); } catch (Exception e){ System.exit(0); } // on affiche le nouveau compteur txtGnrs.setText(""); txtGnrs.setText(""+compteurs[iThread]); }//synchronized }// incremente
Tous les threads utilisent la fentre this pour se synchroniser. A l'excution, on obtient les mmes rsultats corrects que prcdemment. On peut en fait se synchroniser sur n'importe quel objet connu de tous les threads. Voici par exemple une autre mthode qui donne les mmes rsultats :
// variables d'instance Thread[] tches=null; // les threads int[] compteurs=null; // les compteurs Object synchro=new Object(); // un objet de synchronisation de threads // incremente private void incrmente(){ // section critique synchronized(synchro){ .............. }//synchronized }// incremente
- 287 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La fentre cre un objet de type Object qui servira la synchronisation des threads. Cette mthode est meilleure que celle qui se synchronise sur l'objet this parce que moins contraignante. Ici, si un thread T1 est dans la section synchronise de incrmente et qu'un thread T2 veuille excuter une autre section synchronise du mme objet this mais synchronise par un autre objet que synchro, il le pourra.
La premire instruction o un thread boucle en attendant que peutPasser passe vrai est maladroite : le thread occupe le processeur inutilement. On parle d'attente active. On peut amliorer l'criture comme suit :
while(! peutPasser){ // on attend que peutPasser passe vrai Thread.sleep(100); // arrt pendant 100 ms } peutPasser=false; // aucun autre thread ne doit pas passer section critique; // ici le thread est tout seul peutPasser=true; // un autre thread peut passer dans la section critique
La boucle d'attente est ici meilleure : si le thread ne peut pas passer, il se met en sommeil pendant 100 ms avant de vrifier de nouveau s'il peut passer ou non. Le processeur va entre-temps tre attribu d'autres threads du systme. Ces deux mthodes sont en fait incorrectes : elle n'empche pas deux threads de s'engouffrer en mme temps dans la section critique. Supposons qu'un thread T1 dtecte que peutPasser est vrai. Il va alors passer l'instruction suivante o il remet peutPasser faux pour bloquer les autres Threads. Seulement, il peut trs bien tre interrompu ce moment, soit parce que sa part de temps du processeur est puise, soit parce qu'une tche plus prioritaire a demand le processeur ou pour une autre raison. Le rsultat est qu'il perd le processeur. Il le retrouvera un peu plus tard. Entre-temps d'autres tches vont obtenir le processeur dont peut-tre un thread T2 qui boucle en attendant que peutPasser passe vrai. Lui aussi va dcouvrir que peutPasser est vrai (le premier thread n'a pas eu le temps de le mettre faux) et va passer lui-aussi dans la section critique. Ce qu'il ne fallait pas. La squence
while(! peutPasser){ // on attend que peutPasser passe vrai try{ Thread.sleep(100); // arrt pendant 100 ms } catch (Exception e) {} }// while peutPasser=false; // aucun autre thread ne doit passer
est une squence critique qu'il faut protger par une synchronisation. S'inspirant de l'exemple prcdent, on peut crire :
synchronized(synchro){ while(! peutPasser){ // on attend que peutPasser passe vrai try{ Thread.sleep(100); // arrt pendant 100 ms } catch (Exception e) {} }//while peutPasser=false; // aucun autre thread ne doit pas passer }// synchronized section critique; // ici le thread est tout seul peutPasser=true; // un autre thread peut passer dans la section critique
- 288 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cet exemple fonctionne correctement. On peut l'amliorer en vitant l'attente semi-active du thread lorsqu'il surveille rgulirement la valeur du boolen peutPasser. Au lieu de se rveiller rgulirement toutes les 100 ms pour vrifier l'tat de peutPasser, il peut s'endormir et demander ce qu'on le rveille lorsque peutPasser sera vrai. On crit cela de la faon suivante :
synchronized(synchro){ if (! peutPasser) { try{ synchro.wait(); // si on ne peut pas passer alors on attend } catch (Exception e){ # } } peutPasser=false; // aucun autre thread ne doit pas passer }// synchronized
L'opration synchro.wait() ne peut tre faite que par un thread "propritaire" momentan de l'objet synchro. Ici, c'est la squence :
synchronized(synchro){ # }// synchronized
qui assure que le thread est propritaire de l'objet synchro. Par l'opration synchro.wait(), le thread cde la proprit du verrou de synchronisation. Pourquoi cela ? En gnral parce qu'il lui manque des ressources pour continuer travailler. Alors plutt que de bloquer les autres threads en attente de la ressource synchro, il la cde et se met en attente de la ressource qui lui manque. Dans notre exemple, il attend que le boolen peutPasser passe vrai. Comment sera-t-il averti de cet vnement ? De la faon suivante :
synchronized(synchro){ if (! peutPasser) { try{ synchro.wait(); // si on ne peut pas passer alors on attend } catch (Exception e){ # } } peutPasser=false; // aucun autre thread ne doit passer }// synchronized section critique... synchronized(synchro){ synchro.notify(); }
Considrons le premier thread qui passe le verrou de synchronisation. Appelons le T1. Imaginons qu'il trouve le boolen peutPasser vrai puisqu'il est le premier. Il le passe donc faux. Il sort ensuite de la section critique verrouille par l'objet synchro. Un autre thread pourra alors entrer dans la section critique pour tester la valeur de peutPasser. Il le trouvera faux et se mettra alors en attente d'un vnement (wait). Ce faisant, il cde la proprit de l'objet synchro. Un autre thread peut alors entrer dans la section critique : lui aussi se mettra en attente car peutPasser est faux. On peut donc avoir plusieurs threads en attente d'un vnement sur l'objet synchro. Revenons au thread T1 qui lui est pass. Il excute la section critique puis va indiquer qu'un autre thread peut maintenant passer. Il le fait avec la squence :
synchronized(synchro){ synchro.notify(); }
Il doit d'abord reprendre possession de l'objet synchro avec l'instruction synchronized. Ca ne doit pas poser de problme puisqu'il est en comptition avec des threads qui, s'ils obtiennent momentanment l'objet synchro doivent l'abandonner par un wait parce qu'ils trouvent peutPasser faux. Donc notre thread T1 va bien finir par obtenir la proprit de l'objet synchro. Ceci fait, il indique par l'opration synchro.notify que l'un des threads bloqus par un synchro.wait doit tre rveill. Ensuite il abandonne de nouveau la proprit de l'objet synchro qui va alors tre
- 289 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
donne l'un des threads en attente. Celui-ci poursuit son excution avec l'instruction qui suit le wait qui l'avait mis en attente. A son tour, il va excuter la section critique et excuter un synchro.notify pour librer un autre thread. Et ainsi de suite. Voyons ce mode de fonctionnement sur l'exemple du comptage dj tudi.
void btnGnrer_actionPerformed(ActionEvent e) { //gnration des threads // on lit le nombre de threads gnrer int nbThreads=0; try{ // lecture du champ contenant le nbre de threads nbThreads=Integer.parseInt(txtAGnrer.getText().trim()); // positif > if(nbThreads<=0) throw new Exception(); }catch(Exception ex){ //erreur txtStatus.setText("Nombre invalide"); // on recommnece txtAGnrer.requestFocus(); return; }//catch // RAZ compteur de tches txtGnrs.setText("0"); // cpteur de tches 0 // 1er thread peut passer peutPasser=true; // on gnre et on lance les threads tches=new Thread[nbThreads]; compteurs=new int[nbThreads]; for(int i=0;i<tches.length;i++){ // on cre le thread i tches[i]=new Thread() { public void run() { synchronise(); } };//thread i // on dfinit son nom tches[i].setName(""+i); // on lance son excution tches[i].start(); }//for }//gnrer
Maintenant, les threads n'excutent plus la mthode incrmente mais la mthode synchronise suivante :
// tape de synchronisation des threads public void synchronise(){ // on demande l'accs la section critique synchronized(synchro){ try{ // peut-on passer ? if(! peutPasser){ System.out.println(Thread.currentThread().getName()+ " en attente"); synchro.wait(); } // on est pass - on interdit aux autres threads de passer peutPasser=false; } catch(Exception e){ txtStatus.setText(""+e); return; }//try }// synchronized // section critique System.out.println(Thread.currentThread().getName()+ " pass"); incrmente(); // on a fini - on libre un ventuel thread bloqu l'entre de la section critique peutPasser=true; System.out.println(Thread.currentThread().getName()+ " termin"); synchronized(synchro){
- 290 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La mthode synchronise a pour but de faire passer les threads un par un. Elle utilise pour cela une variable de synchronisation synchro. La mthode incrmente n'est maintenant plus protge par le mot cl synchronized :
// incremente private void incrmente(){ // on rcupre le n du thread int iThread=0; try{ iThread=Integer.parseInt(Thread.currentThread().getName()); }catch(Exception ex){} // on lit la valeur du compteur de tches try{ compteurs[iThread]=Integer.parseInt(txtGnrs.getText()); } catch (Exception e){} // on l'incrmente compteurs[iThread]++; // on patiente 100 millisecondes - le thread va alors perdre le processeur try{ Thread.sleep(100); } catch (Exception e){ System.exit(0); } // on affiche le nouveau compteur txtGnrs.setText(""); txtGnrs.setText(""+compteurs[iThread]); }// incremente
Soient T0 T4 les 5 threads gnrs par l'application. T0 prend le premier la proprit du verrou synchro et trouve peutPasser vrai. Il met peutPasser faux et passe : c'est le sens du premier message pass. Selon toute vraisemblance, il continue et excute la section critique et notamment la mthode incrmente. Dans celle-ci, il va s'endormir pendant 100 ms (sleep). Il lche donc le processeur. Celuici est accord un autre thread, le thread T1 qui obtient alors la proprit de l'objet synchro. Il dcouvre qu'il ne peut pas passer et se met en attente (wait). Il lche alors la proprit de l'objet synchro ainsi que le processeur. Celui-ci est accord au thread T2 qui subit le mme sort. Pendant les 100 ms d'arrt de T0, les threads T1 T4 sont donc mis en attente. c'est le sens des 4 messages "en attente". Au bout de 100 ms, T0 rcupre le processeur et termine son travail : c'est le sens du message "0 termin". Il libre ensuite l'un des threads bloqus et se termine. Le processeur libr est affect alors un thread disponible : celui qui vient d'tre libr. Ici c'est T1. Le thread T1 entre alors dans la section critique : c'est le sens du message "1 pass". Il fait ce qu'il a faire et va son tour s'arrter 100 ms. Le processeur est alors disponible pour un autre thread mais tous sont en attente d'un vnement : aucun d'eux ne peut prendre le processeur. Au bout de 100 ms, le thread T1 rcupre le processeur et se termine : c'est le sens du message "1 termin". Les Threads T1 T4 vont avoir le mme comportement que T1 : c'est le sens des trois sries de messages : "pass", "termin".
- 291 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 292 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Chaque couche reoit des services de la couche infrieure et offre les siens la couche suprieure. Supposons que deux applications situes sur des machines A et B diffrentes veulent communiquer : elles le font au niveau de la couche Application. Elles n'ont pas besoin de connatre tous les dtails du fonctionnement du rseau : chaque application remet l'information qu'elle souhaite transmettre la couche du dessous : la couche Prsentation. L'application n'a donc connatre que les rgles d'interfaage avec la couche Prsentation. Une fois l'information dans la couche Prsentation, elle est passe selon d'autres rgles la couche Session et ainsi de suite, jusqu' ce que l'information arrive sur le support physique et soit transmise physiquement la machine destination. L, elle subira le traitement inverse de celui qu'elle a subi sur la machine expditeur. A chaque couche, le processus expditeur charg d'envoyer l'information, l'envoie un processus rcepteur sur l'autre machine apartenant la mme couche que lui. Il le fait selon certaines rgles que l'on appelle le protocole de la couche. On a donc le schma de communication final suivant :
- 293 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Physique
Liaison de donnes
Rseau
Transport
Session
Prsentation
Application
Assure la transmission de bits sur un support physique. On trouve dans cette couche des quipements terminaux de traitement des donnes (E.T.T.D.) tels que terminal ou ordinateur, ainsi que des quipements de terminaison de circuits de donnes (E.T.C.D.) tels que modulateur/ dmodulateur, multiplexeur, concentrateur. Les points d'intrt ce niveau sont : le choix du codage de l'information (analogique ou numrique) le choix du mode de transmission (synchrone ou asynchrone). Masque les particularits physiques de la couche Physique. Dtecte et corrige les erreurs de transmission. Gre le chemin que doivent suivre les informations envoyes sur le rseau. On appelle cela le routage : dterminer la route suivre par une information pour qu'elle arrive son destinataire. Permet la communication entre deux applications alors que les couches prcdentes ne permettaient que la communication entre machines. Un service fourni par cette couche peut tre le multiplexage : la couche transport pourra utiliser une mme connexion rseau (de machine machine) pour transmettre des informations appartenant plusieurs applications. On va trouver dans cette couche des services permettant une application d'ouvrir et de maintenir une session de travail sur une machine distante. Elle vise uniformiser la reprsentation des donnes sur les diffrentes machines. Ainsi des donnes provenant d'une machine A, vont tre "habilles" par la couche Prsentation de la machine A, selon un format standard avant d'tre envoyes sur le rseau. Parvenues la couche Prsentation de la machine destinatrice B qui les reconnatra grce leur format standard, elles seront habilles d'une autre faon afin que l'application de la machine B les reconnaisse. A ce niveau, on trouve les applications gnralement proches de l'utilisateur telles que la messagerie lectronique ou le transfert de fichiers.
- 294 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Couche Physique En rseau local, on trouve gnralement une technologie Ethernet ou Token-Ring. Nous ne prsentons ici que la technologie Ethernet. Ethernet C'est le nom donn une technologie de rseaux locaux commutation de paquets invente PARC Xerox au dbut des annes 1970 et normalise par Xerox, Intel et Digital Equipment en 1978. Le rseau est physiquement constitu d'un cble coaxial d'environ 1,27 cm de diamtre et d'une longueur de 500 m au plus. Il peut tre tendu au moyen de rpteurs, deux machines ne pouvant tre spares par plus de deux rpteurs. Le cble est passif : tous les lments actifs sont sur les machines raccordes au cble. Chaque machine est relie au cble par une carte d'accs au rseau comprenant : un transmetteur (transceiver) qui dtecte la prsence de signaux sur le cble et convertit les signaux analogiques en signaux numrique et inversement. un coupleur qui reoit les signaux numriques du transmetteur et les transmet l'ordinateur pour traitement ou inversement.
Les caractristiques principales de la technologie Ethernet sont les suivantes : Capacit de 10 Mgabits/seconde. Topologie en bus : toutes les machines sont raccordes au mme cble
Rseau diffusant - Une machine qui met transfre des informations sur le cble avec l'adresse de la machine destinatrice. Toutes les machines raccordes reoivent alors ces informations et seule celle qui elles sont destines les conserve. La mthode d'accs est la suivante : le transmetteur dsirant mettre coute le cble - il dtecte alors la prsence ou non d'une onde porteuse, prsence qui signifierait qu'une transmission est en cours. C'est la technique CSMA (Carrier Sense Multiple Access). En l'absence de porteuse, un transmetteur peut dcider de transmettre son tour. Ils peuvent tre plusieurs prendre cette dcision. Les signaux mis se mlangent : on dit qu'il y a collision. Le transmetteur dtecte cette situation : en mme temps qu'il met sur le cble, il coute ce qui passe rellement sur celui-ci. S'il dtecte que l'information transitant sur le cble n'est pas celle qu'il a mise, il en dduit qu'il y a collision et il s'arrtera d'mettre. Les autres transmetteurs qui mettaient feront de mme. Chacun reprendra son mission aprs un temps alatoire dpendant de chaque transmetteur. Cette technique est appele CD (Collision Detect). La mthode d'accs est ainsi appele CSMA/CD. un adressage sur 48 bits. Chaque machine a une adresse, appele ici adresse physique, qui est inscrite sur la carte qui la relie au cble. On appelle cet adresse, l'adresse Ethernet de la machine.
Nous trouvons au niveau de cette couche, les protocoles IP, ICMP, ARP et RARP.
- 295 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IP (Internet Protocol)
Dlivre des paquets entre deux noeuds du rseau ICMP(Internet Control Message Protocol) ICMP ralise la communication entre le programme du protocole IP d'une machine et celui d'une autre machine. C'est donc un protocole d'change de messages l'intrieur mme du protocole IP. ARP (Address Resolution Protocol) fait la correspondance adresse Internet machine--> adresse physique machine RARP(Reverse Address Resolution fait la correspondance adresse physique Protocol) machine--> adresse Internet machine Couches Transport/Session Dans cette couche, on trouve les protocoles suivants : TCP (Transmission Control Protocol) UDP (User Datagram Protocol) Assure une remise fiable d'informations entre deux clients Assure une remise non fiable d'informations entre deux clients
Couches Application/Prsentation/Session On trouve ici divers protocoles : TELNET Emulateur de terminal permettant une machine A de se connecter une machine B en tant que termina permet des transferts de fichiers permet des transferts de fichiers permet l'change de messages entre utilisateurs du rseau transforme un nom de machine en adresse Internet de la machine cr par sun MicroSystems, il spcifie une reprsentation standard des donnes, indpendante des machines dfini galement par Sun, c'est un protocole de communication entre applications distantes, indpendant de la couche transport. Ce protocole est important : il dcharge le programmeur de la connaissance des dtails de la couche transport et rend les applications portables. Ce protocole s'appuie sur sur le protocole XDR toujours dfini par Sun, ce protocole permet une machine, de "voir" le systme de fichiers d'une autre machine. Il s'appuie sur le protocole RPC prcdent
FTP (File Transfer Protocol) TFTP (Trivial File Transfer Protocol) SMTP (Simple Mail Transfer protocol) DNS (Domain Name System) XDR (eXternal Data Representation)
passe l'information la couche du dessous et ainsi de suite jusqu' arriver sur le support physique. L, l'information est physiquement transfre la machine destinatrice o elle retraversera les mmes couches, en sens inverse cette fois-ci, jusqu' arriver l'application destinatrice des informations envoyes. Le schma suivant montre le parcours de l'information : Prenons un exemple : l'application FTP, dfinie au niveau de la couche Application et qui permet des transferts de fichiers entre machines. L'application dlivre une suite d'octets transmettre la couche transport. La couche transport dcoupe cette suite d'octets en segments TCP, et ajoute au dbut de chaque segment, le numro de celuici. Les segments sont passs la couche Rseau gouverne par le protocole IP. La couche IP cre un paquet encapsulant le segment TCP reu. En tte de ce paquet, elle place les adresses Internet des machines source et destination. Elle dtermine galement l'adresse physique de la machine destinatrice. Le tout est pass la couche Liaison de donnes & Liaison physique, c'est dire la carte rseau qui couple la machine au rseau physique. L, le paquet IP est encapsul son tour dans une trame physique et envoy son destinataire sur le cble. Sur la machine destinatrice, la couche Liaison de donnes & Liaison physique fait l'inverse : elle dsencapsule le paquet IP de la trame physique et le passe la couche IP. La couche IP vrifie que le paquet est correct : elle calcule une somme, fonction des bits reus (checksum), somme qu'elle doit retrouver dans l'en-tte du paquet. Si ce n'est pas le cas, celui-ci est rejet. Si le paquet est dclar correct, la couche IP dsencapsule le segment TCP qui s'y trouve et le passe audessus la couche transport. La couche transport, couche TCP dans notre exemple, examine le numro du segment afin de restituer le bon ordre des segments. Elle calcule galement une somme de vrification pour le segment TCP. S'il est trouv correct, la couche TCP envoie un accus de rception la machine source, sinon le segment TCP est refus. Il ne reste plus la couche TCP qu' transmettre la partie donnes du segment l'application destinatrice de celles-ci dans la couche du dessus.
- 297 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Selon la taille de ces deux champs, les adresses IP sont divises en 3 classes : classes A, B et C. Classe A L'adresse IP : I1.I2.I3.I4 a la forme R1.N1.N2.N3 o R1 est l'adresse du rseau N1.N2.N3 est l'adresse d'une machine dans ce rseau Plus exactement, la forme d'une adresse IP de classe A est la suivante :
L'adresse rseau est sur 7 bits et l'adresse du noeud sur 24 bits. On peut donc avoir 127 rseaux de classe A, chacun comportant jusqu' 2^24 noeuds. Classe B Ici, l'adresse IP : I1.I2.I3.I4 a la forme R1.R2.N1.N2 o R1.R2 est l'adresse du rseau N1.N2 est l'adresse d'une machine dans ce rseau Plus exactement, la forme d'une adresse IP de classe B est la suivante :
L'adresse du rseau est sur 2 octets (14 bits exactement) ainsi que celle du noeud. On peut donc avoir 2^14 rseaux de classe B chacun comportant jusqu' 2^16 noeuds. Classe C Dans cette classe, l'adresse IP : I1.I2.I3.I4 a la forme R1.R2.R3.N1 o R1.R2.R3 est l'adresse du rseau N1 est l'adresse d'une machine dans ce rseau
- 298 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
L'adresse rseau est sur 3 octets (moins 3 bits) et l'adresse du noeud sur 1 octet. On peut donc avoir 2^21 rseaux de classe C comportant jusqu' 256 noeuds. L'adresse de la machine Lagaffe de la facult des sciences d'Angers tant 193.49.144.1, on voit que l'octet de poids fort vaut 193, c'est dire en binaire 11000001. On en dduit que le rseau est de classe C. Adresses rserves Certaines adresses IP sont des adresses de rseaux plutt que des adresses de noeuds dans le rseau. Ce sont celles, o l'adresse du noeud est mise 0. Ainsi, l'adresse 193.49.144.0 est l'adresse IP du rseau de la Facult des Sciences d'Angers. En consquence, aucun noeud d'un rseau ne peut avoir l'adresse zro. Lorsque dans une adresse IP, l'adresse du noeud ne comporte que des 1, on a alors une adresse de diffusion : cette adresse dsigne tous les noeuds du rseau. Dans un rseau de classe C, permettant thoriquement 2^8=256 noeuds, si on enlve les deux adresses interdites, on n'a plus que 254 adresses autorises.
Dans la trame finale, il y a l'adresse physique des machines source et destination. Comment sont-elles obtenues ? La machine expditrice connaissant l'adresse IP de la machine avec qui elle veut communiquer obtient l'adresse physique de celle-ci en utilisant un protocole particulier appel ARP (Address Resolution Protocol). Elle envoie un paquet d'un type spcial appel paquet ARP contenant l'adresse IP de la machine dont on cherche l'adresse physique. Elle a pris soin galement d'y placer sa propre adresse IP ainsi que son adresse physique. Ce paquet est envoy tous les noeuds du rseau. Ceux-ci reconnaissent la nature spciale du paquet. Le noeud qui reconnat son adresse IP dans le paquet, rpond en envoyant l'expditeur du paquet son adresse physique. Comment le peut-il ? Il a trouv dans le paquet les adresses IP et physique de l'expditeur. L'expditeur reoit donc l'adresse physique qu'il cherchait. Il la stocke en mmoire afin de pouvoir l'utiliser ultrieurement si d'autres paquets sont envoyer au mme destinataire.
L'adresse IP d'une machine est normalement inscrite dans l'un de ses fichiers qu'elle peut donc consulter pour la connatre. Cette adresse peut tre change : il suffit d'diter le fichier. L'adresse physique elle, est inscrite dans une mmoire de la carte rseau et ne peut tre change. Lorsqu'un administrateur dsire d'organiser son rseau diffremment, il peut tre amen changer les adresses IP de tous les noeuds et donc diter les diffrents fichiers de configuration des diffrents noeuds. Cela peut tre
- 299 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
fastidieux et une occasion d'erreurs s'il y a beaucoup de machines. Une mthode consiste ne pas affecter d'adresse IP aux machines : on inscrit alors un code spcial dans le fichier dans lequel la machine devrait trouver son adresse IP. Dcouvrant qu'elle n'a pas d'adresse IP, la machine la demande selon un protocole appel RARP (Reverse Address Resolution Protocol). Elle envoie alors sur un rseau un paquet spcial appel paquet RARP, analogue au paquet ARP prcdent, dans lequel elle met son adresse physique. Ce paquet est envoy tous les noeuds qui reconnaissent alors un paquet RARP. L'un d'entre-eux, appel serveur RARP, possde un fichier donnant la correspondance adresse physique <--> adresse IP de tous les noeuds. Il rpond alors l'expditeur du paquet RARP, en lui renvoyant son adresse IP. Un administrateur dsirant reconfigurer son rseau, n'a donc qu' diter le fichier de correspondances du serveur RARP. Celui-ci doit normalement avoir une adresse IP fixe qu'il doit pouvoir connatre sans avoir utiliser lui-mme le protocole RARP.
L'important est qu'outre les donnes transmettre, le datagramme IP contient les adresses Internet des machines source et destination. Ainsi la machine destinatrice sait qui lui envoie un message. A la diffrence d'une trame de rseau qui a une longueur dtermine par les caractristiques physiques du rseau sur lequel elle transite, la longueur du datagramme IP est elle fixe par le logiciel et sera donc la mme sur diffrents rseaux physiques. Nous avons vu qu'en descendant de la couche rseau dans la couche physique le datagramme IP tait encapsul dans une trame physique. Nous avons donn l'exemple de la trame physique d'un rseau Ethernet :
Les trames physiques circulent de noeud en noeud vers leur destination qui peut ne pas tre sur le mme rseau physique que la machine expditrice. Le paquet IP peut donc tre encapsul successivement dans des trames physiques diffrentes au niveau des noeuds qui font la jonction entre deux rseaux de type diffrent. Il se peut aussi que le paquet IP soit trop grand pour tre encapsul dans une trame physique. Le logiciel IP du noeud o se pose ce problme, dcompose alors le paquet IP en fragments selon des rgles prcises, chacun d'eux tant ensuite envoy sur le rseau physique. Ils ne seront rassembls qu' leur ultime destination.
VII-A-6-a - Le routage
Le routage est la mthode d'acheminement des paquets IP leur destination. Il y a deux mthodes : le routage direct et le routage indirect. Routage direct Le routage direct dsigne l'acheminement d'un paquet IP directement de l'expditeur au destinataire l'intrieur du mme rseau : La machine expditrice d'un datagramme IP a l'adresse IP du destinataire.
- 300 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Elle obtient l'adresse physique de ce dernier par le protocole ARP ou dans ses tables, si cette adresse a dj t obtenue. Elle envoie le paquet sur le rseau cette adresse physique.
Routage indirect Le routage indirect dsigne l'acheminement d'un paquet IP une destination se trouvant sur un autre rseau que celui auquel appartient l'expditeur. Dans ce cas, les parties adresse rseau des adresses IP des machines source et destination sont diffrentes. La machine source reconnat ce point. Elle envoie alors le paquet un noeud spcial appel routeur (router), noeud qui connecte un rseau local aux autres rseaux et dont elle trouve l'adresse IP dans ses tables, adresse obtenue initialement soit dans un fichier soit dans une mmoire permanente ou encore via des informations circulant sur le rseau. Un routeur est attach deux rseaux et possde une adresse IP l'intrieur de ces deux rseaux.
Dans notre exemple ci-dessus : Le rseau n 1 a l'adresse Internet 193.49.144.0 et le rseau n 2 l'adresse 193.49.145.0. A l'intrieur du rseau n 1, le routeur a l'adresse 193.49.144.6 et l'adresse 193.49.145.3 l'intrieur du rseau n 2.
Le routeur a pour rle de mettre le paquet IP qu'il reoit et qui est contenu dans une trame physique typique du rseau n 1, dans une trame physique pouvant circuler sur le rseau n 2. Si l'adresse IP du destinataire du paquet est dans le rseau n 2, le routeur lui enverra le paquet directement sinon il l'enverra un autre routeur, connectant le rseau n 2 un rseau n 3 et ainsi de suite.
VII-A-7 - La couche transport : les protocoles UDP et TCP VII-A-7-a - Le protocole UDP : User Datagram Protocol
Le protocole UDP permet un change non fiable de donnes entre deux points, c'est dire que le bon acheminement d'un paquet sa destination n'est pas garanti. L'application, si elle le souhaite peut grer cela elle-mme, en attendant par exemple aprs l'envoi d'un message, un accus de rception, avant d'envoyer le suivant.
- 301 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Pour l'instant, au niveau rseau, nous avons parl d'adresses IP de machines. Or sur une machine, peuvent coexister en mme temps diffrents processus qui tous peuvent communiquer. Il faut donc indiquer, lors de l'envoi d'un message, non seulement l'adresse IP de la machine destinatrice, mais galement le "nom" du processus destinataire. Ce nom est en fait un numro, appel numro de port. Certains numros sont rservs des applications standard : port 69 pour l'application tftp (trivial file transfer protocol) par exemple. Les paquets grs par le protocole UDP sont appels galement des datagrammes. Ils ont la forme suivante :
Ces datagrammes seront encapsuls dans des paquets IP, puis dans des trames physiques.
- 302 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ce protocole permet un utilisateur d'une machine A du rseau de se connecter sur une machine B (appele souvent machine hte). TELNET mule sur la machine A un terminal dit universel. L'utilisateur se comporte donc comme s'il disposait d'un terminal connect la machine B. Telnet s'appuie sur le protocole TCP. FTP : (File Transfer protocol) Ce protocole permet l'change de fichiers entre deux machines distantes ainsi que des manipulations de fichiers tels que des crations de rpertoire par exemple. Il s'appuie sur le protocole TCP. TFTP: (Trivial File Transfer Control) Ce protocole est une variante de FTP. Il s'appuie sur le protocole UDP et est moins sophistiqu que FTP. DNS : (Domain Name System) Lorsqu'un utilisateur dsire changer des fichiers avec une machine distante, par FTP par exemple, il doit connatre l'adresse Internet de cette machine. Par exemple, pour faire du FTP sur la machine Lagaffe de l'universit d'Angers, il faudrait lancer FTP comme suit : FTP 193.49.144.1 Cela oblige avoir un annuaire faisant la correspondance machine <--> adresse IP. Probablement que dans cet annuaire les machines seraient dsignes par des noms symboliques tels que : machine DPX2/320 de l'universit d'Angers machine Sun de l'ISERPA d'Angers On voit bien qu'il serait plus agrable de dsigner une machine par un nom plutt que par son adresse IP. Se pose alors le problme de l'unicit du nom : il y a des millions de machines interconnectes. On pourrait imaginer qu'un organisme centralis attribue les noms. Ce serait sans doute assez lourd. Le contrle des noms a t en fait distribu dans des domaines. Chaque domaine est gr par un organisme gnralement trs lger qui a toute libert quant au choix des noms de machines. Ainsi les machines en France appartiennent au domaine fr, domaine gr par l'Inria de Paris. Pour continuer simplifier les choses, on distribue encore le contrle : des domaines sont crs l'intrieur du domaine fr. Ainsi l'universit d'Angers appartient au domaine univ-Angers. Le service grant ce domaine a toute libert pour nommer les machines du rseau de l'Universit d'Angers. Pour l'instant ce domaine n'a pas t subdivis. Mais dans une grande universit comportant beaucoup de machines en rseau, il pourrait l'tre. La machine DPX2/320 de l'universit d'Angers a t nomme Lagaffe alors qu'un PC 486DX50 a t nomm liny. Comment rfrencer ces machines de l'extrieur ? En prcisant la hirarchie des domaines auxquelles elles appartiennent. Ainsi le nom complet de la machine Lagaffe sera : Lagaffe.univ-Angers.fr A l'intrieur des domaines, on peut utiliser des noms relatifs. Ainsi l'intrieur du domaine fr et en dehors du domaine univ- Angers, la machine Lagaffe pourra tre rfrence par Lagaffe.univ-Angers Enfin, l'intrieur du domaine univ-Angers, elle pourra tre rfrence simplement par Lagaffe Une application peut donc rfrencer une machine par son nom. Au bout du compte, il faut quand mme obtenir l'adresse Internet de cette machine. Comment cela est-il ralis ? Suposons que d'une machine A, on veuille communiquer avec une machine B.
- 303 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
si la machine B appartient au mme domaine que la machine A, on trouvera probablement son adresse IP dans un fichier de la machine A. sinon, la machine A trouvera dans un autre fichier ou le mme que prcdemment, une liste de quelques serveurs de noms avec leurs adresses IP. Un serveur de noms est charg de faire la correspondance entre un nom de machine et son adresse IP. La machine A va envoyer une requte spciale au premier serveur de nom de sa liste, appel requte DNS incluant donc le nom de la machine recherche. Si le serveur interrog a ce nom dans ses tablettes, il enverra la machine A, l'adresse IP correspondante. Sinon, le serveur trouvera lui aussi dans ses fichiers, une liste de serveurs de noms qu'il peut interroger. Il le fera alors. Ainsi un certain nombre de serveurs de noms vont tre interrogs, pas de faon anarchique mais d'une faon minimiser les requtes. Si la machine est finalement trouve, la rponse redescendra jusqu' la machine A.
XDR : (eXternal Data Representation) Cr par sun MicroSystems, ce protocole spcifie une reprsentation standard des donnes, indpendante des machines. RPC : (Remote Procedure Call) Dfini galement par sun, c'est un protocole de communication entre applications distantes, indpendant de la couche transport. Ce protocole est important : il dcharge le programmeur de la connaissance des dtails de la couche transport et rend les applications portables. Ce protocole s'appuie sur sur le protocole XDR NFS : Network File System Toujours dfini par Sun, ce protocole permet une machine, de "voir" le systme de fichiers d'une autre machine. Il s'appuie sur le protocole RPC prcdent.
VII-A-9 - Conclusion
Nous avons prsent dans cette introduction quelques grandes lignes des protocoles Internet. Pour approfondir ce domaine, on pourra lire l'excellent livre de Douglas Comer : Titre TCP/IP : Architecture, Protocoles, Applications. Auteur Douglas COMER Editeur InterEditions
- 304 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
byte [] getAddress() String getHostAddress() String getHostName() String toString() InetAddress getByName(String Host)
InetAddress getLocalHost()
donne les 4 octets de l'adresse IP de l'instance InetAddress courante donne l'adresse IP de l'instance InetAddress courante donne le nom Internet de l'instance InetAddress courante donne l'identit adresse IP/ nom internet de l'instance InetAddress courante cre l'instance InetAddress de la machine dsigne par Host. Gnre une exception si Host est inconnu. Host peut tre le nom internet d'une machine ou son adresse IP sous la forme I1.I2.I3.I4 cre l'instance InetAddress de la machine sur laquelle s'excute le programme contenant cette instruction.
Chaque machine a une adresse IP interne qui est 127.0.0.1. Lorsqu'un programme utilise cette adresse rseau, il utilise la machine sur laquelle il fonctionne. L'intrt de cette adresse est qu'elle ne ncessite pas de carte rseau. On peut donc tester des programmes rseau sans tre connect un rseau. Une autre faon de dsigner la machine locale est d'utiliser le nom localhost.
- 305 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// on rcupre l'argument if(arg.length==0) nomMachine="localhost"; else nomMachine=arg[0]; // on tente d'obtenir l'adresse de la machine try{ InetAddress adresse=InetAddress.getByName(nomMachine); System.out.println("IP : "+ adresse.getHostAddress()); System.out.println("nom : "+ adresse.getHostName()); System.out.println("identit : "+ adresse); } catch (UnknownHostException e){ System.out.println ("Erreur getByName : "+e); }// fin try }// fin main }// fin class
Lorsque une application AppA d'une machine A veut communiquer avec une application AppB d'une machine B de l'Internet, elle doit connatre plusieurs choses : l'adresse IP ou le nom de la machine B
- 306 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
le numro du port avec lequel travaille l'application AppB. En effet la machine B peut supporter de nombreuses applications qui travaillent sur l'Internet. Lorsqu'elle reoit des informations provenant du rseau, elle doit savoir quelle application sont destines ces informations. Les applications de la machine B ont accs au rseau via des guichets appels galement des ports de communication. Cette information est contenue dans le paquet reu par la machine B afin qu'il soit dlivr la bonne application. les protocoles de communication compris par la machine B. Dans notre tude, nous utiliserons uniquement les protocoles TCP-IP. le protocole de dialogue accept par l'application AppB. En effet, les machines A et B vont se "parler". Ce qu'elles vont dire va tre encapsul dans les protocoles TCP-IP. Nammoins, lorsqu'au bout de la chane, l'application AppB va recevoir l'information envoye par l'applicaton AppA, il faut qu'elle soit capable de l'interprter. Ceci est analogue la situation o deux personnes A et B communiquent par tlphone : leur dialogue est transport par le tlphone. La parole va tre code sous forme de signaux par le tlphone A, transporte par des lignes tlphoniques, arrive au tlphone B pour y tre dcode. La personne B entend alors des paroles. C'est l qu'intervient la notion de protocole de dialogue : si A parle franais et que B ne comprend pas cette langue, A et B ne pourront dialoguer utilement.
Aussi les deux applications communicantes doivent -elles tre d'accord sur le type de dialogue qu'elles vont adopter. Ainsi par exemple, le dialogue avec un service ftp n'est pas le mme qu'avec un service pop : ces deux services n'acceptent pas les mmes commandes. Elles ont un protocole de dialogue diffrent.
- 307 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
entre la machine A qu'on appelle machine cliente et la machine B qu'on appelle machine serveur. L'un des deux partenaires fermera la connexion.
Le programme serveur traite diffremment la demande de connexion initiale d'un client de ses demandes ultrieures visant obtenir un service. Le programme n'assure pas le service lui-mme. S'il le faisait, pendant la dure du service il ne serait plus l'coute des demandes de connexion et des clients ne seraient alors pas servis. Il procde donc autrement : ds qu'une demande de connexion est reue sur le port d'coute puis accepte, le serveur cre une tche charge de rendre le service demand par le client. Ce service est rendu sur un autre port de la machine serveur appel port de service. On peut ainsi servir plusieurs clients en mme temps. Une tche de service aura la structure suivante :
tant que le service n'a pas t rendu totalement attendre une demande sur le port de service lorsqu'il y en a une, laborer la rponse transmettre la rponse via le port de service fin tant que librer le port de service
- 308 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public Socket(String host, int port) public int getLocalPort() public int getPort() public InetAddress getLocalAdress() public InetAddress getInetAdress() public InputStream getInputStream() public OutputStream getOutputStream() public void shutdownInput() public void shutdownOutput() public void close() public String toString()
ouvre une connexion distante avec le port port de la machine host rend le n du port local utilis par la socket rend le n du port distant auquel la socket est connecte rend l'adresse InetAddress locale laquelle la socket est lie rend l'adresse InetAddress distante laquelle la socket est lie rend un flux d'entre permettant de lire les donnes envoyes par le partenaire distant rend un flux de sortie permettant d'envoyer des donnes au partenaire distant ferme le flux d'entre de la socket ferme le flux de sortie de la socket ferme la socket et ses flux d'E/S rend une chane de caractres "reprsentant" la socket
Le constructeur
public Socket(String host, int port);
cre une socket et la connecte la machine host sur le port port. Ce constructeur gnre une exception dans diffrents cas : mauvaise adresse mauvais port demande refuse ...
Si la demande de connexion russit, le client se voit localement attribuer un port pour communiquer avec la machine B. Une fois la connexion tablie, on peut connatre ce port avec la mthode :
public int getLocalPort();
- 309 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Si la connexion russit, nous avons vu que, de son ct, le serveur fait assurer le service par une autre tche travaillant sur un port dit de service. Ce numro de port peut tre connu avec la mthode :
public int getPort();
Tout ce qui sera envoy dans ce flux sera reu sur le port de service de la machine serveur. De nombreuses applications ont un dialogue sous forme de lignes de texte termines par un passage a ligne. Aussi la mthode println est-elle bien pratique dans ces cas l. On transforme alors le flux de sortie OutputStream en flux PrintWriter qui possde la mthode println. L'criture peut gnrer une exception.
Tout ce qui sera lu dans ce flux vient du port de service de la machine serveur. Pour les applications ayant un dialogue sous forme de lignes de texte termines par un passage la ligne on aimera utiliser la mthode readLine. Pour cela on transforme le flux d'entre InputStream en flux BufferedReader qui possde la mthode readLine(). La lecture peut gnrer une exception.
La mthode peut gnrer une exception. Les ressources utilises, notamment le port rseau, sont libres.
- 310 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// on lit la rponse rponse=in.readLine(); // on traite la rponse ... } // c'est fini sClient.close(); } catch(Exception e){ // on gre l'exception #. }
Nous n'avons pas cherch grer les diffrents types d'exception gnrs par le constructeur Socket ou les mthodes readline, getInputStream, getOutputStream, close pour ne pas compliquer l'exemple. Tout a t runi dans une seule exception.
port est le port d'coute du service : celui o les clients adressent leurs demandes de connexion. count est la taille maximale de la file d'attente du service (50 par dfaut), celle-ci stockant les demandes de connexion des clients auxquelles le serveur n'a pas encore rpondu. Lorsque la file d'attente est pleine, les demandes de connexion qui arrivent sont rejetes. Les deux constructeurs gnrent une exception.
- 311 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cette mthode rend une instance de Socket : c'est la socket de service, celle travers laquelle le service sera rendu, le plus souvent par une autre tche. La mthode peut gnrer une exception
de la classe ServerSocket. Cela libre les ressources occupes, notamment le port d'coute. La mthode peut gnrer une exception.
- 312 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// on traite l'exception # }
- 313 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
public class serveurEcho{ public final static String syntaxe="Syntaxe : serveurEcho port"; public final static int nbConnexions=2; // programme principal public static void main (String arg[]){ // y-a-t-il un argument if(arg.length != 1) erreur(syntaxe,1); // cet argument doit tre entier >0 int port=0; boolean erreurPort=false; Exception E=null; try{ port=Integer.parseInt(arg[0]); }catch(Exception e){ E=e; erreurPort=true; } erreurPort=erreurPort || port <=0; if(erreurPort) erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2); // on cre la socket d'coute ServerSocket ecoute=null; try{ ecoute=new ServerSocket(port,nbConnexions); } catch (Exception e){ erreur("Erreur lors de la cration de la socket d'coute ("+e+")",3); } // suivi System.out.println("Serveur d'cho lanc sur le port " + port); // boucle de service boolean serviceFini=false; Socket service=null; while (! serviceFini){ // attente d'un client try{ service=ecoute.accept(); } catch (IOException e){ e rreur("Erreur lors de l'acceptation d'une connexion ("+e+")",4); } // on identifie la liaison try{ System.out.println("Client ["+identifie(service.getInetAddress())+","+ service.getPort()+"] connect au serveur [" + identifie (InetAddress.getLocalHost()) + "," + service.getLocalPort() + "]"); } catch (Exception e) { erreur("identification liaison",1); } // le service est assur par une autre tche new traiteClientEcho(service).start(); }// fin while }// fin main // affichage des erreurs public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); } // identifie private static String identifie(InetAddress Host){ // identification de Host String ipHost=Host.getHostAddress(); String nomHost=Host.getHostName(); String idHost;
- 314 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
if (nomHost == null) idHost=ipHost; else idHost=ipHost+","+nomHost; return idHost; } }// fin class // assure le service un client du serveur d'cho class traiteClientEcho extends Thread{ private Socket service; // socket de service private BufferedReader in; // flux d'entre private PrintWriter out; // flux de sortie // constructeur public traiteClientEcho(Socket service){ this.service=service; } // mthode run public void run(){ // cration des flux d'entre et de sortie try{ in=new BufferedReader(new InputStreamReader(service.getInputStream())); } catch (IOException e){ erreur("Erreur lors de la cration du flux dentre de la socket de service ("+e+")",1); }// fin try try{ out=new PrintWriter(service.getOutputStream(),true); } catch (IOException e){ erreur("Erreur lors de la cration du flux de sortie de la socket de service ("+e+")",1); }// fin try // l'identification de la liaison est envoye au client try{ out.println("Client ["+identifie(service.getInetAddress())+","+ service.getPort()+"] connect au serveur [" + identifie (InetAddress.getLocalHost()) + "," + service.getLocalPort() + "]"); } catch (Exception e) { erreur("identification liaison",1); } // boucle lecture demande/criture rponse String demande,reponse; try{ // le service s'arrte lorsque le client envoie une marque de fin de fichier while ((demande=in.readLine())!=null){ // cho de la demande reponse="["+demande+"]"; out.println(reponse); // le service s'arrte lorsque le client envoie "fin" if(demande.trim().toLowerCase().equals("fin")) break; }// fin while } catch (IOException e){ erreur("Erreur lors des changes client/serveur ("+e+")",3); }// fin try // on ferme la socket try{ service.close(); } catch (IOException e){ erreur("Erreur lors de la fermeture de la socket de service ("+e+")",2); }// fin try }// fin run // affichage des erreurs public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); }// fin erreur // identifie private String identifie(InetAddress Host){ // identification de Host
- 315 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String ipHost=Host.getHostAddress(); String nomHost=Host.getHostName(); String idHost; if (nomHost == null) idHost=ipHost; else idHost=ipHost+","+nomHost; return idHost; } }// fin class
Les deux classes ncessaires au service ont t runies dans un mme fichier source. Seule l'une d'entre-elles, celle qui a la fonction main a l'attribut public. La structure du serveur est conforme l'architecture gnrale des serveurs tcp. On y ajout une mthode (identifie) permettant d'identifier la liaison entre le serveur et un client. Voici quelques rsultats : Le serveur est lanc par la commande java serveurEcho 187 Il affiche alors dans la fentre de contrle, le message suivant :
Serveur d'cho lanc sur le port 187
Pour tester ce serveur, on utilise le programme telnet qui existe la fois sous Unix et Windows. Telnet est un client tcp universel adapt tous les serveurs qui acceptent des lignes de texte termines par une marque de fin de ligne dans leur dialogue. C'est le cas de notre serveur d'cho. On lance un premier client telnet sous windows (2000 dans cet exemple) en tapant telnet dans une fentre DOS :
DOS>telnet Microsoft (R) Windows 2000 (TM) version 5.00 (numro 2195) Client Telnet Microsoft Client Telnet numro 5.00.99203.1 Le caractre d'chappement est 'CTRL+$' Microsoft Telnet> help Les commandes peuvent tre abrges. Les commandes prises en charge sont : close display open quit set status unset ? ou help ferme la connexion en cours affiche les paramtres d'opration ouvre une connexion un site quitte telnet dfinit les options (entrez 'set ?' pour afficher la liste) affiche les informations d'tat annule les options (entrez 'unset ?' pour afficher la liste) affiche des informations d'aide
Microsoft Telnet> set ? NTLM Active l'authentification NTLM. LOCAL_ECHO Active l'cho local. TERM x (o x est ANSI, VT100, VT52 ou VTNT)) CRLF Envoi de CR et de LF Microsoft Telnet> set local_echo Microsoft Telnet> open localhost 187
Le programme telnet ne fait, par dfaut, pas l'cho des commandes que l'on tape au clavier. Pour avoir cet cho on met la commande :
Microsoft Telnet> set local_echo
- 316 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Pour ouvrir une connexion avec le serveur, en lui prcisant le port du service d'cho (187) et l'adresse de la machine sur lequel il se trouve (localhost) on met la commande :
Microsoft Telnet> open localhost 187
Ici tahe et localhost dsignent la mme machine. Dans la fentre du client telnet, on peut taper des lignes de texte. Le serveur les renvoie en cho :
Client [127.0.0.1,tahe,1059] connect au serveur [127.0.0.1,tahe,187] je suis l [je suis l] au revoir [au revoir]
On notera que le port du client (1059) est bien dtect mais que le port de service (187) est identique au port d'coute (187), ce qui est inattendu. On pouvait en effet s'attendre obtenir le port de la socket de service et non le port d'coute. Il faudrait vrifier si on obtient les mmes rsultats sous Unix. Maintenant, lanons un second client telnet. La fentre du serveur devient :
Serveur d'cho lanc sur le port 187 Client [127.0.0.1,tahe,1059] connect au serveur [127.0.0.1,tahe,187] Client [127.0.0.1,tahe,1060] connect au serveur [127.0.0.1,tahe,187]
Dans la fentre du second client, on peut aussi taper des lignes de texte :
Client [127.0.0.1,tahe,1060] connect au serveur [127.0.0.1,tahe,187] ligne1 [ligne1] ligne2 [ligne2]
On voit ainsi que le serveur d'cho peut servir plusieurs clients la fois. Les clients telnet peuvent tre termins en fermant la fentre Dos dans laquelle ils s'excutent.
- 317 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// y-a-t-il deux arguments if(arg.length != 2) erreur(syntaxe,1); // le premier argument doit tre le nom d'une machine existante String machine=arg[0]; InetAddress serveurAddress=null; try{ serveurAddress=InetAddress.getByName(machine); } catch (Exception e){ erreur(syntaxe+"\nMachine "+machine+" inaccessible (" + e +")",2); } // le port doit tre entier >0 int port=0; boolean erreurPort=false; Exception E=null; try{ port=Integer.parseInt(arg[1]); }catch(Exception e){ E=e; erreurPort=true; } erreurPort=erreurPort || port <=0; if(erreurPort) erreur(syntaxe+"\nPort incorrect ("+E+")",3); // on se connecte au serveur Socket sClient=null; try{ sClient=new Socket(machine,port); } catch (Exception e){ erreur("Erreur lors de la cration de la socket de communication ("+e+")",4); } // on identifie la liaison try{ System.out.println("Client : Client ["+identifie(InetAddress.getLocalHost())+","+ sClient.getLocalPort()+"] connect au serveur [" + identifie (sClient.getInetAddress()) + "," + sClient.getPort() + "]"); } catch (Exception e) { erreur("identification liaison ("+e+")",5); } // cration du flux de lecture des lignes tapes au clavier BufferedReader IN=null; try{ IN=new BufferedReader(new InputStreamReader(System.in)); } catch (Exception e){ erreur("Cration du flux d'entre clavier ("+e+")",6); } // cration du flux d'entre associe la socket client BufferedReader in=null; try{ in=new BufferedReader(new InputStreamReader(sClient.getInputStream())); } catch (Exception e){ erreur("Cration du flux d'entre de la socket client("+e+")",7); } // cration du flux de sortie associe la socket client PrintWriter out=null; try{ out=new PrintWriter(sClient.getOutputStream(),true); } catch (Exception e){ erreur("Cration du flux de sortie de la socket ("+e+")",8); } // boucle demandes - rponses boolean serviceFini=false; String demande=null; String reponse=null;
- 318 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// on lit le message envoy par le serveur juste aprs la connexion try{ reponse=in.readLine(); } catch (IOException e){ erreur("Lecture rponse ("+e+")",4); } // affichage rponse System.out.println("Serveur : " +reponse); while (! serviceFini){ // lecture d'une ligne tape au clavier System.out.print("Client : "); try{ demande=IN.readLine(); } catch (Exception e){ erreur("Lecture ligne ("+e+")",9); } // envoi demande sur le rseau try{ out.println(demande); } catch (Exception e){ erreur("Envoi demande ("+e+")",10); } // attente/lecture rponse try{ reponse=in.readLine(); } catch (IOException e){ erreur("Lecture rponse ("+e+")",4); } // affichage rponse System.out.println("Serveur : " +reponse); // est-ce fini ? if(demande.trim().toLowerCase().equals("fin")) serviceFini=true; } // c'est fini try{ sClient.close(); } catch(Exception e){ erreur("Fermeture socket ("+e+")",11); } }// main // affichage des erreurs public static void erreur(String msg, int exitCode){ System.err.println(msg); System.exit(exitCode); } // identifie private static String identifie(InetAddress Host){ // identification de Host String ipHost=Host.getHostAddress(); String nomHost=Host.getHostName(); String idHost; if (nomHost == null) idHost=ipHost; else idHost=ipHost+","+nomHost; return idHost; } }// fin class
La structure de ce client est conforme l'architecture gnrale des clients tcp. Ici, on a gr les diffrentes exceptions possibles, une par une, ce qui alourdit le programme. Voici les rsultats obtenus lorsqu'on teste ce client :
Client : Client [127.0.0.1,tahe,1045] connect au serveur [127.0.0.1,localhost,187] Serveur : Client [127.0.0.1,localhost,1045] connect au serveur [127.0.0.1,tahe,187] Client : 123 Serveur : [123] Client : abcd Serveur : [abcd] Client : je suis l
- 319 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les lignes commenant par Client sont les lignes envoyes par le client et celles commenant par Serveur sont celles que le serveur a renvoyes en cho.
Pourquoi deux threads alors que dans l'application prcdente ce besoin ne s'tait pas fait ressentir ? Dans cette dernire, le protocole du dialogue tait connu : le client envoyait une seule ligne et le serveur rpondait par une seule ligne. Chaque service a son protocole particulier et on trouve galement les situations suivantes : le client doit envoyer plusieurs lignes de texte avant d'avoir une rponse la rponse d'un serveur peut comporter plusieurs lignes de texte
Aussi la boucle envoi d'une unique ligne au serveur - rception d'une unique ligne envoye par le serveur ne convientelle pas toujours. On va donc crer deux boucles dissocies : une boucle de lecture des commandes tapes au clavier pour tre envoyes au serveur. L'utilisateur signalera la fin des commandes avec le mot cl fin. une boucle de rception et d'affichage des rponses du serveur. Celle-ci sera une boucle infinie qui ne sera interrompue que par la fermeture du flux rseau par le serveur ou par l'utilisateur au clavier qui tapera la commande fin.
Pour avoir ces deux boucles dissocies, il nous faut deux threads indpendants. Montrons un exemple d'exccution o notre client tcp gnrique se connecte un service SMTP (SendMail Transfer Protocol). Ce service est responsable de l'acheminement du courrier lectronique leurs destinataires. Il fonctionne sur le port 25 et a un protocole de dialogue de type changes de lignes de texte.
Dos>java clientTCPgenerique istia.univ-angers.fr 25 Commandes : <-- 220 istia.univ-angers.fr ESMTP Sendmail 8.11.6/8.9.3; Mon, 13 May 2002 08:37:26 +0200 help <-- 502 5.3.0 Sendmail 8.11.6 -- HELP not implemented mail from: machin@univ-angers.fr <-- 250 2.1.0 machin@univ-angers.fr... Sender ok rcpt to: serge.tahe@istia.univ-angers.fr <-- 250 2.1.5 serge.tahe@istia.univ-angers.fr... Recipient ok data <-- 354 Enter mail, end with "." on a line by itself Subject: test ligne1 ligne2 ligne3 . <-- 250 2.0.0 g4D6bks25951 Message accepted for delivery quit <-- 221 2.0.0 istia.univ-angers.fr closing connection
- 320 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
[fin du thread de lecture des rponses du serveur] fin [fin du thread d'envoi des commandes au serveur]
Commentons ces changes client-serveur : le service SMTP envoie un message de bienvenue lorsqu'un client se connecte lui :
<-- 220 istia.univ-angers.fr ESMTP Sendmail 8.11.6/8.9.3; Mon, 13 May 2002 08:37:26 +0200
certains services ont une commande help donnant des indications sur les commandes utilisables avec le service. Ici ce n'est pas le cas. Les commandes SMTP utilises dans l'exemple sont les suivantes : o mail from: expditeur, pour indiquer l'adresse lectronique de l'expditeur du message o rcpt to: destinataire, pour indiquer l'adresse lectronique du destinataire du message. S'il y a plusieurs destinataires, on r-met autant de fois que ncessaire la commande rcpt to: pour chacun des destinataires. o data qui signale au serveur SMTP qu'on va envoyer le message. Comme indiqu dans la rponse du serveur, celui-ci est une suite de lignes termine par une ligne contenant le seul caractre point. Un message peut avoir des enttes spars du corps du message par une ligne vide. Dans notre exemple, nous avons mis un sujet avec le mot cl Subject: une fois le message envoy, on peut indiquer au serveur qu'on a termin avec la commande quit. Le serveur ferme alors la connexion rseau. Le thread de lecture peut dtecter cet vnement et s'arrter. l'utilisateur tape alors fin au clavier pour arrter galement le thread de lecture des commandes tapes au clavier.
On remarquera que le service SMTP ne peut dtecter si un expditeur est valide ou non. Aussi ne peut-on jamais faire confiance au champ from d'un message. Ici l'expditeur machin@univ-angers.fr n'existait pas. Ce client tcp gnrique peut nous permettre de dcouvrir le protocole de dialogue de services internet et partir de l construire des classes spcialises pour des clients de ces services. Dcouvrons le protocole de dialogue du service POP (Post Office Protocol) qui permet de retrouver ses mls stocks sur un serveur. Il travaille sur le port 110.
Dos> java clientTCPgenerique istia.univ-angers.fr 110 Commandes : <-- +OK Qpopper (version 4.0.3) at istia.univ-angers.fr starting. help <-- -ERR Unknown command: "help". user st <-- +OK Password required for st. pass monpassword <-- +OK st has 157 visible messages (0 hidden) in 11755927 octets. list <-- +OK 157 visible messages (11755927 octets) <-- 1 892847 <-- 2 171661 ... <-- 156 2843 <-- 157 2796 <-- . retr 157 <-- +OK 2796 octets
- 321 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
<-- Received: from lagaffe.univ-angers.fr (lagaffe.univ-angers.fr [193.49.144.1]) <-- by istia.univ-angers.fr (8.11.6/8.9.3) with ESMTP id g4D6wZs26600; <-- Mon, 13 May 2002 08:58:35 +0200 <-- Received: from jaume ([193.49.146.242]) <-- by lagaffe.univ-angers.fr (8.11.1/8.11.2/GeO20000215) with SMTP id g4D6wSd37691; <-- Mon, 13 May 2002 08:58:28 +0200 (CEST) ... <-- -----------------------------------------------------------------------<-- NOC-RENATER2 Tl. : 0800 77 47 95 <-- Fax : (+33) 01 40 78 64 00 , Email : noc-r2@cssi.renater.fr <-- -----------------------------------------------------------------------<-<-- . quit <-- +OK Pop server at istia.univ-angers.fr signing off. [fin du thread de lecture des rponses du serveur] fin [fin du thread d'envoi des commandes au serveur]
Les principales commandes sont les suivantes : user login, o on donne son login sur la machine qui dtient nos mls pass password, o on donne le mot de passe associ au login prcdent list, pour avoir la liste des messages sous la forme numro, taille en octets retr i, pour lire le message n i quit, pour arrter le dialogue.
Dcouvrons maintenant le protocole de dialogue entre un client et un serveur Web qui lui travaille habituellement sur le port 80 :
Dos> java clientTCPgenerique istia.univ-angers.fr 80 Commandes : GET /index.html HTTP/1.0 <-- HTTP/1.1 200 OK <-- Date: Mon, 13 May 2002 07:30:58 GMT <-- Server: Apache/1.3.12 (Unix) (Red Hat/Linux) PHP/3.0.15 mod_perl/1.21 <-- Last-Modified: Wed, 06 Feb 2002 09:00:58 GMT <-- ETag: "23432-2bf3-3c60f0ca" <-- Accept-Ranges: bytes <-- Content-Length: 11251 <-- Connection: close <-- Content-Type: text/html <-<-- <html> <-<-- <head> <-- <meta http-equiv="Content-Type" <-- content="text/html; charset=iso-8859-1"> <-- <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> <-- <title>Bienvenue a l'ISTIA - Universite d'Angers</title> <-- </head> .... <-- face="Verdana"> - Dernire mise jour le <b>10 janvier 2002</b></font></p> <-- </body> <-- </html> <-[fin du thread de lecture des rponses du serveur] fin [fin du thread d'envoi des commandes au serveur]
- 322 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ce n'est qu'aprs avoir reu la ligne vide que le serveur Web rpond. Dans l'exemple nous n'avons utilis qu'une commande :
GET /index.html HTTP/1.0
qui demande au serveur l'URL /index.html et indique qu'il travaille avec le protocole HTTP version 1.0. La version la plus rcente de ce protocole est 1.1. L'exemple montre que le serveur a rpondu en renvoyant le contenu du fichier index.html puis qu'il a ferm la connexion puisqu'on voit le thread de lecture des rponses se terminer. Avant d'envoyer le contenu du fichier index.html, le serveur web a envoy une srie d'enttes termine par une ligne vide :
<-<-<-<-<-<-<-<-<-<-<-HTTP/1.1 200 OK Date: Mon, 13 May 2002 07:30:58 GMT Server: Apache/1.3.12 (Unix) (Red Hat/Linux) PHP/3.0.15 mod_perl/1.21 Last-Modified: Wed, 06 Feb 2002 09:00:58 GMT ETag: "23432-2bf3-3c60f0ca" Accept-Ranges: bytes Content-Length: 11251 Connection: close Content-Type: text/html <html>
La ligne <html> est la premire ligne du fichier /index.html. Ce qui prcde s'appelle des enttes HTTP (HyperText Transfer Protocol). Nous n'allons pas dtailler ici ces enttes mais on se rappellera que notre client gnrique y donne accs, ce qui peut tre utile pour les comprendre. La premire ligne par exemple :
<-- HTTP/1.1 200 OK
indique que le serveur Web contact comprend le protocole HTTP/1.1 et qu'il a bien trouv le fichier demand (200 OK), 200 tant un code de rponse HTTP. Les lignes
<-- Content-Length: 11251 <-- Connection: close <-- Content-Type: text/html
disent au client qu'il va recevoir 11251 octets reprsentant du texte HTML (HyperText Markup Language) et qu' la fin de l'envoi, la connexion sera ferme. On a donc l un client tcp trs pratique. Il fait sans doute moins que le programme telnet que nous avons utilis prcdemment mais il tait intressant de l'crire nous-mmes. Le programme du client tcp gnrique est le suivant :
// paquetages imports import java.io.*; import java.net.*; public class clientTCPgenerique{ // // // // // // // // reoit en paramtre les caractristiques d'un service sous la forme serveur port se connecte au service cre un thread pour lire des commandes tapes au clavier celles-ci seront envoyes au serveur cre un thread pour lire les rponses du serveur celles-ci seront affiches l'cran le tout se termine avec la commande fin tape au clavier
// variable d'instance private static Socket client; public static void main(String[] args){
- 323 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// syntaxe final String syntaxe="pg serveur port"; // nombre d'arguments if(args.length != 2) erreur(syntaxe,1); // on note le nom du serveur String serveur=args[0]; // le port doit tre entier >0 int port=0; boolean erreurPort=false; Exception E=null; try{ port=Integer.parseInt(args[1]); }catch(Exception e){ E=e; erreurPort=true; } erreurPort=erreurPort || port <=0; if(erreurPort) erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2); client=null; // il peut y avoir des problmes try{ // on se connecte au service client=new Socket(serveur,port); }catch(Exception ex){ // erreur erreur("Impossible de se connecter au service ("+ serveur +","+port+"), erreur : "+ex.getMessage(),3); // fin return; }//catch // on cre les threads de lecture/criture new ClientSend(client).start(); new ClientReceive(client).start(); // fin thread main return; }// main // affichage des erreurs public static void erreur(String msg, int exitCode){ // affichage erreur System.err.println(msg); // arrt avec erreur System.exit(exitCode); }//erreur }//classe class ClientSend extends Thread { // classe charge de lire des commandes tapes au clavier // et de les envoyer un serveur via un client tcp pass en paramtre private Socket client; // le client tcp // constructeur public ClientSend(Socket client){ // on note le client tcp this.client=client; }//constructeur // mthode Run du thread public void run(){ // donnes locales PrintWriter OUT=null; BufferedReader IN=null;
- 324 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String commande=null; // commande lue au clavier // gestion des erreurs try{ // cration du flux d'criture rseau OUT=new PrintWriter(client.getOutputStream(),true); // cration du flux d'entre clavier IN=new BufferedReader(new InputStreamReader(System.in)); // boucle saisie-envoi des commandes System.out.println("Commandes : "); while(true){ // lecture commande tape au clavier commande=IN.readLine().trim(); // fini ? if (commande.toLowerCase().equals("fin")) break; // envoi commande au serveur OUT.println(commande); // commande suivante }//while }catch(Exception ex){ // erreur System.err.println("Envoi : L'erreur suivante s'est produite : " + ex.getMessage()); }//catch // fin - on ferme les flux try{ OUT.close();client.close(); }catch(Exception ex){} // on signale la fin du thread System.out.println("[Envoi : fin du thread d'envoi des commandes au serveur]"); }//run }//classe class ClientReceive extends Thread{ // classe charge de lire les lignes de texte destines un // client tcp pass en paramtre private Socket client; // le client tcp // constructeur public ClientReceive(Socket client){ // on note le client tcp this.client=client; }//constructeur // mthode Run du thread public void run(){ // donnes locales BufferedReader IN=null; // flux lecture rseau String rponse=null; // rponse serveur // gestion des erreurs try{ // cration du flux lecture rseau IN=new BufferedReader(new InputStreamReader(client.getInputStream())); // boucle lecture lignes de texte du flux IN while(true){ // lecture flux rseau rponse=IN.readLine(); // flux ferm ? if(rponse==null) break; // affichage System.out.println("<-- "+rponse); }//while }catch(Exception ex){ // erreur System.err.println("Rception : L'erreur suivante s'est produite : " + ex.getMessage()); }//catch // fin - on ferme les flux try{ IN.close();client.close(); }catch(Exception ex){} // on signale la fin du thread
- 325 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le programme est lanc par : java serveurTCPgenerique portEcoute, o portEcoute est le port sur lequel les clients doivent se connecter. Le service au client sera assur par deux threads : un thread se consacrant exclusivement la lecture des lignes de texte envoyes par le client un thread se consacrant exclusivement la lecture des rponses tapes au clavier par l'utilisateur. Celui-ci signalera par la commande fin qu'il clt la connexion avec le client.
Le serveur cre deux threads par client. S'il y a n clients, il y aura 2n threads actifs en mme temps. Le serveur lui ne s'arrte jamais sauf par un Ctrl-C tap au clavier par l'utilisateur. Voyons quelques exemples. Le serveur est lanc sur le port 100 et on utilise le client gnrique pour lui parler. La fentre du client est la suivante :
E:\data\serge\MSNET\c#\rseau\client tcp gnrique> java clientTCPgenerique localhost 100 Commandes : commande 1 du client 1 <-- rponse 1 au client 1 commande 2 du client 1 <-- rponse 2 au client 1 fin L'erreur suivante s'est produite : Impossible de lire les donnes de la connexion de transport. [fin du thread de lecture des rponses du serveur] [fin du thread d'envoi des commandes au serveur]
Les lignes commenant par <-- sont celles envoyes du serveur au client, les autres celles du client vers le serveur. La fentre du serveur est la suivante :
Dos> java serveurTCPgenerique 100 Serveur gnrique lanc sur le port 100 Thread de lecture des rponses du serveur au client 1 lanc 1 : Thread de lecture des demandes du client 1 lanc <-- commande 1 du client 1 rponse 1 au client 1 1 : <-- commande 2 du client 1 rponse 2 au client 1 1 : [fin du Thread de lecture des demandes du client 1] fin [fin du Thread de lecture des rponses du serveur au client 1]
Les lignes commenant par <-- sont celles envoyes du client au serveur. Les lignes N : sont les lignes envoyes du serveur au client n N. Le serveur ci-dessus est encore actif alors que le client 1 est termin. On lance un second client pour le mme serveur :
Dos> java clientTCPgenerique localhost 100 Commandes : commande 3 du client 2 <-- rponse 3 au client 2 fin L'erreur suivante s'est produite : Impossible de lire les donnes de la connexion de transport.
- 326 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
[fin du thread de lecture des rponses du serveur] [fin du thread d'envoi des commandes au serveur]
Simulons maintenant un serveur web en lanant notre serveur gnrique sur le port 88 :
Dos> java serveurTCPgenerique 88 Serveur gnrique lanc sur le port 88
Prenons maintenant un navigateur et demandons l'URL http://localhost:88/exemple.html. Le navigateur va alors se connecter sur le port 88 de la machine localhost puis demander la page /exemple.html :
On dcouvre ainsi les enttes HTTP envoys par le navigateur. Cela nous permet de dcouvrir peu peu le protocole HTTP. Lors d'un prcdent exemple, nous avions cr un client Web qui n'envoyait que la seule commande GET. Cela avait t suffisant. On voit ici que le navigateur envoie d'autres informations au serveur. Elles ont pour but d'indiquer au serveur quel type de client il a en face de lui. On voit aussi que les enttes HTTP se terminent par une ligne vide.
- 327 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Elaborons une rponse notre client. L'utilisateur au clavier est ici le vritable serveur et il peut laborer une rponse la main. Rappelons-nous la rponse faite par un serveur Web dans un prcdent exemple :
<-<-<-<-<-<-<-<-<-<-<-HTTP/1.1 200 OK Date: Mon, 13 May 2002 07:30:58 GMT Server: Apache/1.3.12 (Unix) (Red Hat/Linux) PHP/3.0.15 mod_perl/1.21 Last-Modified: Wed, 06 Feb 2002 09:00:58 GMT ETag: "23432-2bf3-3c60f0ca" Accept-Ranges: bytes Content-Length: 11251 Connection: close Content-Type: text/html <html>
Les lignes commenant par 2 : sont envoyes du serveur au client n 2. La commande fin clt la connexion du serveur au client. Nous nous sommes limits dans notre rponse aux enttes HTTP suivants :
HTTP/1.1 200 OK 2 : Server: serveur tcp generique 2 : Connection: close 2 : Content-Type: text/html 2 :
Nous ne donnons pas la taille du fichier que nous allons envoyer (Content-Length) mais nous contentons de dire que nous allons fermer la connexion (Connection: close) aprs envoi de celui-ci. Cela est suffisant pour le navigateur. En voyant la connexion ferme, il saura que la rponse du serveur est termine et affichera la page HTML qui lui a t envoye. Cette dernire est la suivante :
2 2 2 2 2 2 2 2 : <html> : <head><title>Serveur generique</title></head> : <body> : <center> : <h2>Reponse du serveur generique</h2> : </center> : </body> : </html>
L'utilisateur ferme ensuite la connexion au client en tapant la commande fin. Le navigateur sait alors que la rponse du serveur est termine et peut alors l'afficher :
- 328 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
c'est dire exactement ce qu'on a envoy depuis le serveur gnrique. Le code du serveur tcp gnrique est le suivant :
// paquetages import java.io.*; import java.net.*; public class serveurTCPgenerique{ // programme principal public static void main (String[] args){ // // // // // // reoit le port d'coute des demandes des clients cre un thread pour lire les demandes du client celles-ci seront affiches l'cran cre un thread pour lire des commandes tapes au clavier celles-ci seront envoyes comme rponse au client le tout se termine avec la commande fin tape au clavier
final String syntaxe="Syntaxe : pg port"; // variable d'instance // y-a-t-il un argument if(args.length != 1) erreur(syntaxe,1); // le port doit tre entier >0 int port=0; boolean erreurPort=false; Exception E=null; try{ port=Integer.parseInt(args[0]); }catch(Exception e){ E=e; erreurPort=true; } erreurPort=erreurPort || port <=0; if(erreurPort) erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2); // on cre le servive d'coute ServerSocket ecoute=null; int nbClients=0; // nbre de clients traits try{ // on cre le service
- 329 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
ecoute=new ServerSocket(port); // suivi System.out.println("Serveur gnrique lanc sur le port " + port); // boucle de service aux clients Socket client=null; while (true){ // boucle infinie - sera arrte par Ctrl-C // attente d'un client client=ecoute.accept(); // le service est assur des threads spars nbClients++; // on cre les threads de lecture/criture new ServeurSend(client,nbClients).start(); new ServeurReceive(client,nbClients).start(); // on retourne l'coute des demandes }// fin while }catch(Exception ex){ // on signale l'erreur erreur("L'erreur suivante s'est produite : " + ex.getMessage(),3); }//catch }// fin main // affichage des erreurs public static void erreur(String msg, int exitCode){ // affichage erreur System.err.println(msg); // arrt avec erreur System.exit(exitCode); }//erreur }//classe class ServeurSend extends Thread{ // classe charge de lire des rponses tapes au clavier // et de les envoyer un client via un client tcp pass au constructeur Socket client; // le client tcp int numClient; // n de client // constructeur public ServeurSend(Socket client, int numClient){ // on note le client tcp this.client=client; // et son n this.numClient=numClient; }//constructeur // mthode Run du thread public void run(){ // donnes locales PrintWriter OUT=null; // flux d'criture rseau String rponse=null; // rponse lue au clavier BufferedReader IN=null; // flux clavier // suivi System.out.println("Thread de lecture des rponses du serveur au client "+ numClient + " lanc"); // gestion des erreurs try{ // cration du flux d'criture rseau OUT=new PrintWriter(client.getOutputStream(),true); // cration du flux clavier IN=new BufferedReader(new InputStreamReader(System.in)); // boucle saisie-envoi des commandes while(true){ // identification client System.out.print("--> " + numClient + " : "); // lecture rponse tape au clavier rponse=IN.readLine().trim();
- 330 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// fini ? if (rponse.toLowerCase().equals("fin")) break; // envoi rponse au serveur OUT.println(rponse); // rponse suivante }//while }catch(Exception ex){ // erreur System.err.println("L'erreur suivante s'est produite : " + ex.getMessage()); }//catch // fin - on ferme les flux try{ OUT.close();client.close(); }catch(Exception ex){} // on signale la fin du thread System.out.println("[fin du Thread de lecture des rponses du serveur au client "+ numClient+ "]"); }//run }//classe class ServeurReceive extends Thread{ // classe charge de lire les lignes de texte envoyes au serveur // via un client tcp pass au constructeur Socket client; // le client tcp int numClient; // n de client // constructeur public ServeurReceive(Socket client, int numClient){ // on note le client tcp this.client=client; // et son n this.numClient=numClient; }//constructeur // mthode Run du thread public void run(){ // donnes locales BufferedReader IN=null; // flux lecture rseau String rponse=null; // rponse serveur // suivi System.out.println("Thread de lecture des demandes du client "+ numClient + " lanc"); // gestion des erreurs try{ // cration du flux lecture rseau IN=new BufferedReader(new InputStreamReader(client.getInputStream())); // boucle lecture lignes de texte du flux IN while(true){ // lecture flux rseau rponse=IN.readLine(); // flux ferm ? if(rponse==null) break; // affichage System.out.println("<-- "+rponse); }//while }catch(Exception ex){ // erreur System.err.println("L'erreur suivante s'est produite : " + ex.getMessage()); }//catch // fin - on ferme les flux try{ IN.close();client.close(); }catch(Exception ex){} // on signale la fin du thread System.out.println("[fin du Thread de lecture des demandes du client "+ numClient+"]"); }//run }//classe
- 331 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous allons crire un client Web auquel on passerait en paramtre une URL et qui afficherait l'cran le contenu de cette URL. Nous supposerons que le serveur Web contact pour l'URL supporte le protocole HTTP 1.1. Des enttes prcdents, nous n'utiliserons que les suivants :
<-- GET /exemple.html HTTP/1.1 <-- Host: localhost:88 <-- Connection: close
le premier entte indique quelle page nous dsirons le second quel serveur nous interrogeons le troisime que nous souhaitons que le serveur ferme la connexion aprs nous avoir rpondu.
Si ci-dessus, nous remplaons GET par HEAD, le serveur ne nous enverra que les enttes HTTP et pas la page HTML. Notre client web sera appel de la faon suivante : java clientweb URL cmd, o URL est l'URL dsire et cmd l'un des deux mots cls GET ou HEAD pour indiquer si on souhaite seulement les enttes (HEAD) ou galement le contenu de la page (GET). Regardons un premier exemple. Nous lanons le serveur IIS puis le client web sur la mme machine :
dos>java clientweb http://localhost HEAD HTTP/1.1 302 Object moved Server: Microsoft-IIS/5.0 Date: Mon, 13 May 2002 09:23:37 GMT Connection: close Location: /IISSamples/Default/welcome.htm Content-Length: 189 Content-Type: text/html Set-Cookie: ASPSESSIONIDGQQQGUUY=HMFNCCMDECBJJBPPBHAOAJNP; path=/ Cache-control: private
La rponse
HTTP/1.1 302 Object moved
signifie que la page demande a chang de place (donc d'URL). La nouvelle URL est donne par l'entte Location:
Location: /IISSamples/Default/welcome.htm
dos>java clientweb http://localhost GET HTTP/1.1 302 Object moved Server: Microsoft-IIS/5.0
- 332 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Date: Mon, 13 May 2002 09:33:36 GMT Connection: close Location: /IISSamples/Default/welcome.htm Content-Length: 189 Content-Type: text/html Set-Cookie: ASPSESSIONIDGQQQGUUY=IMFNCCMDAKPNNGMGMFIHENFE; path=/ Cache-control: private <head><title>L'objet a chang d'emplacement</title></head> <body><h1>L'objet a chang d'emplacement</h1>Cet objet peut tre trouv <a HREF="/IISSamples/Default/we lcome.htm">ici</a>.</body>
Nous obtenons le mme rsultat qu'avec HEAD avec de plus le corps de la page HTML. Le programme est le suivant :
// paquetages imports import java.io.*; import java.net.*; public class clientweb{ // demande une URL // affiche le contenu de celle-ci l'cran public static void main(String[] args){ // syntaxe final String syntaxe="pg URI GET/HEAD"; // nombre d'arguments if(args.length != 2) erreur(syntaxe,1); // on note l'URI demande String URLString=args[0]; String commande=args[1].toUpperCase(); // vrification validit de l'URI URL url=null; try{ url=new URL(URLString); }catch (Exception ex){ // URI incorrecte erreur("L'erreur suivante s'est produite : " + ex.getMessage(),2); }//catch // vrification de la commande if(! commande.equals("GET") && ! commande.equals("HEAD")){ // commande incorrecte erreur("Le second paramtre doit tre GET ou HEAD",3); } // on extrait les infos utiles de l'URL String path=url.getPath(); if(path.equals("")) path="/"; String query=url.getQuery(); if(query!=null) query="?"+query; else query=""; String host=url.getHost(); int port=url.getPort(); if(port==-1) port=url.getDefaultPort(); // on peut travailler Socket client=null; // le client BufferedReader IN=null; // le flux de lecture du client PrintWriter OUT=null; // le flux d'criture du client String rponse=null; // rponse du serveur try{ // on se connecte au serveur client=new Socket(host,port); // on cre les flux d'entre-sortie du client TCP IN=new BufferedReader(new InputStreamReader(client.getInputStream())); OUT=new PrintWriter(client.getOutputStream(),true);
- 333 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// on demande l'URL - envoi des enttes HTTP OUT.println(commande + " " + path + query + " HTTP/1.1"); OUT.println("Host: " + host + ":" + port); OUT.println("Connection: close"); OUT.println(); // on lit la rponse while((rponse=IN.readLine())!=null){ // on traite la rponse System.out.println(rponse); }//while // c'est fini client.close(); } catch(Exception e){ // on gre l'exception erreur(e.getMessage(),4); }//catch }//main // affichage des erreurs public static void erreur(String msg, int exitCode){ // affichage erreur System.err.println(msg); // arrt avec erreur System.exit(exitCode); }//erreur }//classe
La seule nouveaut dans ce programme est l'utilisation de la classe URL. Le programme reoit une URL (Uniform Resource Locator) ou URI (Uniform Resource Identifier) de la forme http://serveur:port/cheminPageHTML? param1=val1;param2=val2;.... La classe URL nous permet de dcomposer la chane de l'URL en ses diffrents lments. Un objet URL est construit partir de la chane URLstring reue en paramtre :
// vrification validit de l'URL URL url=null; try{ url=new URL(URLString); }catch (Exception ex){ // URI incorrecte erreur("L'erreur suivante s'est produite : " + ex.getMessage(),2); }//catch
Si la chane URL reue en paramtre n'est pas une URL valide (absence du protocole, du serveur, ...), une exception est lance. Cela nous permet de vrifier la validit du paramtre reu. Une fois l'objet URL construit, on a accs aux diffrents lments de celui-ci. Ainsi si l'objet url du code prcdent a t construit partir de la chane http://serveur:port/cheminPageHTML?param1=val1;param2=val2;... on aura : url.getHost()=serveur url.getPort()=port ou -1 si le port n'est pas indiqu url.getPath()=cheminPageHTML ou la chane vide s'il n'y a pas de chemin url.getQuery()=param1=val1;param2=val2;... ou null s'il n'y a pas de requte uri.getProtocol()=http
1 2 3
il lit la premire ligne des enttes HTTP envoys par le serveur pour vrifier si on y trouve la chane 302 Object moved qui signale une redirection il lit les enttes suivants. S'il y a redirection, il recherche la ligne Location: url qui donne la nouvelle URL de la page demande et note cette URL. il affiche le reste de la rponse du serveur. S'il y a redirection, les tapes 1 3 sont rptes avec la nouvelle URL. Le programme n'accepte pas plus d'une redirection. Cette limite fait l'objet d'une constante qui peut tre modifie.
Voici un exemple :
Dos>java clientweb2 http://localhost GET HTTP/1.1 302 Object moved Server: Microsoft-IIS/5.0 Date: Mon, 13 May 2002 11:38:55 GMT Connection: close Location: /IISSamples/Default/welcome.htm Content-Length: 189 Content-Type: text/html Set-Cookie: ASPSESSIONIDGQQQGUUY=PDGNCCMDNCAOFDMPHCJNPBAI; path=/ Cache-control: private <head><title>L'objet a chang d'emplacement</title></head> <body><h1>L'objet a chang d'emplacement</h1>Cet objet peut tre trouv <a HREF="/IISSamples/Default/we lcome.htm">ici</a>.</body> <--Redirection vers l'URL http://localhost:80/IISSamples/Default/welcome.htm--> HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Connection: close Date: Mon, 13 May 2002 11:38:55 GMT Content-Type: text/html Accept-Ranges: bytes Last-Modified: Mon, 16 Feb 1998 21:16:22 GMT ETag: "0174e21203bbd1:978" Content-Length: 4781 <html> <head> <title>Bienvenue dans le Serveur Web personnel</title> </head> .... </body> </html>
- 335 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String commande=args[1].toUpperCase(); // vrification validit de l'URI URL url=null; try{ url=new URL(URLString); }catch (Exception ex){ // URI incorrecte erreur("L'erreur suivante s'est produite : " + ex.getMessage(),2); }//catch // vrification de la commande if(! commande.equals("GET") && ! commande.equals("HEAD")){ // commande incorrecte erreur("Le second paramtre doit tre GET ou HEAD",3); } // on peut travailler Socket client=null; BufferedReader IN=null; PrintWriter OUT=null; String rponse=null; final int nbRedirsMax=1; int nbRedirs=0; String premireLigne; boolean redir=false; String locationString="";
// // // // // // // // //
le client le flux de lecture du client le flux d'criture du client rponse du serveur pas plus d'une redirection accepte nombre de redirections en cours 1re ligne de la rponse indique s'il y a redirection ou non la chane URL d'une ventuelle redirection
// expression rgulire pour trouver une URL de redirection Pattern location=Pattern.compile("^Location: (.+?)$"); // gestion des erreurs try{ // on peut avoir plusieurs URL demander s'il y a des redirections while(nbRedirs<=nbRedirsMax){ // on extrait les infos utiles de l'URL String protocol=url.getProtocol(); String path=url.getPath(); if(path.equals("")) path="/"; String query=url.getQuery(); if(query!=null) query="?"+query; else query=""; String host=url.getHost(); int port=url.getPort(); if(port==-1) port=url.getDefaultPort(); // on se connecte au serveur client=new Socket(host,port); // on cre les flux d'entre-sortie du client TCP IN=new BufferedReader(new InputStreamReader(client.getInputStream())); OUT=new PrintWriter(client.getOutputStream(),true); // on demande l'URL - envoi des enttes HTTP OUT.println(commande + " " + path + query + " HTTP/1.1"); OUT.println("Host: " + host + ":" + port); OUT.println("Connection: close"); OUT.println(); // on lit la premire ligne de la rponse premireLigne=IN.readLine(); // cho cran System.out.println(premireLigne); // redirection ? if(premireLigne.endsWith("302 Object moved")){ // il y a une redirection redir=true; nbRedirs++; }//if // enttes HTTP suivants jusqu' trouver la ligne vide signalant la fin des enttes boolean locationFound=false; while(!(rponse=IN.readLine()).equals("")){ // on affiche la rponse System.out.println(rponse); // s'il y a redirection, on recherche l'entte Location
- 336 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
if(redir && ! locationFound){ // on compare la ligne l'expression relationnelle location Matcher rsultat=location.matcher(rponse); if(rsultat.find()){ // si on a trouv on note l'URL de redirection locationString=rsultat.group(1); // on note qu'on a trouv locationFound=true; }//if }//if // entte suivant }//while // lignes suivantes de la rponse System.out.println(rponse); while((rponse=IN.readLine())!=null){ // on affiche la rponse System.out.println(rponse); }//while // on ferme la connexion client.close(); // a-t-on fini ? if ( ! locationFound || nbRedirs>nbRedirsMax) break; // il y a une redirection oprer - on construit la nouvelle URL URLString=protocol +"://"+host+":"+port+locationString; url=new URL(URLString); // suivi System.out.println("\n<--Redirection vers l'URL "+URLString+"-->\n"); }//while } catch(Exception e){ // on gre l'exception erreur(e.getMessage(),4); }//catch }//main // affichage des erreurs public static void erreur(String msg, int exitCode){ // affichage erreur System.err.println(msg); // arrt avec erreur System.exit(exitCode); }//erreur }//classe
- 337 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
un constructeur qui on passe les trois tableaux de donnes ncessaires au calcul de l'impt
public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception{
A partir de cette classe a t drive la classe impotsJDBC qui permet de remplir les trois tableaux limites, coeffR, coeffN partir du contenu d'une base de donnes :
public class impotsJDBC extends impots{ // rajout d'un constructeur permettant de construire // les tableaux limites, coeffr, coeffn partir de la table // impots d'une base de donnes public impotsJDBC(String dsnIMPOTS, String userIMPOTS, String mdpIMPOTS) throws SQLException,ClassNotFoundException{ // dsnIMPOTS : nom DSN de la base de donnes // userIMPOTS, mdpIMPOTS : login/mot de passe d'accs la base
Une application graphique avait t crite. L'application utilisait un objet de la classe impotsJDBC. L'application et cet objet taient sur la mme machine. Nous nous proposons de mettre le programme de test et l'objet impotsJDBC sur des machines diffrentes. Nous aurons une application client-serveur o l'objet impotsJDBC distant sera le serveur. La nouvelle classe s'appelle ServeurImpots et est drive de la classe impotsJDBC :
// paquetages imports import java.net.*; import java.io.*; import java.sql.*; public class ServeurImpots extends impotsJDBC { // attributs int portEcoute; // le port d'coute des demandes clients boolean actif; // tat du serveur // constructeur public ServeurImpots(int portEcoute,String DSNimpots, String USERimpots, String MDPimpots) throws IOException, SQLException, ClassNotFoundException { // construction parent super(DSNimpots, USERimpots, MDPimpots); // on note le port d'coute this.portEcoute=portEcoute; // pour l'instant inactif actif=false; // cre et lance un thread de lecture des commandes tapes au clavier // le serveur sera gr partir de ces commandes Thread admin=new Thread(){ public void run(){ try{ admin(); }catch (Exception ignored){} } }; admin.start(); }//ServeurImpots
Le seul paramtre nouveau dans le constructeur est le port d'coute des demandes des clients. Les autres paramtres sont passs directement la classe de base impotsJDBC. Le serveur d'impts est contrl par des commandes tapes au clavier. Aussi cre-t-on un thread pour lire ces commandes. Il y en aura deux possibles : start pour lancer le service, stop pour l'arrter dfinitivement. La mthode admin qui gre ces commandes est la suivante :
public void admin() throws IOException{ // lit les commandes d'administration du serveur tapes au clavier
- 338 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// dans une boucle sans fin String commande=null; BufferedReader IN=new BufferedReader(new InputStreamReader(System.in)); while(true){ // invite System.out.print("Serveur d'impts>"); // lecture commande commande=IN.readLine().trim().toLowerCase(); // excution commande if(commande.equals("start")){ // actif ? if(actif){ //erreur System.out.println("Le serveur est dj actif"); // on continue continue; }//if // on cre et lance le service d'coute Thread ecoute=new Thread(){ public void run(){ ecoute(); } }; ecoute.start(); }//if else if(commande.equals("stop")){ // fin de tous les threads d'excution System.exit(0); }//if else { // erreur System.out.println("Commande incorrecte. Utilisez (start,stop)"); }//if }//while }//admin
Si la commande tape au clavier est start, un thread d'coute des demandes clients est lanc. Si la commande tape est stop, tous les threads sont arrts. Le thread d'coute excute la mthode ecoute :
public void ecoute(){ // thread d'coute des demandes des clients // on cre le service d'coute ServerSocket ecoute=null; try{ // on cre le service ecoute=new ServerSocket(portEcoute); // suivi System.out.println("Serveur d'impts lanc sur le port " + portEcoute); // boucle de service Socket liaisonClient=null; while (true){ // boucle infinie // attente d'un client liaisonClient=ecoute.accept(); // le service est assur par une autre tche new traiteClientImpots(liaisonClient,this).start(); // on retourne l'coute des demandes }// fin while }catch(Exception ex){ // on signale l'erreur erreur("L'erreur suivante s'est produite : " + ex.getMessage(),3); }//catch }//thread d'coute
On retrouve un serveur tcp classique coutant sur le port portEcoute. Les demandes des clients sont traites par la mthode run du thread traiteCientImpots au constructeur duquel on passe deux paramtres :
- 339 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
1 2
l'objet Socket liaisonClient qui va permettre d'atteindre le client l'objet impotsJDBC this qui va donner accs la mthode this.calculer de calcul de l'impt.
// ------------------------------------------------------// assure le service un client du serveur d'impts class traiteClientImpots extends Thread{ private private private private Socket liaisonClient; // liaison avec le client BufferedReader IN; // flux d'entre PrintWriter OUT; // flux de sortie impotsJDBC objImpots; // objet Impt
La mthode run traite les demandes des clients. Ce sont des lignes de texte qui peuvent avoir deux formes : calcul mari(o/n) nbEnfants salaireAnnuel fincalculs
Le calcul de l'impt est effectu par la mthode calculerImpt qui reoit en paramtre le tableau des champs de la demande faite par le client. La validit de la demande est vrifie et ventuellement l'impt calcul et renvoy au client.
// calcul d'impts public void calculerImpt(String[] champs){ // traite la demande : calcul mari nbEnfants salaireAnnuel // dcompose en champs dans le tableau champs String mari=null; int nbEnfants=0; int salaireAnnuel=0; // validit des arguments try{ // il faut au moins 4 champs if(champs.length!=4) throw new Exception(); // mari mari=champs[1]; if (! mari.equals("o") && ! mari.equals("n")) throw new Exception(); // enfants nbEnfants=Integer.parseInt(champs[2]); // salaire salaireAnnuel=Integer.parseInt(champs[3]); }catch (Exception ignored){ // erreur de format OUT.println(" syntaxe : calcul mari(O/N) nbEnfants salaireAnnuel"); // fini return; }//if // on peut calculer l'impt long impot=objImpots.calculer(mari.equals("o"),nbEnfants,salaireAnnuel); // on envoie la rponse au client OUT.println(""+impot); }//calculer
- 341 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
System.out.println("L'erreur suivante s'est produite : "+ex.getMessage()); }//catch }//Main // affichage des erreurs public static void erreur(String msg, int exitCode){ // affichage erreur System.err.println(msg); // arrt avec erreur System.exit(exitCode); }//erreur }// fin class
On passe au programme de test les donnes ncessaires la construction d'un objet ServeurImpots et partir de l il cre cet objet. Tentons une premire excution :
dos>java testServeurImpots 124 mysql-dbimpots admimpots mdpimpots Serveur d'impts>start Serveur d'impts>Serveur d'cho lanc sur le port 124 stop
La commande
dos>java testServeurImpots 124 mysql-dbimpots admimpots mdpimpots
cre un objet ServeurImpots qui n'coute pas encore les demandes des clients. C'est la commande start tape au clavier qui lance cette coute. La commande stop arrte le serveur. Utilisons maintenant un client. Nous utiliserons le client gnrique cr prcdemment. Le serveur est lanc :
dos>java testServeurImpots 124 mysql-dbimpots admimpots mdpimpots Serveur d'impts>start Serveur d'impts>Serveur d'cho lanc sur le port 124
On voit que le client a bien rcupr le message de bienvenue du serveur. On envoie d'autres commandes :
x <-- Commande incorrecte. Utilisez (calcul,fincalculs). calcul <-- syntaxe : calcul mari(O/N) nbEnfants salaireAnnuel calcul o 2 200000 <-- 22506 calcul n 2 200000 <-- 33388 fincalculs <-- Au revoir... [fin du thread de lecture des rponses du serveur] fin [fin du thread d'envoi des commandes au serveur]
- 342 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
VII-E - Exercices VII-E-1 - Exercice 1 - Client TCP gnrique graphique VII-E-1-a - Prsentation de l'application
On se propose de crer un programme capable de dialoguer sur l'Internet avec les principaux services TCP. On l'appellera un client tcp gnrique. Lorsqu'on a compris cette application, on trouve que tous les clients tcp se ressemblent. La fentre du programme est la suivante :
- 343 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
n 1
nom TxtRemoteHost
type JTextField
2 3
TxtPort TxtSend
JTextField JTextField
OptRCLF OptLF
JCheckBox
LstSuivi
JList
LstDialogue
JList
CmdAnnuler
JButton
rle nom de la machine offrant le service dsir port du service demand texte du message qui sera envoy au serveur par le client boutons permettant d'indiquer comment se terminent les lignes dans le dialogue client/ serveur RCLF : retour chariot (#13) + passage la ligne (#10) LF : passage la ligne (#10) affiche des messages sur l'tat de la communication entre le client & le serveur affiche les messages changs par le client (->) et le serveur (<-) cach - situ sous la liste de dialogue - Apparat lorsque la connexion est en cours et permet de l'interrompre si le serveur ne rpond pas
Les options de menu disponibles sont les suivantes : option Connexion sous-options Connecter Dconnecter Quitter Envoyer RazSuivi RazDialogue Auteur rle connecte le client au serveur ferme la connexion Termine le programme Envoie le message du contrle TxtSend au serveur Efface la liste LstSuivi Efface la liste LstDialogue affiche une bote de copyright
Messages
- 344 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
seules les options de menu Connexion/Quitter & Auteur sont actives le bouton Annuler est cach les listes LstSuivi & LstDialogue sont vides
Menu Connexion/Connecter Cette option n'est disponible que lorsque les champs Hte Distant et n de port sont non vides et qu'une connexion n'est pas actuellement active. Un clic sur cette option entrane les oprations suivantes : la validit du port est vrifie : ce doit tre un entier >0 un thread est lanc pour assurer la connexion au serveur le bouton Annuler apparat afin de permettre l'utilisateur d'interrompre la connexion en cours toutes les options de menu sont dsactives sauf Quitter & Auteur
La connexion peut se terminer de plusieurs faons : L'utilisateur a appuy sur le bouton Annuler : on arrte le thread de connexion et on remet le menu dans son tat de dpart. On indique dans le suivi qu'il y a eu fermeture de la connexion par l'utilisateur. La connexion se termine avec une erreur : on fait la mme chose que prcdemment et de plus dans le suivi, on indique la cause de l'erreur. La connexion se termine correctement : on enlve le bouton Annuler, indique dans le suivi que la connexion a t faite, autorise le menu RazSuivi, inhibe le menu Connecter, autorise le menu Dconnecter
Menu Connexion/Dconnecter Cette option n'est disponible que lorsqu'une connexion avec le serveur existe. Lorsqu'elle est active elle clt la connexion avec le serveur et remet le menu dans son tat de dpart. On indique dans le suivi que la connexion a t ferme par le client. Menu Connexion/Quitter Cette option clt une ventuelle connexion active avec le serveur et termine l'application. Menu Messages/Envoyer Cette option n'est accessible que si les conditions suivantes sont runies : la connexion avec le serveur a t faite il y a un message envoyer
Si ces conditions sont runies, on envoie au serveur le texte prsent dans le champ TxtSend (3) termin par la squence RCLF si l'option RCLF a t coche, la squence LF sinon. Une ventuelle erreur l'mission est signale dans la liste de suivi. Menus RazSuivi et RazDialogue Vident respectivement les listes LstSuivi et LstDialogue. Ces options sont inhibes lorsque les listes coorespondantes sont vides. Le bouton Annuler
- 345 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ce bouton situ en bas du formulaire n'apparat que lorsque le client est en cours de connexion au serveur. Cette connexion peut ne pas se faire parce que le serveur ne rpond pas ou mal. Le bouton Annuler donne alors l'utilisateur, la possibilit d'interrompre la demande de connexion. Les listes de suivi La liste LstSuivi (5) fait le suivi de la connexion. Elle indique les moments cls de la connexion : son ouverture par le client sa fermeture par le serveur ou le client toutes les erreurs qui peuvent se produire tant que la liaison est active
La liste LstDialogue (6) fait le suivi du dialogue qui s'instaure entre le client et le serveur. Un thread surveille en tche de fond ce qui arrive sur la socket de communication du client et l'affiche dans la liste 6. L'option Auteur Ce menu ouvre une fentre dite de Copyright :
Gestion des erreurs Les erreurs de connexion sont signales dans la liste de suivi 6, celles lies au dialogue client/serveur dans la liste de dialogue 7. Lors d'une erreur de liaison, le dialogue client/serveur est ferm et le formulaire remis dans son tat initial prt pour une nouvelle connexion.
tout type de client (PC, Mac, Unix,...) peut utiliser ce service le client peut tre n'importe o sur l'Internet les moyens de calcul sont optimiss : seules quelques machines puissantes sont ncessaires. Ainsi, une petite organisation sans moyens de calcul peut utiliser ce service moyennant une contribution financire calcule d'aprs le temps de calcul utilis.
Malgr la puissance des machines, un calcul peut parfois durer plusieurs heures : le serveur n'est alors pas disponible pour d'autres clients. Se pose alors pour un client, le problme de trouver un serveur de calcul disponible. Pour cela, on utilise alors un gestionnaire de ressources de calcul , appel serveur GRC par la suite. Ce service est plac sur une unique machine et travaille sur le port 864 en mode tcp. C'est lui que s'adresse un client dsirant un accs un serveur de calcul. Le serveur GRC qui dtient la liste complte des serveurs de calcul lui rpond en lui envoyant le nom d'un serveur actuellement inactif. Le client n'a plus alors qu' envoyer ses donnes au serveur qu'on lui aura dsign. On se propose d'crire le serveur GRC.
L'interface prsente deux listes de serveurs : gauche, la liste des serveurs inactifs donc disponibles pour des calculs droite, la liste des serveurs occups par les calculs d'un client.
La structure du menu est la suivante : Menu Principal Service Menu secondaire Lancer Arrter Quitter Auteur La structure des contrles prsents sur le formulaire est la suivante : Rle Lance le service tcp sur le port 864 Arrte le service Termine l'application Informations de Copyright
- 347 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Option Service/Arrter Cette option interrompt le service : interrompt le service : la liste des serveurs occups est vide la liste des serveurs libres est remplie avec le contenu du fichier Serveurs le menu Lancer est autoris le menu Arrter est inhib
Option Service/Quitter L'application se termine. Dialogue client/serveur Le dialogue client/serveur se fait par change de lignes de texte termines par la squence RCLF. Le serveur GRC reconnat deux commandes : getserveur et finservice. Nous dtaillons le rle de ces deux commandes : 1 getserveur Le client demande s'il y a un serveur de calcul disponible pour lui. Le serveur GRC prend alors le premier serveur trouv dans sa liste de serveurs libres et renvoie son nom au client sous la forme : 100-nom du serveur Par ailleurs, il passe le serveur accord au client dans la liste des serveurs occups sous la forme :
- 348 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
serveur (IP du client) comme le montre l'exemple suivant o le serveur calcul1.istia.univ-angers.fr est occup servir le client d'adresse IP 193.52.43.5 :
Un client ne peut envoyer une commande getserveur si un serveur de calcul lui a dj t affect. Ainsi avant de rpondre au client, le serveur GRC vrifie que l'adresse IP du client n'est pas dj prsent parmi celles enregistres dans la liste des serveurs occups. Si c'est le cas, le serveur GRC rpond : 501-Vous avez actuellement une demande en cours Enfin, il y a le cas o aucun serveur de calcul n'est disponible : la liste des serveurs libres est vide. Dans ce cas, le serveur GRC rpond : 502- Il n'y a aucun serveur de calcul disponible Dans tous les cas, aprs avoir rpondu au client, le serveur GRC clt la connexion avec celui-ci afin de pouvoir servir d'autres clients. 2 finservice Le client signifie qu'il n'a plus besoin du serveur de calcul qu'il utilisait. Le serveur GRC vrifie d'abord que le client est bien un client qu'il servait. Pour cela, il vrifie que l'adresse IP du client est prsente parmi celles enregistres dans la liste des serveurs occups. Si ce n'est pas le cas, le serveur GRC rpond : 503-Aucun serveur ne vous a t attribu Si le client est reconnu, le serveur GRC lui rpond : 101-Fin de service accepte et passe le serveur de calcul attribu ce client dans la liste des serveurs libres. Pour reprendre l'exemple prcdent, si le client envoie la commande finservice, l'affichage du serveur GRC devient :
- 349 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Aprs l'envoi de la rponse, quelque soit celle-ci, le serveur GRC clt la connexion.
// rponse du serveur smtp 214-Commands: 214- HELO EHLO MAIL RCPT DATA 214- RSET NOOP QUIT HELP VRFY
- 350 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
214- EXPN VERB 214-For more info use "HELP <topic>". 214-To report bugs in the implementation send email to 214- sendmail@CS.Berkeley.EDU. 214-For local information send email to Postmaster at your site. 214 End of HELP info mail from: serge.tahe@istia.univ-angers.fr // nouvelle commande mise au clavier // commentaires --------La commande mail a la syntaxe suivante : mail from: adresse lectronique de l'expditeur du message // fin de commentaires // rponse du serveur smtp 250 serge.tahe@istia.univ-angers.fr... Sender ok // commentaires Le serveur smtp ne fait aucune vrification de validit de l'adresse de l'expditeur : il la prend telle qu'on la lui a donne // fin de commentaires rcpt to: user1@istia.univ-angers.fr // nouvelle commande mise au clavier
// commentaires --------La commande rcpt a la syntaxe suivante : rcpt to: adresse lectronique du destinataire du message Si l'adresse lectronique est une adresse de la machine sur laquelle travaille le serveur smtp, il vrifie qu'elle existe bien sinon il ne fait aucune vrification. Si vrification il y a eu et qu'une erreur a t dtecte elle sera signale avec un numro >= 500. On peut mettre autant de commandes rcpt to que l'on veut : cela permet d'envoyer un message plusieurs personnes. // fin de commentaires // rponse du serveur smtp 250 user1@istia.univ-angers.fr... Recipient ok data // nouvelle commande mise au clavier
// commentaires --------La commande data a la syntaxe suivante : data ligne1 ligne2 ... . Elle est suivie des lignes de texte composant le message, celui-ci devant se terminer par une ligne comportant le seul caractre point . Le message est alors envoy au destinataire indiqu par la commande rcpt. // fin de commentaires // rponse du serveur smtp 354 Enter mail, end with "." on a line by itself // texte du message tap au clavier subject: essai smtp essai smtp a partir de telnet . // commentaires
- 351 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Dans les lignes de texte de la commande data, on peut mettre une ligne subject: pour prciser le sujet du courrier. Cette ligne doit tre suivie d'une ligne vide. // rponse du serveur smtp 250 HAA11627 Message accepted for delivery quit // nouvelle commande mise au clavier
// commentaires La commande quit clt la connexion au service smtp // fin de commentaires // rponse du serveur smtp 221 Istia.Istia.Univ-Angers.fr closing connection
- 352 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Numro 1 JTextField
Type
2 3
JTextField JTextField
JTextField
5 6 7 8
Rle Suite d'adresses lectroniques spares par une virgule Texte du sujet du message Suite d'adresses lectroniques spares par une virgule Suite d'adresses lectroniques spares par une virgule Texte du message liste de suivi liste de dial bouton Annuler non reprsent, apparaissant lorsque le client demande la connexion au serveur SMTP. Permet l'utilisateur d'interrompre cette demande si le serveur ne rpond pas.
Sauvegarder...
Auteur
- 353 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les deux champs doivent tre remplis pour que le bouton OK soit actif. Les deux informations doivent tre mmorises dans des variables globales afin d'tre disponibles pour d'autres modules. Menu Courrier/Envoyer Cette option n'est accessible que si les conditions suivantes sont runies : la configuration a t faite il y a un message envoyer il y a un sujet il y a au moins un destinataire dans les champs 1, 3 et 4
Si ces conditions sont runies, la squence des vnements est la suivante : le formulaire est mis dans un tat o toutes les actions pouvant interfrer dans le dialogue client/serveur sont inhibes il y a connexion sur le port 25 du serveur prcis dans la configuration le client dialogue ensuite avec le serveur smtp selon le protocole dcrit plus haut le mail from: utilise l'adresse lectronique de l'expditeur donne dans la configuration le rcpt to: s'utilise pour chacune des adresses lectroniques trouves dans les champs 1, 3 et 4 dans les lignes envoyes aprs la commande data, on trouvera les textes suivants : - une ligne Subject: texte du sujet du contrle 2 - une ligne Cc: adresses du contrle 3 -une ligne Bcc: adresses du contrle 4 - le texte du message du contrle 5 - le point terminal
Le bouton Annuler Ce bouton situ en bas du formulaire n'apparat que lorsque le client est en cours de connexion au serveur smtp. Cette connexion peut ne pas se faire parce que le serveur smtp ne rpond pas ou mal. Le bouton Annuler donne alors l'utilisateur, la possibilit d'interrompre la demande de connexion. Les listes de suivi La liste (6) fait le suivi de la connexion. Elle indique les moments cls de la connexion : son ouverture par le client sa fermeture par le serveur ou le client toutes les erreurs de connexion
- 354 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La liste (7) fait le suivi du dialogue smtp qui s'instaure entre le client et le serveur. Ces deux listes sont associes des options du menu : Masquer Suivi Rend invisible la liste de suivi 6 ainsi que le libell qui est au-dessus. Si la hauteur occupe par ces deux contrles est H, tous les contrles situs dessous sont remonts d'une hauteur H et la taille totale du formulaire est diminue de H. Par ailleurs, Masquer Suivi rend invisible l'option RazSuivi ci-dessous. Vide la liste de suivi 6 Rend invisible la liste de dialogue 7, le libell qui est dessus ainsi que l'option de menu RazDialogue ci-dessous. Comme pour Masquer Suivi, la position des contrles situs dessous (bouton Annuler peuttre) est recalcule et la taille de la fentre diminue. Vide la liste de dialogue 7
Raz Dialogue L'option Auteur Ce menu ouvre une fentre dite de Copyright :
Gestion des erreurs Les erreurs de connexion sont signales dans la liste de suivi 6, celles lies au dialogue client/serveur dans la liste de dialogue 7. Lors d'une erreur, l'utilisateur en est averti par une bote d'erreur et la liste contenant la cause de l'erreur est affiche si elle tait auparavant masque. Par ailleurs, le dialogue client/serveur est ferm et le formulaire remis dans son tat initial.
Les lignes SmtpServer et ReplyAddress reprennent les deux informations acquises par l'option Options/Configurer. Les lignes Suivi et Dialogue donnent l'tat des listes de Suivi et de Dialogue : 1 (prsente), 0 (absente).
- 355 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Au chargement du programme, le fichier sendmail.ini est lu s'il existe et le formulaire est configur en consquence. Si le fichier sendmail.ini n'existe pas on fait comme si on avait :
SmtpServer= ReplyAddress= Suivi=1 Dialogue=1
Si le fichier sendmail.ini existe mais est incomplet (lignes manquantes), la ligne manquante est remplace par la ligne correspondante ci-dessus. Ainsi la ligne Suivi=... est manquante, on fait comme si on avait Suivi=1. Toutes les lignes ne correspondant pas au modle : mot cl= valeur sont ignores ainsi que celles o le mot cl est invalide. Le mot cl peut-tre en majuscules ou minuscules : cela n'importe pas. Dans l'option Options/Configurer, les valeurs SmtpServer et ReplyAddress actuellement en cours sont prsentes. L'utilisateur peut alors les modifier s'il le dsire.
- 356 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La signification des diffrents contrles est la suivante : n 1 2 3 4 5 nom txtRemoteHost txtLogin txtMdp txtNewMdp txtConfirmation type JTextField JTextField JTextField JTextField JTextField rle nom du serveur login de l'utilisateur Mot de Passe de l'utilisateur Nouveau mot de passe de l'utilisateur Confirmation du nouveau mot de passe Messages du suivi de la connexion Messages du dialogue Client/ Serveur non reprsent Bouton apparaissant lorsque la connexion au serveur est en cours. Permet de l'arrter .
6 7
lstSuivi lstDialogue
JList JList
10
cmdAnnuler
JButton
- 357 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Menu Connexion/Connecter Cette option n'est disponible que lorsque les champs 1 5 ont t remplis. Un clic sur cette option entrane les oprations suivantes : un thread est lanc pour assurer la connexion au serveur le bouton Annuler apparat afin de permettre l'utilisateur d'interrompre la connexion en cours toutes les options de menu sont dsactives sauf Quitter & Auteur
La squence des vnements est ensuite la suivante : 1 2 L'utilisateur a appuy sur le bouton Annuler : on arrte le thread de connexion et on remet le menu dans son tat de dpart. On indique dans le suivi qu'il y a eu fermeture de la connexion par l'utilisateur. La demande de connexion est accepte par le serveur. On entame ensuite le dialogue avec le serveur pour changer le mot de passe. Les changes de ce dialogue sont inscrits dans la liste LstDialogue. Une fois le dialogue termin, la connexion avec le serveur est close et le menu du formulaire remis dans son tat initial. Tant que le dialogue est actif, le bouton Annuler reste prsent afin de permettre l'utilisateur de clre la connexion s'il le veut. Si au cours de la communication se produit une erreur quelconque, la connexion est close et la cause de l'erreur affiche dans la liste de suivi LstSuivi.
3 4
Menu Connexion/Quitter Cette option clt une ventuelle connexion active avec le serveur et termine l'application. Menus RazSuivi et RazDialogue
- 358 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Vident respectivement les listes LstSuivi et LstDialogue. Ces options sont inhibes lorsque les listes coorespondantes sont vides. Le bouton Annuler Ce bouton situ en bas du formulaire n'apparat que lorsque le client est en cours de connexion ou connect au serveur. Le bouton Annuler donne l'utilisateur, la possibilit d'interrompre la communication avec le serveur. Les listes de suivi La liste LstSuivi (5) fait le suivi de la connexion. Elle indique les moments cls de la connexion : son ouverture par le client sa fermeture par le serveur ou le client toutes les erreurs de qui peuvent se produire tant que la liaison est active
La liste LstDialogue (6) fait le suivi du dialogue qui s'instaure entre le client et le serveur. L'option Auteur Ce menu ouvre une fentre dite de Copyright :
Gestion des erreurs Les erreurs de communication sont signales dans la liste de suivi 6, celles lies au dialogue client/serveur dans la liste de dialogue 7. Lors d'une erreur de liaison, le dialogue client/serveur est ferm et le formulaire remis dans son tat initial prt pour une nouvelle connexion.
- 359 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le dernier point est un facteur de portabilit : si la couche rseau d'une application RMI venait changer, l'application elle-mme n'aurait pas tre r-crite. Ce sont les classes RMI du langage Java qui devront tre adaptes la nouvelle couche rseau. Le principe d'une communication RMI est le suivant : 1 Une application Java classique est crite sur une machine A. Elle va jouer le rle de serveur. Pour ce faire certains de ses objets vont faire l'objet d'une publication sur la machine A sur laquelle l'application s'excute et deviennent alors des services. Une application Java classique est crite sur une machine B. Elle va jouer le rle de client. Elle aura accs aux objets/services publis sur la machine A, c'est dire que via une rfrence distante, elle va pouvoir les manipuler comme s'ils taient locaux. Pour cela, elle aura besoin de connatre la structure de l'objet distant auquel elle veut accder (mthodes & proprits).
- 360 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Ici, on dclare donc une interface interEcho dclarant une mthode echo comme accessible distance. Cette mthode est susceptible de gnrer une exception de la classe RemoteException, classe qui regroupe tous les erreurs lies au rseau.
Dans la classe prcdente, nous trouvons : 1 2 la mthode qui fait l'cho un constructeur qui ne fait rien si ce n'est appeler le constructeur de la classe mre. Il est l pour dclarer qu'il peut gnrer une exception de type RemoteException.
Nous allons crer une instance de cette classe avec une mthode main. Pour qu'un objet/service soit accessible de l'extrieur, il doit tre cr et enregistr dans l'annuaire des objets accessibles de l'extrieur. Un client dsirant accder un objet distant procde en effet de la faon suivante : 1 il s'adresse au service d'annuaire de la machine sur laquelle se trouve l'objet qu'il dsire. Ce service d'annuaire opre sur un port que le client doit connatre (1099 par dfaut). Le client demande l'annuaire, une rfrence d'un objet/service dont il donne le nom. Si ce nom est celui d'un objet/service de l'annuaire, celui-ci renvoie au client une rfrence via laquelle le client va pouvoir dialoguer avec l'objet/service distant. partir de ce moment, le client peut utiliser cet objet distant comme s'il tait local
Pour en revenir notre serveur, nous devons crer un objet de type srvEcho et l'enregistrer dans l'annuaire des objets accessibles de l'extrieur. Cet enregistrement se fait avec la mthode de classe rebind de la classe Naming : Naming.rebind(String nom, Remote obj) avec nom le nom qui sera associ l'objet distant obj l'objet distant Notre classe srvEcho devient donc la suivante :
import java.rmi.*;
- 361 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
import java.rmi.server.*; import java.net.*; // classe implmentant l'cho distant public class srvEcho extends UnicastRemoteObject implements interEcho{ // constructeur public srvEcho() throws RemoteException{ super(); }// fin constructeur // mthode ralisant l'cho public String echo(String msg) throws RemoteException{ return "[" + msg + "]"; }// fin cho // cration du service public static void main (String arg[]){ try{ srvEcho serveurEcho=new srvEcho(); Naming.rebind("srvEcho",serveurEcho); System.out.println("Serveur d'cho prt"); } catch (Exception e){ System.err.println(" Erreur " + e + " lors du lancement du serveur d'cho "); } }// main }// fin classe
Lorsqu'on lit le programme prcdent, on a l'impression qu'il va s'arrter aussitt aprs avoir cr et enregistr le service d'cho. Ce n'est pas le cas. Parce que la classe srvEcho est drive de la classe UnicastRemoteObject, l'objet cr s'excute indfiniment : il coute les demandes des clients sur un port anonyme c'est dire choisi par le systme selon les circonstances. La cration du service est asynchrone : dans l'exemple, la mthode main cre le service et continue son excution : elle affichera bien Serveur d'cho prt .
- 362 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String urlService=arg[0]; BufferedReader in=null; String msg=null; String reponse=null; interEcho serveur=null; try{ // ouverture du flux clavier in=new BufferedReader(new InputStreamReader(System.in)); // localisation du service serveur=(interEcho) Naming.lookup(urlService); // boucle de lecture des msg envoyer au serveur d'cho System.out.print("Message : "); msg=in.readLine().toLowerCase().trim(); while(! msg.equals("fin")){ // envoi du msg au serveur et rception de la rponse reponse=serveur.echo(msg); // suivi System.out.println("Rponse serveur : " + reponse); // msg suivant System.out.print("Message : "); msg=in.readLine().toLowerCase().trim(); }// while // c'est fini System.exit(0); // gestion des erreurs } catch (Exception e){ System.err.println("Erreur : " + e); System.exit(2); }// try }// main }// classe
Il n'y a rien de bien particulier dans ce client si ce n'est l'instruction qui demande une rfrence du serveur :
serveur=(interEcho) Naming.lookup(urlService);
On se rappelle que notre service d'cho a t enregistr dans l'annuaire des services de la machine o il se trouve avec l'instruction :
Naming.rebind("srvEcho",serveurEcho);
Le client utilise donc lui aussi une mthode de la classe Naming pour obtenir une rfrence du serveur qu'il veut utiliser. La mthode lookup utilise admet comme paramtre l'url du service demand. Celle-ci a la forme d'une url classique : rmi://machine:port/nom_service avec rmi facultatif - protocole rmi machine nom ou adresse IP de la machine sur laquelle opre le serveur d'cho - facultatif, par dfaut localhost. port port d'coute du service d'annuaire de cette machine - facultatif, par dfaut 1099 nom_service nom sous lequel a t enregistr le service demand (srvEcho pour notre exemple) Ce qui est rcupr, c'est une instance de l'interface distante interEcho. Si on suppose que le client et le serveur ne sont pas sur la mme machine, lorsqu'on compile le client cltEcho.java, on doit disposer dans le mme rpertoire, du fichier interEcho.class, rsultat de la compilation de l'interface distante interEcho, sinon on aura une erreur de compilation sur les lignes qui rfrencent cette interface.
- 363 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Aprs compilation de ces deux fichiers source, on a les fichiers .class suivants :
E:\data\java\RMI\echo\serveur>dir *.class SRVECH~1 CLA INTERE~1 CLA 1 129 256 09/03/99 09/03/99 15:58 srvEcho.class 15:58 interEcho.class
Dans les deux cas, la machine virtuelle Java indique qu'elle n'a pas trouv la classe srvEcho_stub. Effectivement, nous n'avons encore jamais entendu parler de cette classe. Dans le client, la localisation du serveur s'est faite avec l'instruction suivante :
serveur=(interEcho) Naming.lookup(urlService);
- 364 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
rmi protocole rmi localhost machine o opre le serveur - ici la mme machine sur laquelle le client. La syntaxe est normalement machine:port. En l'absence du port, c'est le port 1099 qui sera utilis par dfaut. A l'coute de ce port, se trouve le service d'annuaire du serveur. srvEcho c'est le nom du service particulier demand A la compilation, aucune erreur n'avait t signale. Il fallait simplement que le fichier interEcho.class de l'interface distante soit disponible. A l'excution, la machine virtuelle rclame la prsence d'un fichier srvEcho_stub.class si le service demand est le service srvEcho, de faon gnrale un fichier X_stub.class pour un service X. Ce fichier n'est ncessaire qu' l'excution pas la compilation du client. Il en est de mme pour le serveur. Qu'est-ce donc que ce fichier ? Sur le serveur, se trouve la classe srvEcho.class qui est notre objet/service distant. Le client, s'il n'a pas besoin de cette classe, a nammoins besoin d'une sorte d'image d'elle afin de pouvoir communiquer avec. En fait, le client n'adresse pas directement ses requtes l'objet distant : il les adresse son image locale srvEcho_stub.class situe sur la mme machine que lui. Cette image locale srvEcho_stub.class dialogue avec une image de mme nature (srvEcho_stub.class) situe cette fois sur le serveur. Cette image est cre partir du fichier .class du serveur avec un outil de Java appel rmic. Sous Windows, la commande : E:\data\java\RMI\echo\serveur>j:\jdk12\bin\rmic srvEcho va produire, partir du fichier srvEcho.class deux autres fichiers .class :
E:\data\java\RMI\echo\serveur>dir *.class SRVECH~2 CLA SRVECH~3 CLA 3 264 1 736 09/03/99 09/03/99 16:57 srvEcho_Stub.class 16:57 srvEcho_Skel.class
Il y a bien l, le fichier srvEcho_stub.class dont le client et le serveur ont besoin l'excution. Il y a galement un fichier srvEcho_Skel.class dont pour l'instant on ignore le rle. On fait une copie du fichier srvEcho_stub.class dans le rpertoire du client et du serveur et on supprime le fichier srvEcho_Skel.class. On a donc les fichiers suivants : du ct serveur :
E:\data\java\RMI\echo\serveur>dir *.class SRVECH~1 CLA INTERE~1 CLA SRVECH~1 CLA 1 129 256 3 264 09/03/99 09/03/99 09/03/99 15:58 srvEcho.class 15:58 interEcho.class 16:01 srvEcho_Stub.class
du ct client :
E:\data\java\RMI\echo\client>dir *.class CLTECH~1 CLA INTERE~1 CLA SRVECH~1 CLA 1 506 256 3 264 09/03/99 09/03/99 09/03/99 16:08 cltEcho.class 15:59 interEcho.class 16:01 srvEcho_Stub.class
- 365 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
l'enregistre dans l'annuaire des services de la machine sur laquelle opre le serveur d'cho
Ce dernier point ncessite la prsence d'un service d'annuaire. Celui-ci est lanc par la commande :
start j:\jdk12\bin\rmiregistry
rmiregistry est le service d'annuaire. Il est ici lanc en tche de fond dans une fentre Dos de Windows par la commande start. L'annuaire actif, on peut crer le service d'cho et l'enregistrer dans l'annuaire des services. L encore, il est lanc en tche de fond par une commande start :
E:\data\java\RMI\echo\serveur>start j:\jdk12\bin\java srvEcho
Le serveur d'cho s'excute dans une nouvelle fentre DOS et affiche comme on le lui avait demand :
Serveur d'cho prt
Le serveur est lanc comm prcdemment sur la machine Windows. Sur la machine linux, on a transfr les fichiers .class du client :
shiva[serge]:/home/admin/serge/java/rmi/client# $ dir total 9 drwxr-xr-x 2 serge admin 1024 Mar 10 10:02 . drwxr-xr-x 4 serge admin 1024 Mar 10 10:01 .. -rw-r--r-- 1 serge admin 1506 Mar 10 10:02 cltEcho.class -rw-r--r-- 1 serge admin 256 Mar 10 10:02 interEcho.class -rw-r--r-- 1 serge admin 3264 Mar 10 10:02 srvEcho_Stub.class
- 366 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On a donc une erreur : la machine virtuelle Java rclame apparemment le fichier srvEcho_skel.class qui avait t produit par l'utilitaire rmic mais qui jusqu' maintenant n'avait pas servi. On le recre et on le transfre galement sur la machine linux :
shiva[serge]:/home/admin/serge/java/rmi/client# $ dir total 11 drwxr-xr-x 2 serge admin 1024 Mar 10 10:17 . drwxr-xr-x 4 serge admin 1024 Mar 10 10:01 .. -rw-r--r-- 1 serge admin 1506 Mar 10 10:02 cltEcho.class -rw-r--r-- 1 serge admin 256 Mar 10 10:02 interEcho.class -rw-r--r-- 1 serge admin 1736 Mar 10 10:17 srvEcho_Skel.class -rw-r--r-- 1 serge admin 3264 Mar 10 10:02 srvEcho_Stub.class
On a la mme erreur que prcdemment... Alors on rflchit et on relit les docs sur RMI. On finit par se dire que c'est peut-tre le serveur lui-mme qui a besoin du fameux fichier srvEcho_Skel.class. On relance alors, sur la machine Windows, le serveur avec les deux fichiers srvEcho_Stub.class et srvEcho_Skel.class prsents :
E:\data\java\RMI\echo\serveur>dir *.class SRVECH~1 INTERE~1 SRVECH~2 SRVECH~3 CLA CLA CLA CLA 1 129 256 3 264 1 736 09/03/99 09/03/99 10/03/99 10/03/99 15:58 srvEcho.class 15:58 interEcho.class 9:05 srvEcho_Stub.class 9:05 srvEcho_Skel.class
puis sur la machine linux, on teste de nouveau le client et cette fois-ci, a marche :
shiva[serge]:/home/admin/serge/java/rmi/client# $ dir *.class -rw-r--r-- 1 serge admin 1506 Mar 10 10:02 cltEcho.class -rw-r--r-- 1 serge admin 256 Mar 10 10:02 interEcho.class -rw-r--r-- 1 serge admin 3264 Mar 10 10:02 srvEcho_Stub.class shiva[serge]:/home/admin/serge/java/rmi/client# $ java cltEcho rmi://tahe.istia.univ-angers.fr/srvEcho Message : msg1 Rponse serveur : [msg1] Message : msg2 Rponse serveur : [msg2] Message : fin
On en dduit donc, que ct serveur les deux fichiers srvEcho_Stub.class et srvEcho_Skel.class doivent tre prsents. Ct client, seul le fichier srvEcho_Stub.class a t ncessaire jusqu' maintenant. Il s'tait avr indispensable lorsque le client et le serveur taient sur la mme machine Windows. Sous linux, on l'enlve pour voir...
shiva[serge]:/home/admin/serge/java/rmi/client# $ dir *.class -rw-r--r-- 1 serge admin 1506 Mar 10 10:02 cltEcho.class -rw-r--r-- 1 serge admin 256 Mar 10 10:02 interEcho.class shiva[serge]:/home/admin/serge/java/rmi/client# $ java cltEcho rmi://tahe.istia.univ-angers.fr/srvEcho *** Security Exception: No security manager, stub class loader disabled *** java.rmi.RMISecurityException: security.No security manager, stub class loader disabled at sun.rmi.server.RMIClassLoader.getClassLoader(RMIClassLoader.java:84) at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:88) at java.io.ObjectInputStream.inputClassDescriptor(ObjectInputStream.java) at java.io.ObjectInputStream.readObject(ObjectInputStream.java) at java.io.ObjectInputStream.inputObject(ObjectInputStream.java) at java.io.ObjectInputStream.readObject(ObjectInputStream.java) at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:105) at java.rmi.Naming.lookup(Naming.java:60) at cltEcho.main(cltEcho.java:28) Erreur : java.rmi.UnexpectedException: Unexpected exception; nested exception is:
- 367 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On a une erreur intressante qui a l'air de dire que la machine virtuelle Java a voulu charger la fameuse classe stub mais qu'il a chou en l'absence d'un security manager . On se dit qu'on a vu quelque chose sur ce thme dans les docs. On s'y replonge... et on trouve que le serveur doit crer et installer un gestionnaire de scurit (security manager) qui garantisse aux clients qui demandent le chargement de classes que celles-ci sont saines. En l'absence de ce security manager, ce chargement de classes est impossible. Ca semble coller : notre client linux a demand la classe srvEcho_stub.class dont il a besoin au serveur et celui-ci a refus en disant qu'aucun gestionnaire de scurit n'avait t install. On modifie donc le code de la fonction main du serveur de la faon suivante :
// cration du service public static void main (String arg[]){ // installation d'un gestionnaire de scurit System.setSecurityManager(new RMISecurityManager()); // lancement et enregistrement du service try{ srvEcho serveurEcho=new srvEcho(); Naming.rebind("srvEcho",serveurEcho); System.out.println("Serveur d'cho prt"); } catch (Exception e){ System.err.println(" Erreur " + e + " lors du lancement du serveur d'cho "); } }// main
On compile et on produit les fichiers srvEcho_stub.class et srvEcho_Skel.class avec l'outil rmic. On lance le service d'annuaire (rmiregistry) puis le serveur et on a une erreur qu'auparavant on n'avait pas !
Erreur java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve) lors du lancement du serveur d'cho
Le gestionnaire de scurit semble avoir t trop efficace. On lit de nouveau les docs... On s'aperoit que lorsqu'un gestionnaire de scurit est actif, il faut prciser au lancement d'un programme ses droits. Cela se fait avec l'option suivante :
start j:\jdk12\bin\java -Djava.security.policy=mypolicy srvEcho
o java.security.policy est un mot cl mypolicy est un fichier texte dfinissant les droits du programme. Ici, c'est le suivant :
grant { // Allow everything for now permission java.security.AllPermission; };
Le programme a ici tous les droits. On recommence. On se place dans le rpertoire du serveur et on fait successivement : lancement du service d'annuaire : start j:\jdk12\bin\rmiregistry lancement du serveur : start j:\jdk12\bin\java -Djava.security.policy=mypolicy srvEcho
Et cette fois, le serveur d'cho (le client pas encore) se lance correctement. Maintenant vous pouvez faire l'exprience suivante :
- 368 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
arrtez le serveur d'cho puis le service d'annuaire relancez le service d'annuaire en tant dans un autre rpertoire que celui du serveur revenez sur le rpertoire du serveur lancez le serveur d'cho - vous obtenez l'erreur suivante :
Erreur java.rmi.ServerException: RemoteException occurred in server thread; nes ted exception is: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.lang.ClassNotFoundException: srvEcho_Stub lors du lancement du serveur d'cho
On en dduit que le rpertoire partir duquel le service d'annuaire est lanc a de l'importance. Ici, Java n'a pas trouv la classe srvEcho_stub.class parce que le service d'annuaire n'a pas t lanc du rpertoire du serveur. Lors du lancement du serveur, on peut prciser dans quel rpertoire se trouvent les classes ncessaires au serveur :
start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=file:/e:/data/java/rmi/echo/serveur/ srvEcho
La commande est sur une unique ligne. Le mot cl java.rmi.server.codebase sert indiquer l'URL du rpertoire contenant les classes ncessaires au serveur. Ici, cette URL prcise le protocole file qui est le protocole d'accs aux fichiers locaux et le rpertoire contenant les fichiers .class du serveur. Si donc on procde comme suit : arrt du service d'annuaire relancer le service d'annuaire partir d'un autre rpertoire que celui du serveur dans le rpertoire du serveur, lancer celui-ci avec la commande (une seule ligne) :
start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=file:/e:/data/java/rmi/echo/serveur/ srvEcho
Le serveur est alors lanc correctement. On peut donc passer au client. On le teste :
shiva[serge]:/home/admin/serge/java/rmi/client# $ dir *.class -rw-r--r-- 1 serge admin 1506 Mar 10 14:28 cltEcho.class -rw-r--r-- 1 serge admin 256 Mar 10 10:02 interEcho.class shiva[serge]:/home/admin/serge/java/rmi/client# $ java cltEcho rmi://tahe.istia.univ-angers.fr/srvEcho *** Security Exception: No security manager, stub class loader disabled *** java.rmi.RMISecurityException: security.No security manager, stub class loader disabled at sun.rmi.server.RMIClassLoader.getClassLoader(RMIClassLoader.java:84) at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:88) at java.io.ObjectInputStream.inputClassDescriptor(ObjectInputStream.java) at java.io.ObjectInputStream.readObject(ObjectInputStream.java) at java.io.ObjectInputStream.inputObject(ObjectInputStream.java) at java.io.ObjectInputStream.readObject(ObjectInputStream.java) at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:105) at java.rmi.Naming.lookup(Naming.java:60) at cltEcho.main(cltEcho.java:31) Erreur : java.rmi.UnexpectedException: Unexpected exception; nested exception is: java.rmi.RMISecurityException: security.No security manager, stub class loader disabled
On obtient la mme erreur signalant l'absence d'un gestionnaire de scurit. On se dit qu'on s'est peut-tre tromp et que c'est le client qui doit se crer son gestionnaire de scurit. On laisse le serveur avec son gestionnaire de scurit mais on en cre un pour le client galement. La fonction main du client cltEcho.java devient alors :
public static void main(String arg[]){ // syntaxe : cltEcho machine port // machine : machine o opre le serveur d'cho
- 369 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// port : port o opre l'annuaire des services sur la machine du service d'cho // vrification des arguments if(arg.length!=1){ System.err.println("Syntaxe : pg url_service_rmi"); System.exit(1); } // installation d'un gestionnaire de scurit System.setSecurityManager(new RMISecurityManager()); // dialogue client-serveur String urlService=arg[0]; BufferedReader in=null; String msg=null; String reponse=null; interEcho serveur=null; try{ .... } catch (Exception e){ .... }// try }// main
On procde ensuite comme suit : on recompile cltEcho.java on transfre les fichiers .class sur la machine linux
shiva[serge]:/home/admin/serge/java/rmi/client# $ dir *.class -rw-r--r-1 serge admin 1506 Mar 10 14:28 cltEcho.class -rw-r--r-1 serge admin 256 Mar 10 10:02 interEcho.class
on lance le client
$ java cltEcho rmi://tahe.istia.univ-angers.fr/srvEcho java.io.FileNotFoundException: /e:/data/java/rmi/echo/serveur/srvEcho_Stub.class at java.io.FileInputStream.<init>(FileInputStream.java) at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:150) at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:170) at sun.applet.AppletClassLoader.loadClass(AppletClassLoader.java:119) at sun.applet.AppletClassLoader.findClass(AppletClassLoader.java:496) at sun.applet.AppletClassLoader.loadClass(AppletClassLoader.java:199) at sun.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:159) at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:97) at java.io.ObjectInputStream.inputClassDescriptor(ObjectInputStream.java) at java.io.ObjectInputStream.readObject(ObjectInputStream.java) at java.io.ObjectInputStream.inputObject(ObjectInputStream.java) at java.io.ObjectInputStream.readObject(ObjectInputStream.java) at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:105) at java.rmi.Naming.lookup(Naming.java:60) at cltEcho.main(cltEcho.java:31) File not found when looking for: srvEcho_Stub Erreur : java.rmi.UnmarshalException: Return value class not found; nested exception is: java.lang.ClassNotFoundException: srvEcho_Stub
Malgr les apparences, on progresse : l'erreur n'est plus la mme. On constate que le client a pu demander au serveur la classe srvEcho_Stub.class, mais que celui-ci ne l'a pas trouv. Donc, le client doit avoir un gestionnaire de scurit s'il veut pouvoir demander des classes au serveur. Si on regarde l'erreur prcdente, on voit que le fichier srvEcho_Stub.class a t cherch dans le rpertoire e:/data/ java/rmi/echo/serveur/ et qu'il n'a pas t trouv. C'est pourtant bien l qu'il est. Si on regarde plus prcisment, la liste des mthodes impliques dans l'erreur, on trouve celle-ci :
- 370 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
sun.net.www.protocol.file.FileURLConnection.getInputStream. Le client semble avoir ouvert un flux avec un objet de type FileURLConnection. On se dit que tout a a un rapport avec la faon dont on a lanc notre serveur :
start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=file:/e:/data/java/rmi/echo/serveur/ srvEcho
Le message d'erreur semble faire rfrence la valeur du mot cl java.rmi.server.codebase. Lorsqu'on regarde les docs de nouveau, on voit que la valeur de ce mot cl est, dans les exemples donns, toujours : http://.., c.a.d. que le protocole utilis est http. Il n'apparat pas clairement comment le client demande et obtient ses classes auprs du serveur. Peut-tre les demande-t-il avec l'URL du mot cl java.rmi.server.codebase, URL prcise au lancement du serveur. On dcide donc de lancer le serveur par la nouvelle commande suivante :
start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=http://tahe.istia.univ-angers.fr/rmi/echo/ srvEcho
Le protocole est maintenant http. On est oblig de dplacer les fichiers .class un endroit accessible au serveur http de la machine sur laquelle seront stockes les classes. Dans notre exemple, le serveur tourne sur une machine windows avec un serveur http PWS de Microsoft. La racine de ce serveur est d:\Inetpub\wwwroot. Aussi procdet-on de la faon suivante : on cre le rpertoire d:\Inetpub\wwwroot\rmi\echo on y place les fichiers .class du serveur ainsi que le fichier mypolicy on lance le serveur Web si ce n'est dj fait on relance le service d'annuaire (rmiregistry) on relance le serveur avec la commande
start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=http://tahe.istia.univ-angers.fr/rmi/echo/ srvEcho
Ouf ! Ca marche. Le client a bien russi rcuprer le fameux fichier srvEcho_Stub.class. Tout a nous a donn des ides, et on se demande si le client qui se trouve sur la machine Windows du serveur, fonctionnerait lui aussi sans le fichier srvEcho_Stub.class. On passe dans le rpertoire du client, on supprime le fichier srvEcho_Stub.class s'il s'y trouve et on lance le client de la mme faon que sous Linux :
E:\data\java\RMI\echo\client>dir *.class CLTECH~1 CLA 1 622 10/03/99 14:12 cltEcho.class INTERE~1 CLA 256 09/03/99 15:59 interEcho.class E:\data\java\RMI\echo\client>j:\jdk12\bin\java -Djava.security.policy=mypolicy cltEcho rmi://tahe.istia.univ-angers.fr/srvEcho
- 371 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
VIII-B-1-h - Rsum
Ct serveur Windows : le serveur a un gestionnaire de scurit il a t lanc avec des options : start j:\jdk12\bin\java -Djava.security.policy=mypolicy
-Djava.rmi.server.codebase=http://tahe.istia.univ-angers.fr/rmi/echo/ srvEcho Ct client Linux ou Windows le client a un gestionnaire de scurit sur linux, il a t lanc par java cltEcho rmi://tahe.istia.univ-angers.fr/srvEcho sur windows, il a t lanc par j:\jdk12\bin\java -Djava.security.policy=mypolicy cltEcho rmi://tahe.istia.univangers.fr/srvEcho
parce que la classe srvEcho_Stub.class va tre demande par les clients, le rpertoire choisi pour les classes du serveur est un rpertoire accessible au serveur http de la machine Linux. Ici l'URL de ce rpertoire est http://shiva.istia.univangers.fr/~serge/rmi/echo/serveur le service d'annuaire est lanc en tche de fond : /usr/local/bin/jdk/rmiregistry & le serveur est lanc en tche de fond : /usr/local/bin/jdk/bin/javaDjava.rmi.server.codebase=http:// shiva.istia.univ-angers.fr/~serge/rmi/echo/serveur/srvEcho &
On peut tester les clients. Le client Windows d'abord. on passe dans le rpertoire du client sur la machine windows on lance le client par la commande :
E:\data\java\RMI\echo\client>j:\jdk12\bin\java -Djava.security.policy=mypolicy cltEcho rmi://shiva.istia.univ-angers.fr/srvEcho Message : msg1 Rponse serveur : [msg1] Message : fin
- 372 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
A noter que pour le client linux qui fonctionne sur la mme machine que le serveur d'cho, il n'a pas t besoin de prciser de machine dans l'URL du service demand.
VIII-C - Deuxime exemple : Serveur SQL sur machine Windows VIII-C-1 - Le problme
Nous avons vu dans le chapitre JDBC comment grer des bases de donnes relationnelles. Dans les exemples prsents, les applications et la base de donnes utilise taient sur la mme machine Windows. On se propose ici, d'crire un serveur RMI sur une machine Windows, qui permettrait aux clients distants d'exploiter les bases ODBC publiques du poste sur lequel se trouve le serveur.
Le client RMI pourrait faire 3 oprations : se connecter la base de son choix mettre des requtes SQL fermer la connexion
Le serveur excute les requtes SQL du client et lui envoie les rsultats. C'est son travail essentiel et c'est pourquoi nous l'appellerons un serveur SQL. Nous appliquons les diffrentes tapes vues prcdemment avec le serveur d'cho.
Le rle des diffrentes mthodes est le suivant : connect le client se connecte une base de donnes distante dont il donne le pilote, l'url JDBC ainsi que son identit id et son mot de passe mdp pour accder cette base. Le serveur lui rend une chane de caractres indiquant le rsultat de la connexion :
200 - Connexion russie 500 - Echec de la connexion
executeSQL le client demande l'excution d'une requte SQL sur la base laquelle il est connect. Il indique le caractre qui doit sparer les champs dans les rsultats qui lui sont renvoys. Le serveur renvoie un tableau de chanes :
100 n pour une requte de mise jour de la base, n tant le nombre de lignes mises jour 500 msg d'erreur si la requte a gnr une erreur 501 Pas de rsultats si la requte n'a gnr aucun rsultat 101 ligne1 101 ligne2 101 ...
si la requte a gnr des rsultats. Les lignes ainsi renvoyes par le serveur sont les lignes rsultats de la requte. close le client ferme sa connexion avec la base distante. Le serveur renvoie une chane indiquant le rsultat de cette fermeture :
200 Base ferme 500 Erreur lors de la fermeture de la base (msg d'erreur)
- 374 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// connexion la base url grce au driver pilote // identification avec identit id et mot de passe mdp String resultat=null; // rsultat de la mthode try{ // chargement du pilote Class.forName(pilote); // demande de connexion DB=DriverManager.getConnection(url,id,mdp); // ok resultat="200 Connexion russie"; } catch (Exception e){ // erreur resultat="500 Echec de la connexion (" + e + ")"; } // fin return resultat; } // ------------- executeSQL public String[] executeSQL(String requete, String separateur) throws RemoteException{ // excute une requte SQL sur la base DB // et met les rsultats dans un tableau de chanes // donnes ncessaires l'excution de la requte Statement S=null; ResultSet RS=null; String[] lignes=null; Vector resultats=new Vector(); String ligne=null; try{ // cration du conteneur de la requte S=DB.createStatement(); // excution requte if (! S.execute(requete)){ // requte de mise jour // on renvoie le nombre de lignes mises jour lignes=new String[1]; lignes[0]="100 "+S.getUpdateCount(); return lignes; } // c'tait une requte d'interrogation // on rcupre les rsultats RS=S.getResultSet(); // nombre de champs du Resultset int nbChamps=RS.getMetaData().getColumnCount(); // on les exploite while(RS.next()){ // cration de la ligne des rsultats ligne="101 "; for (int i=1;i<nbChamps;i++) ligne+=RS.getString(i)+separateur; ligne+=RS.getString(nbChamps); // ajout au vecteur des rsultats resultats.addElement(ligne); }// while // fin de l'exploitation des rsultats // on libre les ressources RS.close(); S.close(); // on rend les rsultats int nbLignes=resultats.size(); if (nbLignes==0){ lignes=new String[1]; lignes[0]="501 Pas de rsultats"; } else { lignes=new String[resultats.size()]; for(int i=0;i<lignes.length;i++) lignes[i]=(String) resultats.elementAt(i);
- 375 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
}//if return lignes; } catch (Exception e){ // erreur lignes=new String[1]; lignes[0]="500 " + e; return lignes; }// try-catch }// executeSQL // --------------- close public String close() throws RemoteException { // ferme la connexion la base de donnes String resultat=null; try{ DB.close(); resultat="200 Base ferme"; } catch (Exception e){ resultat="500 Erreur la fermeture de la base ("+e+")"; } // renvoi du rsultat return resultat; } // ----------- main public static void main (String[] args){ // gestionnaire de scurit System.setSecurityManager(new RMISecurityManager()); // lancement du service srvSQL serveurSQL=null; try{ // cration serveurSQL=new srvSQL(); // enregistrement Naming.rebind("srvSQL",serveurSQL); // suivi System.out.println("Serveur SQL prt"); } catch (Exception e){ // erreur System.err.println("Erreur lors du lancement du serveur SQL ("+ e +")"); }// try-catch }// main }// classe
- 376 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null , avec ici : urlserviceAnnuaire pilote urlBase srvSQL nom rmi du serveur SQL sun.jdbc.odbc.JdbcOdbcDriver le pilote usuel des bases avec interface odbc jdbc:odbc:articles pour utiliser une base articles dclare dans la liste des bases publiques ODBC de la machine Windows null pas d'identit null pas de mot de passe , les champs des rsultats seront spars par une virgule
id mdp separateur
Une fois lanc avec les paramtres prcdents, le client suit les tapes suivantes : il se connecte au serveur RMI srvSQL, donc un serveur RMI sur la mme machine que le client il demande la connexion la base de donnes articles connect(#'sun.jdbc.odbc.JdbcOdbcDriver'', ##jdbc:odbc:articles'', '''', '''') il demande l'utilisateur de taper une requte SQL au clavier il l'envoie au serveur SQL executeSQL(requete, '',''); il affiche l'cran les rsultats renvoys par le serveur il redemande l'utilisateur de taper une requte SQL au clavier. Il s'arrtera lorsque la requte est fin.
- 377 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String urlService=arg[0]; String pilote=arg[1]; String urlBase=arg[2]; String id, mdp, separateur; if(arg[3].equals("null")) id=""; else id=arg[3]; if(arg[4].equals("null")) mdp=""; else mdp=arg[4]; if(arg[5].equals("null")) separateur=" "; else separateur=arg[5]; // installation d'un gestionnaire de scurit System.setSecurityManager(new RMISecurityManager()); // dialogue client-serveur String requete=null; String reponse=null; String[] lignes=null; String codeErreur=null; try{ // ouverture du flux clavier in=new BufferedReader(new InputStreamReader(System.in)); // suivi System.out.println("--> Connexion au serveur RMI en cours..."); // localisation du service serveurSQL=(interSQL) Naming.lookup(urlService); // suivi System.out.println("--> Connexion la base de donnes en cours"); // demande de connexion initiale la base de donnes reponse=serveurSQL.connect(pilote,urlBase,id,mdp); // suivi System.out.println("<-- "+reponse); // analyse rponse codeErreur=reponse.substring(0,3); if(codeErreur.equals("500")) erreur("Abandon sur erreur de connexion la base",3); // boucle de lecture des requtes envoyer au serveur SQL System.out.print("--> Requte : "); requete=in.readLine().toLowerCase().trim(); while(! requete.equals("fin")){ // envoi de la requte au serveur et rception de la rponse lignes=serveurSQL.executeSQL(requete,separateur); // suivi afficheLignes(lignes); // requte suivante System.out.print("--> Requte : "); requete=in.readLine().toLowerCase().trim(); }// while // suivi System.out.println("--> Fermeture de la connexion la base de donnes distante"); // on clt la connexion reponse=serveurSQL.close(); // suivi System.out.println("<-- " + reponse); // fin System.exit(0); // gestion des erreurs } catch (Exception e){ erreur("Abandon sur erreur : " + e,2); }// try }// main // ----------- AfficheLignes private static void afficheLignes(String[] lignes){ for (int i=0;i<lignes.length;i++) System.out.println("<-- " + lignes[i]); }// afficheLignes // ------------ erreur private static void erreur(String msg, int exitCode){ // affichage msg d'erreur System.err.println(msg); // libration ventuelle des ressources try{
- 378 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
in.close(); serveurSQL.close(); } catch(Exception e){} // on quitte System.exit(exitCode); }// erreur }// classe
on compile le client
E:\data\java\RMI\sql\client>j:\jdk12\bin\javac cltSQL.java E:\data\java\RMI\sql\client>dir *.class INTERS~1 CLTSQL~1 SRVSQL~1 SRVSQL~2 CLA CLA CLA CLA 451 2 839 4 491 2 414 11/03/99 12/03/99 11/03/99 11/03/99 10:55 18:00 13:19 13:19 interSQL.class cltSQL.class srvSQL_Stub.class srvSQL_Skel.class
VIII-C-6 - tape 4 : Tests avec serveur & client sur mme machine windows
le service d'annuaire est lanc dans un rpertoire autre que celui du serveur et du client
F:\>start j:\jdk12\bin\rmiregistry
- 379 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
on lance le serveur
E:\data\java\RMI\sql\serveur>start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=file:/e:/data/java/rmi/sql/serveur/ srvSQL
on lance le client
E:\data\java\RMI\sql\client>j:\jdk12\bin\java -Djava.security.policy=mypolicy cltSQL srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null , --> --> <---> <-<-<-<-<-<-<-<-<---> <---> <-<-<-<-<-<-<-<-<---> --> <-Connexion au serveur RMI en cours... Connexion la base de donnes en cours 200 Connexion russie Requte : select nom, stock_actu from articles order by stock_actu desc 101 vlo,31 101 essai3,13 101 skis nautiques,13 101 cano,13 101 panthre,11 101 lopard,11 101 cachalot,10 101 fusil,10 101 arc,10 Requte : update articles set stock_actu=stock_actu-1 where stock_actu<=11 100 5 Requte : select nom,stock_actu from articles order by stock_actu asc 101 cachalot,9 101 fusil,9 101 arc,9 101 panthre,10 101 lopard,10 101 essai3,13 101 skis nautiques,13 101 cano,13 101 vlo,31 Requte : fin Fermeture de la connexion la base de donnes distante 200 Base ferme
VIII-C-7 - tape 5 : Tests avec serveur sur machine windows et client sur machine
on arrte ventuellement le serveur et le service d'annuaire on transfre les fichiers .class du client sur une machine linux
shiva[serge]:/home/admin/serge/java/rmi/sql/client# $ dir *.class -rw-r--r-- 1 serge admin 2839 Mar 11 14:37 cltSQL.class -rw-r--r-- 1 serge admin 451 Mar 11 14:37 interSQL.class
les fichiers du serveur sont mis dans un rpertoire accessible au serveur http de la machine windows
D:\Inetpub\wwwroot\rmi\sql>dir INTERS~1 CLA SRVSQL~1 CLA 451 3 238 11/03/99 10:55 interSQL.class 11/03/99 13:19 srvSQL.class
- 380 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
4 491 2 414 81
on relance le serveur avec des paramtres diffrents que ceux utiliss dans le test prcdent
D:\Inetpub\wwwroot\rmi\sql>start j:\jdk12\bin\java -Djava.security.policy=mypolicy -Djava.rmi.server.codebase=http://tahe.istia.univ-angers.fr/rmi/sql/ srvSQL
VIII-C-8 - Conclusion
On a l une application intressante en ce qu'elle permet l'accs une base de donnes partir d'un poste quelconque du rseau. On aurait trs bien pu l'crire de faon traditionnelle avec des sockets et ce qui est d'ailleurs demand dans un exercice du chapitre sur les bases de donnes. Si on crivait cette application de faon traditionnelle : on aurait un client et un serveur qui pourraient tre crits avec des langages diffrents le client et le serveur communiqueraient par change de lignes de texte et auraient un dialogue qui pourrait tre du genre :
client : connect machine port pilote urlBase id mdp o les deux premiers paramtres spcifient o trouver le serveur, les quatre suivants indiquant les paramtres de connexion la base de donnes exploiter
- 381 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le serveur pourrait rpondre par quelque chose du genre : 200 - Connexion russie 500 - Echec de la connexion client : executeSQL requete, separateur pour demander au serveur d'excuter une requte SQL sur la base connecte au client. separateur tant le caractre sparateur des champs dans les lignes de la rponse. Le serveur pourrait rpondre quelque chose du genre
100 n pour une requte de mise jour de la base, n tant le nombre de lignes mises jour 500 msg d'erreur si la requte a gnr une erreur 501 Pas de rsultats si la requte n'a gnr aucun rsultat 101 ligne1 101 ligne2 101 ...
si la requte a gnr des rsultats. Les lignes ainsi renvoyes par le serveur sont les lignes rsultats de la requte. client : close pour fermer la connexion avec la base distante. Le serveur pourrait renvoyer une chane indiquant le rsultat de cette fermeture : 200 Base ferme 500 Erreur lors de la fermeture de la base (msg d'erreur) On voit ici que si on est capable de construire une application traditionnelle avec un protocole du genre prcdent, on peut en dduire une structure possible du serveur RMI. L o dans le protocole on a une phrase du client vers le serveur du genre : commande param1 param2 ... paramq on pourra avoir au sein du serveur RMI une mthode String commande(param1,param2,..., paramq) et cette mthode accessible au client devra donc faire partie de l'interface publie du serveur. Pour en terminer l, notons que notre serveur ne gre actuellement qu'un client : il ne peut en grer plusieurs, tel qu'il est crit actuellement. En effet, si un client se connecte une base B1, un objet Connection DB=DB1 est cr par le serveur. Si un second client demande une connexion une base B2, le serveur le note en faisant Connection DB=DB2, cassant ainsi la connexion du premier client la base B1.
- 382 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
VIII-D-2 - Exercice 2
crire l'applet Java de commerce lectronique prsente dans les exercices du chapitre JDBC afin qu'elle travaille avec le serveur RMI de l'exercice prcdent.
- 383 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Nous allons voir que la construction avec CORBA d'une application distribue est proche de la mthode employe avec Java RMI : les concepts se ressemblent. CORBA prsente l'avantage de l'interoprabilit avec des applications crites dans d'autres langages.
Nous prenons comme premier exemple, celui du serveur d'cho dj utilis dans le contexte RMI. Le lecteur pourra ainsi voir les diffrences entre les deux mthodes. L'application a t teste avec le jdk1.2.
- 384 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
La description de l'interface sera stocke dans un fichier echo.idl. Elle est crite dans le langage IDL (Interface Definition Language) de l'OMG. Pour tre exploitable, elle doit tre analyse par un programme qui va crer des fichiers source dans le langage utilis pour dvelopper l'application CORBA. Ici, nous utiliserons le programme idltojava.exe qui partir de l'interface prcdente va crer les fichiers source .java ncessaires l'application. Le programme idltojava.exe n'est pas livr avec le JDK. On peut se le procurer sur le site de Sun http://java.sun.com. Analysons les quelques lignes de l'interface idl prcdente : module echo est quivalent package echo de Java. La compilation de l'interface va donner naissance au package java echo c.a.d. un rpertoire contenant des classes Java. interface iSrvEcho est quivalent interface iSrvEcho de Java. Va donner naissance une interface Java. string echo(in string msg) est quivalent l'instruction Java String echo(String msg). Les types du langage IDL ne correspondent pas exactement ceux du langage Java. On trouvera les correspondances un peu plus loin dans ce chapitre. Dans le langage IDL, les paramtres d'une fonction peuvent tre des paramtres d'entre (in), de sortie (out), d'entre-sortie (inout). Ici, la mthode echo reoit un paramtre d'entre msg qui est une chane de caractres et renvoie une chane de caractres comme rsultat. L'interface prcdente est celle de notre serveur d'cho. On rappelle qu'une interface distante dcrit les mthodes de l'objet serveur accessibles aux clients. Ici, seule la mthode echo sera disponible pour les clients.
L'option -fno-cpp sert indiquer qu'il n'y a pas utiliser de pr-processeur (utilis avec le C/C++ le plus souvent). La compilation du fichier echo.idl produit un sous-rpertoire echo avec dedans les fichiers suivants :
E:\data\java\corba\ECHO>dir echo _ISRVE~1 ISRVEC~1 ISRVEC~2 ISRVEC~3 _ISRVE~2 JAV JAV JAV JAV JAV 1 095 311 825 1 827 1 803 17/03/99 17/03/99 17/03/99 17/03/99 17/03/99 17:19 17:19 17:19 17:19 17:19 _iSrvEchoStub.java iSrvEcho.java iSrvEchoHolder.java iSrvEchoHelper.java _iSrvEchoImplBase.java
- 385 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On voit que c'est quasiment la traduction mot mot de l'interface IDL. Si on a la curiosit de regarder le contenu des autres fichiers .java, on trouvera des choses plus complexes. Voici ce que dit la documentation sur le rle de ces diffrents fichiers : iSrvEcho.java l'interface du serveur _iSrvEchoImplbase.java implmente l'interface iSrvEcho prcdente. C'est une classe abstraite, squelette du serveur fournissant au serveur les fonctionnalits CORBA ncessaires l'application distribue. _iSrvEchoStub.java C'est l'image ( stub ) du serveur dont usera le client. Elle fournit au client les fonctionnalits CORBA pour atteindre le serveur. iSrvEchoHelper.java Fournit les mthodes ncessaires la gestion des rfrences d'objets CORBA iSrvEchoHolder.java Fournit les mthodes ncessaires la gestion des paramtres d'entre-sortie des mthodes de l'interface.
- 386 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
ISRVEC~3 CLA
858
Le code se comprend de lui-mme. Cette classe est enregistre dans le fichier srvEcho.java dans le rpertoire parent de celui du package de l'interface iSrvEcho. On peut compiler pour vrifier :
E:\data\java\corba\ECHO>j:\jdk12\bin\javac srvEcho.java E:\data\java\corba\ECHO>dir ECHO IDL SRVECH~1 CLA SRVECH~1 JAV ECHO <REP> 78 15/03/99 13:56 ECHO.IDL 488 18/03/99 11:30 srvEcho.class 252 15/03/99 14:02 srvEcho.java 17/03/99 17:19 echo
- 387 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
String machine=arg[0]; String port=arg[1]; String nomService=arg[2]; try{ // il nout faut un objet CORBA pour travailler String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port}; ORB orb=ORB.init(initORB,null); // on met le service dans l'annuaire des services // il s'appellera srvEcho org.omg.CORBA.Object objRef= orb.resolve_initial_references("NameService"); NamingContext ncRef=NamingContextHelper.narrow(objRef); NameComponent nc= new NameComponent(nomService,""); NameComponent path[]={nc}; // on cre le serveur et on l'associe au service srvEcho srvEcho serveurEcho=new srvEcho(); ncRef.rebind(path,serveurEcho); orb.connect(serveurEcho); // suivi System.out.println("Serveur d'cho prt"); // attente des demandes des clients java.lang.Object sync=new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch(Exception e){ // il y a eu une erreur System.err.println("Erreur " + e); e.printStackTrace(System.err); } }// main }// serveurEcho
Nous expliquons ci-aprs les grandes lignes du lancement du serveur sans entrer dans les dtails qui sont complexes au premier abord. Il faut retenir de l'exemple prcdent ses grandes lignes qui vont revenir dans tout serveur CORBA.
- 388 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Les couples (paramtre, valeur) utiliss sont les suivants : ("-ORBInitialHost",machine) ce couple prcise la machine ou opre l'annuaire des services CORBA, ici la machine passe en paramtre au serveur. ("-ORBInitialPort",port ) ce couple prcise le port ou opre l'annuaire des services CORBA, ici le port pass en paramtre au serveur. Le second paramtre de la mthode init est laiss null. Si on avait laiss le premier paramtre galement null, le couple (machine,port) utilis aurait t par dfaut (localhost,900).
La premire partie du code consiste prparer le nom du service. Ce nom est symbolis dans le code par la variable path. Le nom d'un service comprend plusieurs composantes : une composante initiale objRef, objet gnrique qui doit tre ramen un type NamingContext, ici ncRef. le nom du service, ici nomService qui a t pass en paramtre au serveur
Ces composantes du nom (NameComponent) sont rassembles dans un tableau, ici path. C'est ce tableau qui nomme de faon prcise le service cr. Une fois le nom cr, il reste l'associer un exemplaire du serveur (la classe srvEcho construite prcdemment)
srvEcho serveurEcho=new srvEcho();
- 389 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le client se connecte au service d'cho puis demande l'utilisateur de taper des messages au clavier. Ceux-ci sont envoys au serveur d'cho qui les renvoie. Un suivi de ce dialogue est fait l'cran. Le client CORBA du service d'cho ressemble beaucoup au client RMI dj crit. L encore, le client doit se connecter un service d'annuaire pour obtenir une rfrence de l'objet-serveur auquel il veut se connecter. La diffrence entre les deux clients rside l et uniquement l. Voici le code du client CORBA d'cho :
// packages imports import java.io.*; import echo.*; import org.omg.CosNaming.*; import org.omg.CORBA.*; // ---------- classe cltEcho public class cltEcho { public static void main(String arg[]){ // syntaxe : cltEcho machineAnnuaire portAnnuaire nomservice // machine : machine o opre l'annuaire des services CORBA // port : port o opre l'annuaire des services // nomService : nom du service d'cho // vrification des arguments if(arg.length!=3){ System.err.println("Syntaxe : pg machineAnnuaire portAnnuaire nomservice"); System.exit(1); } // on rcupre les paramtres String machine=arg[0]; String port=arg[1]; String nomService=arg[2]; // on fait la liaison avec le serveur d'cho iSrvEcho serveurEcho=getServeurEcho(machine,port,nomService);
- 390 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// dialogue client-serveur BufferedReader in=null; String msg=null; String reponse=null; iSrvEcho serveur=null; try{ // ouverture du flux clavier in=new BufferedReader(new InputStreamReader(System.in)); // boucle de lecture des msg envoyer au serveur d'cho System.out.print("Message : "); msg=in.readLine().toLowerCase().trim(); while(! msg.equals("fin")){ // envoi du msg au serveur et rception de la rponse reponse=serveurEcho.echo(msg); // suivi System.out.println("Rponse serveur : " + reponse); // msg suivant System.out.print("Message : "); msg=in.readLine().toLowerCase().trim(); }// while // c'est fini System.exit(0); // gestion des erreurs } catch (Exception e){ System.err.println("Erreur : " + e); System.exit(2); }// try }// main // ---------------------- getServeurEcho private static iSrvEcho getServeurEcho(String machine, String port, String nomService){ // demande une rfrence du serveur d'cho // suivi System.out.println("--> Connexion au serveur CORBA en cours..."); // la rfrence du serveur d'cho iSrvEcho serveurEcho=null; try{ // on demande un objet CORBA pour travailler String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port}; ORB orb=ORB.init(initORB,null); // on utilise le service d'annuaire pour localiser le serveur d'cho org.omg.CORBA.Object objRef= orb.resolve_initial_references("NameService"); NamingContext ncRef=NamingContextHelper.narrow(objRef); // le service recherch s'appelle srvEcho - on le demande NameComponent nc= new NameComponent(nomService,""); NameComponent path[]={nc}; serveurEcho=iSrvEchoHelper.narrow(ncRef.resolve(path)); } catch (Exception e){ System.err.println("Erreur lors de la localisation du serveur d'cho (" + e + ")"); System.exit(10); }// try-catch // on rend la rfrence au serveur return serveurEcho; }// getServeurEcho }// classe
- 391 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
A l'issue de cette opration, le client dtient une rfrence du serveur d'cho. Ensuite un client CORBA ne diffre pas d'un client RMI. La mthode prive qui assure la connexion au serveur est la suivante :
// ---------------------- getServeurEcho private static iSrvEcho getServeurEcho(String machine, String port, String nomService){ // demande une rfrence du serveur d'cho // suivi System.out.println("--> Connexion au serveur CORBA en cours..."); // la rfrence du serveur d'cho iSrvEcho serveurEcho=null; try{ // on demande un objet CORBA pour travailler String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port}; ORB orb=ORB.init(initORB,null); // on construit le nom du serveur d'cho org.omg.CORBA.Object objRef= orb.resolve_initial_references("NameService"); NamingContext ncRef=NamingContextHelper.narrow(objRef); NameComponent nc= new NameComponent(nomService,""); NameComponent path[]={nc}; // on demande le service serveurEcho=iSrvEchoHelper.narrow(ncRef.resolve(path)); } catch (Exception e){ System.err.println("Erreur lors de la localisation du serveur d'cho (" + e + ")"); System.exit(10); }// try-catch // on rend la rfrence au serveur return serveurEcho; }// getServeurEcho
On retrouve les mmes squences de code que dans le serveur : on cre un objet ORB qui nous permettra de contacter l'annuaire des services CORBA
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port}; ORB orb=ORB.init(initORB,null);
on demande au service d'annuaire une rfrence du service d'cho (c'est l qu'on diffre du serveur)
serveurEcho=iSrvEchoHelper.narrow(ncRef.resolve(path));
IX-B-6-c - Compilation
E:\data\java\corba\ECHO>j:\jdk12\bin\javac cltEcho.java E:\data\java\corba\ECHO>dir CLTECH~1 CLA CLTECH~1 JAV ECHO IDL SERVEU~1 CLA SERVEU~1 JAV SRVECH~1 CLA SRVECH~1 JAV ECHO <REP> 2 599 2 907 78 1 793 1 806 488 252 18/03/99 16/03/99 15/03/99 18/03/99 16/03/99 18/03/99 15/03/99 17/03/99 13:51 16:15 13:56 13:18 15:38 11:30 14:02 17:19 cltEcho.class cltEcho.java ECHO.IDL serveurEcho.class serveurEcho.java srvEcho.class srvEcho.java echo
- 392 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
ce qui a pour effet de lancer le service d'annuaire sur le port 1000 de la machine. Le service d'annuaire tnameserv produit un affichage d'cran qui ressemble ce qui suit :
Initial Naming Context: IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f 6e746578743a312e3000000000010000000000000030000100000000000a69737469612d30303900 044700000018afabcafe000000027620dd9a000000080000000000000000 TransientNameServer: setting port for initial object references to: 1000
C'est peu lisible, mais on retiendra la dernire ligne : le service est actif sur le port 1000.
Le serveur affiche :
Serveur d'cho prt
IX-B-7-d - Lancement du client sur poste Windows autre que celui du serveur
E:\data\java\corba\ECHO>j:\jdk12\bin\java cltEcho tahe.istia.univ-angers.fr 1000 srvEcho --> Connexion au serveur CORBA en cours... Message : abcd Rponse serveur : [abcd] Message : efgh Rponse serveur : [efgh] Message : fin
- 393 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Le client CORBA pourrait faire 3 oprations : se connecter la base de son choix mettre des requtes SQL fermer la connexion
Le serveur excute les requtes SQL du client et lui envoie les rsultats. C'est son travail essentiel et c'est pourquoi nous l'appellons un serveur SQL. Nous appliquons les diffrentes tapes vues prcdemment avec le serveur d'cho.
Le rle des diffrentes mthodes tait le suivant : connect le client se connecte une base de donnes distante dont il donne le pilote, l'url JDBC ainsi que son identit id et son mot de passe mdp pour accder cette base. Le serveur lui rend une chane de caractres indiquant le rsultat de la connexion : 200 - Connexion russie 500 - Echec de la connexion
- 394 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
executeSQL le client demande l'excution d'une requte SQL sur la base laquelle il est connect. Il indique le caractre qui doit sparer les champs dans les rsultats qui lui sont renvoys. Le serveur renvoie un tableau de chanes : 100 n pour une requte de mise jour de la base, n tant le nombre de lignes mises jour 500 msg d'erreur si la requte a gnr une erreur 501 Pas de rsultats si la requte n'a gnr aucun rsultat 101 ligne1 101 ligne2 101 ... si la requte a gnr des rsultats. Les lignes ainsi renvoyes par le serveur sont les lignes rsultats de la requte. close le client ferme sa connexion avec la base distante. Le serveur renvoie une chane indiquant le rsultat de cette fermeture : 200 Base ferme 500 Erreur lors de la fermeture de la base (msg d'erreur) L'interface IDL du serveur sera la suivante :
module srvSQL{ typedef sequence<string> resultats; interface interSQL{ string connect(in string pilote, in string urlBase, in string id, in string mdp); resultats executeSQL(in string requete, in string separateur); string close(); };// interface };// module
La seule nouveaut par rapport ce qu'on a vu avec l'interface IDL du serveur d'cho est l'utilisation du mot cl sequence. Ce mot cl permet de dfinir un tableau une dimension. La dfinition se fait en deux tapes : dfinition d'un type pour dsigner le tableau, ici resultats :
typedef sequence<string> resultats;
Le mot cl typedef est bien connu des programmeurs C/C++ : il permet de dfinir un nouveau type. Ici, le type resultats est dfini comme quivalent au type sequence<string>, c.a.d. un tableau dynamique (non dimensionn) de chanes de caractres.
- 395 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
On constate que la compilation a donn naissance un rpertoire portant le nom du module de l'interface IDL(srvSQL). Regardons le contenu de ce rpertoire :
E:\data\java\corba\sql>dir srvSQl RESULT~1 RESULT~2 _INTER~1 INTERS~1 INTERS~2 INTERS~3 _INTER~2 JAV JAV JAV JAV JAV JAV JAV 833 1 883 2 474 448 841 1 855 4 535 19/03/99 19/03/99 19/03/99 19/03/99 19/03/99 19/03/99 19/03/99 10:00 10:00 10:00 10:00 10:00 10:00 10:00 resultatsHolder.java resultatsHelper.java _interSQLStub.java interSQL.java interSQLHolder.java interSQLHelper.java _interSQLImplBase.java
On rappelle que les fichiers Helper et Holder sont des classes lies aux paramtres d'entr-sortie et rsultats des mthodes de l'interface distante. Le rpertoire srvSQL contient tous les fichiers .java lis l'interface interSQL dfinie dans le fichier .idl. In contient galement des fichiers lis au type resultats cr dans l'interface IDL. Le fichier interSQL.java est le fichier Java de l'interface de notre serveur. Il est important de vrifier que ce qui a t produit automatiquement correspond notre attente. Le fichier interSQL.java gnr est ici le suivant :
/* * * * * */ package srvSQL; public interface interSQL extends org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { String connect(String pilote, String urlBase, String id, String mdp) ; String[] executeSQL(String requete, String separateur) ; String close() ; } File: ./SRVSQL/INTERSQL.JAVA From: SRVSQL.IDL Date: Fri Mar 19 09:59:48 1999 By: D:\JAVAIDL\IDLTOJ~1.EXE Java IDL 1.2 Aug 18 1998 16:25:34
On constate qu'on a la mme interface que celle utilise pour le client-serveur RMI. On peut donc continuer. Compilons tous ces fichiers .java :
E:\data\java\corba\sql\srvSQL>j:\jdk12\bin\javac *.java Note: _interSQLImplBase.java uses or overrides a deprecated API. Recompile with "-deprecation" for details.
- 396 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
1 warning E:\data\java\corba\sql\srvSQL>dir *.class _INTER~1 _INTER~2 INTERS~1 INTERS~2 INTERS~3 RESULT~1 RESULT~2 CLA CLA CLA CLA CLA CLA CLA 3 094 1 953 430 2 096 870 2 047 881 19/03/99 19/03/99 19/03/99 19/03/99 19/03/99 19/03/99 19/03/99 10:01 10:01 10:01 10:01 10:01 10:01 10:01 _interSQLImplBase.class _interSQLStub.class interSQL.class interSQLHelper.class interSQLHolder.class resultatsHelper.class resultatsHolder.class
- 397 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// requte de mise jour // on renvoie le nombre de lignes mises jour lignes=new String[1]; lignes[0]="100 "+S.getUpdateCount(); return lignes; } // c'tait une requte d'interrogation // on rcupre les rsultats RS=S.getResultSet(); // nombre de champs du Resultset int nbChamps=RS.getMetaData().getColumnCount(); // on les exploite while(RS.next()){ // cration de la ligne des rsultats ligne="101 "; for (int i=1;i<nbChamps;i++) ligne+=RS.getString(i)+separateur; ligne+=RS.getString(nbChamps); // ajout au vecteur des rsultats resultats.addElement(ligne); }// while // fin de l'exploitation des rsultats // on libre les ressources RS.close(); S.close(); // on rend les rsultats int nbLignes=resultats.size(); if (nbLignes==0){ lignes=new String[1]; lignes[0]="501 Pas de rsultats"; } else { lignes=new String[resultats.size()]; for(int i=0;i<lignes.length;i++) lignes[i]=(String) resultats.elementAt(i); }//if return lignes; } catch (Exception e){ // erreur lignes=new String[1]; lignes[0]="500 " + e; return lignes; }// try-catch }// executeSQL // --------------- close public String close(){ // ferme la connexion la base de donnes String resultat=null; try{ DB.close(); resultat="200 Base ferme"; } catch (Exception e){ resultat="500 Erreur la fermeture de la base ("+e+")"; } // renvoi du rsultat return resultat; } }// classe SQLServant
Cette classe est place dans le fichier SQLServant.java que nous compilons :
E:\data\java\corba\sql>dir SRVSQL IDL 275 19/03/99 9:59 srvSQL.idl SRVSQL <REP> 19/03/99 9:41 srvSQL SQLSER~1 JAV 2 941 15/03/99 9:09 SQLServant.java E:\data\java\corba\sql>j:\jdk12\bin\javac SQLServant.java E:\data\java\corba\sql>dir *.class SQLSER~1 CLA 2 568 19/03/99 10:19 SQLServant.class
- 398 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
- 399 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Voici un exemple de paramtres possibles : localhost 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null , avec ici : machine port srvSQL pilote urlBase machine sur laquelle se trouve l'annuaire des services CORBA port sur lequel opre cet annuaire srvSQL nom CORBA du serveur SQL sun.jdbc.odbc.JdbcOdbcDriver le pilote usuel des bases avec interface odbc jdbc:odbc:articles pour utiliser une base articles dclare dans la liste des bases publiques ODBC de la machine Windows null pas d'identit null pas de mot de passe , les champs des rsultats seront spars par une virgule
id mdp separateur
Une fois lanc avec les paramtres prcdents, le client suit les tapes suivantes :
- 400 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
il se connecte la machine machine sur le port port pour demander le service CORBA srvSQL il demande la connexion la base de donnes articles
connect(#'sun.jdbc.odbc.JdbcOdbcDriver'', ##jdbc:odbc:articles'', '''', '''') il demande l'utilisateur de taper une requte SQL au clavier il l'envoie au serveur SQL
executeSQL(requete, '',''); il affiche l'cran les rsultats renvoys par le serveur il redemande l'utilisateur de taper une requte SQL au clavier. Il s'arrtera lorsque la requte est fin.
Le texte Java du client suit. Les commentaires devraient suffire sa comprhension. On constatera que : le code est identique celui du client RMI dj tudi. Il en diffre par le processus de demande du service l'annuaire, processus isol dans la mthode getServeurSQL. la mthode getServeurSQL est identique celle crite pour le client d'cho
On voit donc que : un client CORBA ne diffre d'un client RMI que par sa faon de contacter le serveur cette faon est identique pour tous les clients CORBA
import import import import srvSQL.*; org.omg.CosNaming.*; org.omg.CORBA.*; java.io.*;
public class clientSQL { // donnes globales de la classe private static String syntaxe = "syntaxe : cltSQL machine port service pilote urlBase id mdp separateur"; private static BufferedReader in=null; private static interSQL serveurSQL=null; public static void main(String arg[]){ // syntaxe : cltSQL machine port separateur pilote url id mdp // machine port : machine & port de l'annuaire des services CORBA contacter // service : nom du service // pilote : pilote utiliser pour la base de donnes exploiter // urlBase : url jdbc de la base exploiter // id : identit de l'utilisateur // mdp : son mot de passe // separateur : chane sparant les champs dans les rsultats d'une requte // vrification du nb d'arguments if(arg.length!=8) erreur(syntaxe,1); // init paramtres de la connexion la base de donnes String machine=arg[0]; String port=arg[1]; String service=arg[2]; String pilote=arg[3]; String urlBase=arg[4]; String id, mdp, separateur; if(arg[5].equals("null")) id=""; else id=arg[5];
- 401 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
if(arg[6].equals("null")) mdp=""; else mdp=arg[6]; if(arg[7].equals("null")) separateur=" "; else separateur=arg[7]; // paramtres du service d'annuaire CORBA String[] initORB={"-ORBInitialHost",arg[0],"-ORBInitialPort",arg[1]}; // client CORBA - on demande une rfrence du serveur SQL interSQL serveurSQL=getServeurSQL(machine,port,service); // dialogue client-serveur String requete=null; String reponse=null; String[] lignes=null; String codeErreur=null; try{ // ouverture du flux clavier in=new BufferedReader(new InputStreamReader(System.in)); // suivi System.out.println("--> Connexion la base de donnes en cours"); // demande de connexion initiale la base de donnes reponse=serveurSQL.connect(pilote,urlBase,id,mdp); // suivi System.out.println("<-- "+reponse); // analyse rponse codeErreur=reponse.substring(0,3); if(codeErreur.equals("500")) erreur("Abandon sur erreur de connexion la base",3); // boucle de lecture des requtes envoyer au serveur SQL System.out.print("--> Requte : "); requete=in.readLine().toLowerCase().trim(); while(! requete.equals("fin")){ // envoi de la requte au serveur et rception de la rponse lignes=serveurSQL.executeSQL(requete,separateur); // suivi afficheLignes(lignes); // requte suivante System.out.print("--> Requte : "); requete=in.readLine().toLowerCase().trim(); }// while // suivi System.out.println("--> Fermeture de la connexion la base de donnes distante"); // on clt la connexion reponse=serveurSQL.close(); // suivi System.out.println("<-- " + reponse); // fin System.exit(0); // gestion des erreurs } catch (Exception e){ erreur("Abandon sur erreur : " + e,2); }// try }// main // ----------- AfficheLignes private static void afficheLignes(String[] lignes){ for (int i=0;i<lignes.length;i++) System.out.println("<-- " + lignes[i]); }// afficheLignes // ------------ erreur private static void erreur(String msg, int exitCode){ // affichage msg d'erreur System.err.println(msg); // libration ventuelle des ressources try{ in.close(); serveurSQL.close(); } catch(Exception e){} // on quitte System.exit(exitCode); }// erreur
- 402 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
// ---------------------- getServeurSQL private static interSQL getServeurSQL(String machine, String port, String service){ // demande une rfrence du serveur SQL // machine : machine de l'annuaire des services CORBA // port : port de l'annuaire des services CORBA // service : nom du service CORBA demander // suivi System.out.println("--> Connexion au serveur CORBA en cours..."); // la rfrence du serveur SQL interSQL serveurSQL=null; // paramtres du service d'annuaire CORBA String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port}; try{ // on demande un objet CORBA pour travailler - on passe pour cela le port // d'coute de l'annuaire des services CORBA ORB orb=ORB.init(initORB,null); // on utilise le service d'annuaire pour localiser le serveur SQL org.omg.CORBA.Object objRef= orb.resolve_initial_references("NameService"); NamingContext ncRef=NamingContextHelper.narrow(objRef); // le service recherch s'appelle srvSQL - on le demande NameComponent nc= new NameComponent(service,""); NameComponent path[]={nc}; serveurSQL=interSQLHelper.narrow(ncRef.resolve(path)); } catch (Exception e){ System.err.println("Erreur lors de la localisation du serveur SQL (" + e + ")"); System.exit(10); }// try-catch // on rend la rfrence au serveur return serveurSQL; }// getServeurSQL }// classe
- 403 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
Cette base a la structure suivante : nom code nom prix stock_actu stock_mini type code de l'article sur 4 caractres son nom (chane de caractres) son prix (rel) son stock actuel (entier) le stock minimum (entier) en-dea duquel il faut rapprovisioner l'article
- 404 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
IX-C-7-e - Lancement d'un client sur une autre machine que celle du serveur
Voici les rsultats obtenus avec un client sur une autre machine que celle du serveur :
E:\data\java\corba\sql>j:\jdk12\bin\java clientSQL tahe.istia.univ-angers.fr 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null , --> Connexion au serveur CORBA en cours... --> Connexion la base de donnes en cours <-- 200 Connexion russie --> Requte : select * from articles <-- 101 a300,v_lo,1202,31,8 <-- 101 d600,arc,5000,9,8 <-- 101 d800,cano,1502,7,7 <-- 101 x123,fusil,3000,9,8 <-- 101 s345,skis nautiques,1800,13,8 <-- 101 f450,essai3,3,13,9 <-- 101 z400,lopard,500000,7,7 <-- 101 g457,panthre,800000,7,7 --> Requte : fin --> Fermeture de la connexion la base de donnes distante <-- 200 Base ferme
- 405 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/
type IDL boolean char wchar octet string wstring short unsigned short long unsigned long long long unsigned long long float double
type Java boolean char char byte java.lang.String java.lang.String short short int int long long float double
Rappelons que pour dfinir un tableau d'lments de type T dans l'interface IDL, on utilise l'instruction : typedef sequence<T> nomType; et qu'ensuite on utilise nomType pour rfrencer le type du tableau. Ainsi, dans l'interface du serveur SQL on a utilis la dclaration : typedef sequence<string> resultats; pour que resultats dsigne un tableau String[] sous Java.
- 406 Ce document est issu de http://www.developpez.com et reste la proprit exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise l'obtention pralable de l'autorisation de l'auteur.
http://tahe.developpez.com/java/cours/temp/