Vous êtes sur la page 1sur 344

Crez votre

application web avec


Java EE
Par Coyote

www.siteduzero.com

Licence Creative Commons BY-NC-SA 2.0


Dernire mise jour le 28/07/2012

2/345

Sommaire
Sommaire ........................................................................................................................................... 2
Lire aussi ............................................................................................................................................ 4
Crez votre application web avec Java EE ........................................................................................ 6
Comment lire ce cours ? ................................................................................................................................................... 6

Partie 1 : Les bases du Java EE ......................................................................................................... 7


Introduction au Java EE .................................................................................................................................................... 7
Pour commencer .........................................................................................................................................................................................................
Comment lire ce cours ? .............................................................................................................................................................................................
Prrequis .....................................................................................................................................................................................................................
Qu'est-ce que Java EE ? .............................................................................................................................................................................................
Java EE n'est pas Java ...............................................................................................................................................................................................
Java EE n'est pas Javascript ......................................................................................................................................................................................
Internet n'est pas le web ! ...........................................................................................................................................................................................
Comment a marche ...................................................................................................................................................................................................
Les langages du web ..................................................................................................................................................................................................
En rsum ...................................................................................................................................................................................................................

7
7
7
7
7
7
8
8
9
9

Le Java EE mis nu ! ..................................................................................................................................................... 10


Principes de fonctionnement ..................................................................................................................................................................................... 10
Le modle MVC : en thorie ...................................................................................................................................................................................... 11
Le modle MVC : en pratique .................................................................................................................................................................................... 12
En rsum ................................................................................................................................................................................................................. 13

Outils et environnement de dveloppement ................................................................................................................... 13


L'IDE Eclipse .............................................................................................................................................................................................................
Prsentation ..............................................................................................................................................................................................................
Tlchargement et installation ..................................................................................................................................................................................
Configuration .............................................................................................................................................................................................................
Le serveur Tomcat .....................................................................................................................................................................................................
Prsentation ..............................................................................................................................................................................................................
Installation .................................................................................................................................................................................................................
Cration du projet web avec Eclipse .........................................................................................................................................................................
Structure d'une application Java EE .........................................................................................................................................................................
Structure standard .....................................................................................................................................................................................................
Votre premire page web ..........................................................................................................................................................................................
En rsum .................................................................................................................................................................................................................

14
14
14
15
16
16
16
19
29
29
30
34

Partie 2 : Premiers pas avec Java EE ............................................................................................... 34


La servlet ......................................................................................................................................................................... 35
Derrire les rideaux ...................................................................................................................................................................................................
Retour sur HTTP .......................................................................................................................................................................................................
Pendant ce temps l, sur le serveur ......................................................................................................................................................................
Cration .....................................................................................................................................................................................................................
Mise en place ............................................................................................................................................................................................................
Dfinition de la servlet ...............................................................................................................................................................................................
Mapping de la servlet ................................................................................................................................................................................................
Mise en service .........................................................................................................................................................................................................
Do you GET it? ....................................................................................................................................................................................................
Cycle de vie d'une servlet .........................................................................................................................................................................................
Envoyer des donnes au client .................................................................................................................................................................................
En rsum .................................................................................................................................................................................................................

35
35
36
36
39
40
41
42
42
44
45
47

Servlet avec vue .......................................................................................................................................................... 47


Introduction aux JSP ................................................................................................................................................................................................. 48
Nature d'une JSP ...................................................................................................................................................................................................... 48
Mise en place d'une JSP ........................................................................................................................................................................................... 49
Cration de la vue ..................................................................................................................................................................................................... 49
Cycle de vie d'une JSP ............................................................................................................................................................................................. 51
Mise en relation avec notre servlet ............................................................................................................................................................................ 53
En rsum ................................................................................................................................................................................................................. 55

Transmission de donnes ............................................................................................................................................... 55


Donnes issues du serveur : les attributs ................................................................................................................................................................. 56
Donnes issues du client : les paramtres ............................................................................................................................................................... 57
En rsum ................................................................................................................................................................................................................. 60

Le JavaBean ................................................................................................................................................................... 60
Objectifs ....................................................................................................................................................................................................................
Pourquoi le JavaBean ? ............................................................................................................................................................................................
Un JavaBean n'est pas un EJB .................................................................................................................................................................................
Structure ....................................................................................................................................................................................................................
Mise en place ............................................................................................................................................................................................................
Cration de notre bean d'exemple ............................................................................................................................................................................
Configuration du projet sous Eclipse .........................................................................................................................................................................
Mise en service dans notre application .....................................................................................................................................................................
En rsum .................................................................................................................................................................................................................

61
61
61
61
62
62
65
67
68

La technologie JSP (1/2) ................................................................................................................................................. 70


Les balises ................................................................................................................................................................................................................ 70
Les directives ............................................................................................................................................................................................................ 71

www.siteduzero.com

Sommaire

3/345

La porte des objets ..................................................................................................................................................................................................


Les actions standard .................................................................................................................................................................................................
L'action standard useBean ........................................................................................................................................................................................
L'action standard getProperty ...................................................................................................................................................................................
L'action standard setProperty ....................................................................................................................................................................................
L'action standard forward ..........................................................................................................................................................................................

74
76
76
77
77
78

La technologie JSP (2/2) ................................................................................................................................................. 79


Expression Language ................................................................................................................................................................................................ 80
Prsentation .............................................................................................................................................................................................................. 80
La ralisation de tests ............................................................................................................................................................................................... 80
La manipulation d'objets ............................................................................................................................................................................................ 82
Dsactiver l'valuation des expressions EL .............................................................................................................................................................. 87
Les objets implicites .................................................................................................................................................................................................. 89
Les objets de la technologie JSP .............................................................................................................................................................................. 89
Les objets de la technologie EL ................................................................................................................................................................................ 92

Des problmes de vue ? ................................................................................................................................................. 97


Nettoyons notre exemple .......................................................................................................................................................................................... 98
Compltons notre exemple... .................................................................................................................................................................................. 101
Le point sur ce qu'il nous manque ........................................................................................................................................................................... 105
Documentation ........................................................................................................................................................................................................ 105
Liens utiles .............................................................................................................................................................................................................. 105

TP Fil rouge - tape 1 ................................................................................................................................................... 106


Objectifs .................................................................................................................................................................................................................. 107
Contexte .................................................................................................................................................................................................................. 107
Fonctionnalits ........................................................................................................................................................................................................ 107
Contraintes .............................................................................................................................................................................................................. 107
Conseils ................................................................................................................................................................................................................... 110
propos des formulaires ......................................................................................................................................................................................... 110
Le modle ................................................................................................................................................................................................................ 111
Les contrleurs ........................................................................................................................................................................................................ 111
Les vues .................................................................................................................................................................................................................. 111
Cration du projet .................................................................................................................................................................................................... 111
Illustration du comportement attendu ...................................................................................................................................................................... 112
Exemples de rendu du comportement attendu ........................................................................................................................................................ 113
Correction ................................................................................................................................................................................................................ 116
Le code des beans .................................................................................................................................................................................................. 116
Le code des servlets ................................................................................................................................................................................................ 118
Le code des JSP ..................................................................................................................................................................................................... 121

Partie 3 : Une bonne vue grce la JSTL ...................................................................................... 123


Objectifs et configuration ............................................................................................................................................... 124
C'est sa raison d'tre... ............................................................................................................................................................................................
Lisibilit du code produit ..........................................................................................................................................................................................
Moins de code crire ............................................................................................................................................................................................
Vous avez dit MVC ? ...............................................................................................................................................................................................
retenir ...................................................................................................................................................................................................................
Plusieurs versions ...................................................................................................................................................................................................
Configuration ...........................................................................................................................................................................................................
Configuration de la JSTL .........................................................................................................................................................................................

124
124
125
125
126
126
126
126

La bibliothque Core ..................................................................................................................................................... 129


Les variables et expressions ...................................................................................................................................................................................
Affichage d'une expression .....................................................................................................................................................................................
Gestion d'une variable .............................................................................................................................................................................................
Les conditions .........................................................................................................................................................................................................
Une condition simple ...............................................................................................................................................................................................
Des conditions multiples .........................................................................................................................................................................................
Les boucles .............................................................................................................................................................................................................
Boucle "classique" ...................................................................................................................................................................................................
Itration sur une collection ......................................................................................................................................................................................
Itration sur une chane de caractres ....................................................................................................................................................................
Ce que la JSTL ne permet pas (encore) de faire ....................................................................................................................................................
Les liens ..................................................................................................................................................................................................................
Liens ........................................................................................................................................................................................................................
Redirection ..............................................................................................................................................................................................................
Imports ....................................................................................................................................................................................................................

130
130
131
134
134
134
135
135
137
140
140
140
140
143
144

JSTL core : exercice d'application ................................................................................................................................. 145


Les bases de l'exercice ........................................................................................................................................................................................... 146
Correction ................................................................................................................................................................................................................ 148

La bibliothque xml ....................................................................................................................................................... 151


La syntaxe XPath ....................................................................................................................................................................................................
Le langage XPath ....................................................................................................................................................................................................
Les actions de base ................................................................................................................................................................................................
Rcuprer et analyser un document .......................................................................................................................................................................
Afficher une expression ...........................................................................................................................................................................................
Crer une variable ...................................................................................................................................................................................................
Les conditions .........................................................................................................................................................................................................
Les conditions .........................................................................................................................................................................................................
Les boucles .............................................................................................................................................................................................................
Les boucles .............................................................................................................................................................................................................
Les tranformations ..................................................................................................................................................................................................
Transformations ......................................................................................................................................................................................................

152
152
153
153
156
157
157
157
158
158
159
159

JSTL xml : exercice d'application .................................................................................................................................. 161

www.siteduzero.com

Sommaire

4/345

Les bases de l'exercice ........................................................................................................................................................................................... 162


Correction ................................................................................................................................................................................................................ 163

Faisons le point ! ........................................................................................................................................................... 164


Reprenons notre exemple .......................................................................................................................................................................................
Quelques conseils ...................................................................................................................................................................................................
Utilisation de constantes .........................................................................................................................................................................................
Inclure automatiquement la JSTL Core toutes vos JSP .......................................................................................................................................
Formater proprement et automatiquement votre code avec Eclipse ......................................................................................................................
Documentation ........................................................................................................................................................................................................
Liens utiles ..............................................................................................................................................................................................................

165
167
167
169
170
175
175

TP Fil rouge - tape 2 ................................................................................................................................................... 177


Objectifs ..................................................................................................................................................................................................................
Utilisation de la JSTL ...............................................................................................................................................................................................
Application des bonnes pratiques ...........................................................................................................................................................................
Exemples de rendus ...............................................................................................................................................................................................
Conseils ..................................................................................................................................................................................................................
Utilisation de la JSTL ...............................................................................................................................................................................................
Application des bonnes pratiques ...........................................................................................................................................................................
Correction ................................................................................................................................................................................................................
Code des servlets ...................................................................................................................................................................................................
Code des JSP .........................................................................................................................................................................................................

177
177
177
177
178
179
179
179
180
183

Partie 4 : Une application interactive ! ............................................................................................. 188


Formulaires : le b.a.-ba ................................................................................................................................................. 189
Mise en place ..........................................................................................................................................................................................................
JSP & CSS ..............................................................................................................................................................................................................
La servlet .................................................................................................................................................................................................................
L'envoi des donnes ...............................................................................................................................................................................................
Contrle : ct servlet .............................................................................................................................................................................................
Affichage : ct JSP ................................................................................................................................................................................................

189
196
199
200
201
205

Formulaires : la mode MVC ....................................................................................................................................... 212


Analyse de notre conception ................................................................................................................................................................................... 213
Cration du modle ................................................................................................................................................................................................. 214
Reprise de la servlet ............................................................................................................................................................................................... 217
Reprise de la JSP .................................................................................................................................................................................................... 218

TP Fil rouge - tape 3 ................................................................................................................................................... 220


Objectifs ..................................................................................................................................................................................................................
Fonctionnalits ........................................................................................................................................................................................................
Exemples de rendus ...............................................................................................................................................................................................
Conseils ..................................................................................................................................................................................................................
Correction ................................................................................................................................................................................................................
Code des objets mtier ...........................................................................................................................................................................................
Code des servlets ...................................................................................................................................................................................................
Code des JSP .........................................................................................................................................................................................................

221
221
221
223
223
223
229
231

La session : connectez vos clients ................................................................................................................................ 235


Le formulaire ...........................................................................................................................................................................................................
Le principe de la session .........................................................................................................................................................................................
Le modle ...............................................................................................................................................................................................................
La servlet .................................................................................................................................................................................................................
Les vrifications ......................................................................................................................................................................................................
Test du formulaire de connexion .............................................................................................................................................................................
Test de la destruction de session ............................................................................................................................................................................
Derrire les rideaux .................................................................................................................................................................................................
La thorie : principe de fonctionnement ..................................................................................................................................................................
La pratique : scrutons nos requtes et rponses ....................................................................................................................................................
Le bilan ....................................................................................................................................................................................................................

236
236
239
241
243
243
245
251
251
252
265

Le filtre : crez un espace membre ............................................................................................................................... 265


Restreindre l'accs une page ...............................................................................................................................................................................
Les pages d'exemple ..............................................................................................................................................................................................
La servlet de contrle ..............................................................................................................................................................................................
Test du systme ......................................................................................................................................................................................................
Le problme ............................................................................................................................................................................................................
Le principe du filtre ..................................................................................................................................................................................................
Gnralits ..............................................................................................................................................................................................................
Fonctionnement ......................................................................................................................................................................................................
Cycle de vie .............................................................................................................................................................................................................
Restreindre l'accs un ensemble de pages .........................................................................................................................................................
Restreindre un rpertoire ........................................................................................................................................................................................
Restreindre l'application entire ..............................................................................................................................................................................
Dsactiver le filtre ....................................................................................................................................................................................................

266
266
267
269
270
270
270
271
272
273
273
279
285

Le cookie : le navigateur vous ouvre ses portes ........................................................................................................... 286


Le principe du cookie .............................................................................................................................................................................................. 287
Ct HTTP .............................................................................................................................................................................................................. 287
Ct Java EE .......................................................................................................................................................................................................... 287
Souvenez-vous de vos clients ! ............................................................................................................................................................................... 287
Reprise de la servlet ............................................................................................................................................................................................... 288
Reprise de la JSP .................................................................................................................................................................................................... 293
Vrifications ............................................................................................................................................................................................................. 294
propos de la scurit ........................................................................................................................................................................................... 298

TP Fil rouge - tape 4 ................................................................................................................................................... 298


Objectifs .................................................................................................................................................................................................................. 299
Fonctionnalits ........................................................................................................................................................................................................ 299

www.siteduzero.com

Lire aussi

5/345

Exemples de rendus ...............................................................................................................................................................................................


Conseils ..................................................................................................................................................................................................................
Correction ................................................................................................................................................................................................................
Le code des vues ....................................................................................................................................................................................................
Le code des servlets ...............................................................................................................................................................................................
Le code des objets mtiers .....................................................................................................................................................................................

299
302
304
304
310
315

Formulaires : l'envoi de fichiers ..................................................................................................................................... 319


Cration du formulaire ............................................................................................................................................................................................. 320
Rcupration des donnes ..................................................................................................................................................................................... 320
Mise en place .......................................................................................................................................................................................................... 320
Traitement des donnes .......................................................................................................................................................................................... 321
La diffrence entre la thorie et la pratique ............................................................................................................................................................. 328
Enregistrement du fichier ........................................................................................................................................................................................ 330
Dfinition du chemin physique ................................................................................................................................................................................ 330
criture du fichier sur le disque ............................................................................................................................................................................... 331
Test du formulaire d'upload ..................................................................................................................................................................................... 334
Problmes et limites ................................................................................................................................................................................................ 334
Comment grer les fichiers de mme noms ? ........................................................................................................................................................ 334
Comment viter les doublons ? ............................................................................................................................................................................... 334
O stocker les fichiers reus ? ................................................................................................................................................................................ 335
Rendre le tout entirement automatique ................................................................................................................................................................. 335
Intgration dans MVC .............................................................................................................................................................................................. 335
Cration du bean reprsentant un fichier ................................................................................................................................................................ 336
Cration de l'objet mtier en charge du traitement du formulaire ........................................................................................................................... 336
Reprise de la servlet ............................................................................................................................................................................................... 341
Adaptation de la page JSP aux nouvelles informations transmises ........................................................................................................................ 342
Comportement de la solution finale ......................................................................................................................................................................... 343
Avancement du cours .............................................................................................................................................................................................. 344
Et aprs ? ................................................................................................................................................................................................................ 344

www.siteduzero.com

Lire aussi

6/345

Crez votre application web avec Java EE

Par

Coyote

Mise jour : 25/07/2012


Difficult : Intermdiaire

Dure d'tude : 1 mois

17 955 visites depuis 7 jours, class 17/785


La cration d'applications web avec Java EE semble complique beaucoup de dbutants. Une norme nbuleuse de sigles en
tout genre gravite autour de la plate-forme, un nombre consquent de technologies et d'approches diffrentes existent : servlet,
JSP, Javabean, MVC, JDBC, JNDI, EJB, JPA, JMS, JSF, Struts, Spring, Tomcat, Glassfish, JBoss, WebSphere, WebLogic... La liste
n'en finit pas, et pour un novice ne pas touffer sous une telle avalanche est bien souvent mission impossible !
Soyons honntes, ce tutoriel ne vous expliquera pas le fonctionnement et l'utilisation de toutes ces technologies. Car a aussi,
c'est mission impossible ! Il faudrait autant de tutos...
Non, ce cours a pour objectif de guider vos premiers pas dans l'univers Java EE : aprs quelques explications sur les concepts
gnraux et les bonnes pratiques en vigueur, vous allez entrer dans le vif du sujet et dcouvrir comment crer un projet web, en y
ajoutant de la complexit au fur et mesure que le cours avancera. la fin du cours, vous serez capables de crer une
application web qui respecte les standards reconnus dans le domaine et vous disposerez des bases ncessaires pour utiliser la
plupart des technologies se basant sur Java EE.

Comment lire ce cours ?


Un contenu consquent est prvu, mais je ne vais volontairement pas tre exhaustif : les technologies abordes sont trs vastes,
et l'objectif du cours est de vous apprendre crer une application. Si je vous rcrivais la documentation de la plate-forme Java
EE en franais, a serait tout simplement imbuvable. Je vais ainsi fortement insister sur des points non documents et des
pratiques que je juge importantes, et tre plus expditif sur certains points, pour lesquels je me contenterai de vous prsenter les
bases et de vous renvoyer vers les documentations et sources officielles pour plus d'informations. Je vous invite donc ne pas
vous limiter la seule lecture de ce cours, et parcourir chacun des liens que j'ai mis en place tout au long des chapitres.
Enfin, avant d'attaquer sachez que ce cours ne part pas totalement de zro : il vous faut des bases en Java afin de ne pas vous
sentir largus ds les premiers chapitres. Ainsi, si vous n'tes pas encore familier avec le langage, vous pouvez lire les parties 1
et 2 du tutoriel sur le Java du Site du Zro.

www.siteduzero.com

Crez votre application web avec Java EE

7/345

Partie 1 : Les bases du Java EE


Dans cette courte premire partie, nous allons poser le dcor : quelles sont les briques de base d'une application Java EE,
comment elles interagissent, quels outils utiliser pour dvelopper un projet...

Introduction au Java EE
Avant de nous plonger dans l'univers Java EE, commenons par faire une mise au point sur ce que vous devez connatre avant
d'attaquer ce cours, et penchons-nous un instant sur ce qu'est le web, et sur ce qu'il n'est pas. Simples rappels pour certains
d'entre vous, dcouverte pour d'autres, nous allons ici expliquer ce qui se passe dans les coulisses lorsque l'on accde un site
web depuis son navigateur. Nous aborderons enfin brivement les autres langages existants, et les raisons qui nous poussent
choisir Java EE.

Pour commencer
Comment lire ce cours ?
Un contenu consquent est prvu dans ce cours, mais je ne vais volontairement pas tre exhaustif : les technologies abordes
sont trs vastes, et l'objectif est avant tout de vous apprendre crer une application. Si je vous rcrivais la documentation de
la plate-forme Java EE en franais, a serait tout simplement imbuvable. Je vais ainsi fortement insister sur des points non
documents et des pratiques que je juge importantes, et tre plus expditif sur certains points, pour lesquels je me contenterai de
vous prsenter les bases et de vous renvoyer vers les documentations et sources officielles pour plus d'informations. Je vous
invite donc ne pas vous limiter la seule lecture de ce cours, et parcourir chacun des liens que j'ai mis en place tout au long
des chapitres ; plus vous ferez preuve de curiosit et d'assiduit, plus votre apprentissage sera efficace.

Prrequis
Avant d'attaquer, sachez que ce cours ne part pas totalement de zro :
des notions en dveloppement Java sont ncessaires (lire les parties 1 et 2 du cours de Java) ;
des notions en langages HTML et CSS sont prfrables, pour une meilleure comprhension des exemples (lire le cours de
HTML5 / CSS3) ;
des notions en langage SQL sont prfrables, pour une meilleure comprhension de la partie 5 du cours (lire le cours de
MySQL).

Qu'est-ce que Java EE ?


Pour commencer, tordons le coup certaines confusions plutt tenaces chez les dbutants

Java EE n'est pas Java


Le terme Java fait bien videmment rfrence un langage, mais galement une plate-forme : son nom complet est Java SE
pour Java Standard Edition , et tait anciennement raccourci J2SE . Celle-ci est constitue de nombreuses bibliothques,
ou API : citons par exemple java.lang, java.io, java.math, java.util, etc. Bref, toutes ces bibliothques que vous
devez dj connatre et qui contiennent un nombre consquent de classes et de mthodes prtes l'emploi pour effectuer toutes
sortes de tches.
Le terme Java EE signifie Java Enterprise Edition, et tait anciennement raccourci en J2EE . Il fait quant lui rfrence
une extension de la plate-forme standard. Autrement dit, la plate-forme Java EE est construite sur le langage Java et la plate-forme
Java SE, et elle y ajoute un grand nombre de bibliothques remplissant tout un tas de fonctionnalits que la plate-forme standard
ne remplit pas d'origine. L'objectif majeur de Java EE est de faciliter le dveloppement d'applications web robustes et distribues,
dployes et excutes sur un serveur d'applications. Inutile de rentrer plus loin dans les dtails, tout ceci tant bien entendu
l'objet des chapitres venir.
Si le cur vous en dit, vous pouvez consulter les spcifications de la plate-forme Java EE actuelle, finalises depuis dcembre
2009.

Java EE n'est pas Javascript


S'il est vrai que Java EE permet la cration d'applications web, il ne faut pas pour autant le confondre avec le langage Javascript,
souvent raccourci en JS , qui est lui aussi massivement utilis dans les applications web. Ce sont l deux langages totalement

www.siteduzero.com

Partie 1 : Les bases du Java EE

8/345

diffrents, qui n'ont comme ressemblance que leur nom ! En d'autres termes, Java est au Javascript ce que le bal est la
balustrade
Ne vous leurrez donc pas, et lorsque vous entendrez parler de scripts Java, rappelez-vous bien que cela dsigne simplement du
code Java, et surtout pas du code Javascript.

Internet n'est pas le web !


Avant tout, il ne faut pas confondre l'internet et le web :
l'internet est le rseau, le support physique de l'information. Pour faire simple, c'est un ensemble de machines, de cbles
et d'lments rseau en tout genre parpills sur la surface du globe ;
le web constitue une partie seulement du contenu accessible sur l'internet. Vous connaissez et utilisez d'autres contenus,
comme le courrier lectronique ou encore la messagerie instantane.
Un site web est un ensemble constitu de pages web (elles-mmes faites de fichiers HTML, CSS, Javascript, etc.). Lorsqu'on
dveloppe puis publie un site web, on met en ralit en ligne du contenu sur internet. On distingue deux types de sites :
les sites internet statiques : ce sont des sites dont le contenu est fixe , il n'est modifiable que par le propritaire du
site. Ils sont raliss l'aide des technologies HTML, CSS et Javascript uniquement.
les sites internet dynamiques : ce sont des sites dont le contenu est dynamique , parce que le propritaire n'est plus
le seul pouvoir le faire changer ! En plus des langages prcdemment cits, ils font intervenir d'autres technologies :
Java EE est l'une d'entre elles !

Comment a marche
Lorsqu'un utilisateur consulte un site, ce qui se passe derrire les rideaux est un simple change entre un client et un serveur :
le client : dans la plupart des cas, c'est le navigateur install sur votre ordinateur. Retenez que ce n'est pas le seul moyen
d'accder au web, mais c'est celui qui nous intresse dans ce cours.
le serveur : c'est la machine sur laquelle le site est hberg, o les fichiers sont stocks et les pages web gnres.

Echange dynamique client <-> serveur

La communication qui s'effectue entre le client et le serveur est rgie par des rgles bien dfinies : le protocole HTTP. Entrons
donc un peu plus dans le dtail, et regardons de quoi est constitu un change simple :
1. l'utilisateur saisit une URL dans la barre d'adresses de son navigateur ;
2. le navigateur envoie alors une requte HTTP au serveur pour lui demander la page correspondante ;
3. le serveur reoit cette requte, l'interprte et gnre alors une page web qu'il va renvoyer au client par le biais d'une
rponse HTTP ;
4. le navigateur reoit, via cette rponse, la page web finale, qu'il affiche alors l'utilisateur.

Echange dynamique HTTP client <-> serveur

www.siteduzero.com

Partie 1 : Les bases du Java EE

9/345

Ce qu'il faut comprendre et retenir de tout a :


les donnes sont changes entre le client et le serveur via le protocole HTTP ;
le client ne comprend que les langages de prsentation de l'information, en d'autres termes les technologies HTML, CSS
et Javascript ;
les pages sont gnres sur le serveur de manire dynamique, partir du code source du site.

Les langages du web


Nous venons de le voir dans le dernier paragraphe, le client ne fait que recevoir des pages web, les afficher l'utilisateur et
transmettre ses actions au serveur. Vous savez dj que les langages utiliss pour mettre en forme les donnes et les afficher
l'utilisateur sont le HTML, le CSS et ventuellement le Javascript. Ceux-ci ont une caractristique commune importante : ils sont
tous interprts par le navigateur, directement sur la machine client. D'ailleurs, le client est uniquement capable de comprendre
ces quelques langages, rien de plus !
Eh bien le serveur aussi dispose de technologies bien lui, que lui seul est capable de comprendre : une batterie complte ayant
pour objectif final de gnrer les pages web envoyer au client, avec tous les traitements que cela peut impliquer au passage :
analyse des donnes reues via HTTP, transformation des donnes, enregistrement des donnes dans une base de donnes ou
des fichiers, intgration des donnes dans le design
Seulement, la diffrence du couple HTML & CSS qui est un standard incontournable pour la mise en forme des pages web, il
existe plusieurs technologies capables de traiter les informations sur le serveur. Java EE est l'une d'entre elles, mais il en existe
d'autres : PHP, .NET, Django et Ruby on Rails, pour ne citer que les principales. Toutes offrent sensiblement les mmes
possibilits, mais toutes utilisent un langage et un environnement bien elles !
Comment choisir la technologie la mieux adapte son projet ?

C'est en effet une trs bonne question : qu'est-ce qui permet de se dcider parmi cet ventail de possibilits ? C'est un dbat
presque sans fin. Toutefois, dans la vie relle le choix est bien souvent influenc, voire dict par :
votre propre exprience : si vous avez dj dvelopp en Java, Python ou C# auparavant, il semble prudent de vous
orienter respectivement vers Java EE, Django et .NET ;
vos besoins : rapidit de dveloppement, faible utilisation des ressources sur le serveur, ractivit de la communaut
soutenant la technologie, ampleur de la documentation disponible en ligne, cot, etc.
Quoi qu'il en soit, peu importent les raisons qui vous ont pousss lire ce cours, nous sommes bien l pour apprendre le Java EE
!

En rsum
Java EE est une extension de la plate-forme standard Java SE, principalement destine au dveloppement d'applications
web.
Internet dsigne le rseau physique ; le web dsigne le contenu accessible travers ce rseau.
Pour interagir avec un site web (le serveur), l'utilisateur (le client) passe par son navigateur.
travers le protocole HTTP, le navigateur envoie des requtes au serveur et le serveur lui renvoie des rponses :
le travail du serveur est de recevoir des requtes, de gnrer les pages web et de les envoyer au client.
le travail du navigateur est de transmettre les actions de l'utilisateur au serveur, et d'afficher les informations qu'il
renvoie.

Nous voil maintenant prts faire un premier pas vers le Java EE. Dans le prochain chapitre, nous allons dcouvrir de quoi est
faite une application web, et comment elle interagit avec le protocole HTTP.

www.siteduzero.com

Partie 1 : Les bases du Java EE

10/345

Le Java EE mis nu !
Le Java Enterprise Edition, comme son nom l'indique, a t cr pour le dveloppement d'applications d'entreprises. Nous nous
y attarderons dans le chapitre suivant, mais sachez d'ores et dj que ses spcifications ont t penses afin, notamment, de
faciliter le travail en quipe sur un mme projet : l'application est dcoupe en couches, et le serveur sur lequel tourne
l'application est lui-mme dcoup en plusieurs niveaux. Pour faire simple, Java EE fournit un ensemble dextensions au Java
standard afin de faciliter la cration dapplications centralises.
Voyons comment tout cela s'agence !

Principes de fonctionnement
Nous venons de dcouvrir qu'afin de pouvoir communiquer entre eux, le client et le serveur doivent se parler via HTTP. Nous
savons dj que, ct client, le navigateur s'en occupe. Ct serveur, qui s'en charge ? C'est un composant que l'on nomme
logiquement serveur HTTP. Son travail est simple : il doit couter tout ce qui arrive sur le port utilis par le protocole HTTP, le
port 80, et scruter chaque requte entrante. C'est tout ce qu'il fait, c'est en somme une interface de communication avec le
protocole.
titre informatif, voici les deux plus connus : Apache HTTP Server et IIS (Microsoft).
Cependant, nous n'allons directement utiliser ni l'un ni l'autre. Pourquoi ?

tre capable de discuter via HTTP c'est bien, mais notre serveur doit permettre d'effectuer d'autres tches. En effet, une fois la
requte HTTP lue et analyse, il faut encore traiter son contenu et ventuellement renvoyer une rponse au client en
consquence. Vous devez probablement dj savoir que cette responsabilit vous incombe en grande partie : c'est le code que
vous allez crire qui va dcider ce qu'il faut faire lorsque telle requte arrive ! Seulement, comme je viens de vous l'annoncer, un
serveur HTTP de base ne peut pas grer votre application, ce n'est pas son travail.
Remarque : cette affirmation est en partie fausse, dans le sens o la plupart des serveurs HTTP sont devenus des
serveurs web part entire, incluant des plugins qui les rendent capables de supporter des langages de script comme
le PHP, l'ASP, etc.
Ainsi, nous avons besoin d'une solution plus globale : ce composant, qui va se charger d'excuter votre code en plus de faire le
travail du serveur HTTP, se nomme le serveur d'applications. Donner une dfinition exacte du terme est difficile : ce que nous
pouvons en retenir, c'est qu'un tel serveur inclut un serveur HTTP, et y ajoute la gestion d'objets de diverses natures au travers
d'un composant que nous allons pour le moment nommer le conteneur.

Architecture serveur
Concrtement, le serveur d'applications va :
rcuprer les requtes HTTP issues des clients ;
les mettre dans des botes, des objets, que votre code sera capable de manipuler ;
faire passer ces objets dans la moulinette qu'est votre application, via le conteneur ;
renvoyer des rponses HTTP aux clients, en se basant sur les objets retourns par votre code.
L encore, il en existe plusieurs sur le march, que l'on peut dcouper en deux secteurs :

www.siteduzero.com

Partie 1 : Les bases du Java EE

11/345

les solutions propritaires et payantes : WebLogic et WebSphere, respectivement issues de chez Oracle et IBM, sont les
rfrences dans le domaine. Massivement utilises dans les banques et la finance notamment, elles sont la fois
robustes, finement paramtrables et trs coteuses.
les solutions libres et gratuites : Apache Tomcat, JBoss, GlassFish et Jonas en sont les principaux reprsentants.
Comment faire un choix parmi toutes ces solutions ?

Hormis les problmatiques de cots qui sont videntes, d'autres paramtres peuvent influencer votre dcision ; citons par
exemple la rapidit de chargement et dexcution, ainsi que la quantit de technologies supportes. En ce qui nous concerne,
nous partons de zro : ainsi, un serveur d'applications basique, lger et gratuit fera trs bien l'affaire. a tombe bien, il en existe
justement un qui rpond parfaitement tous nos besoins : Apache Tomcat.
Pour information, c'est d'ailleurs souvent ce type de serveurs qui est utilis lors des phases de dveloppement de
grands projets en entreprise. Le cot des licences des solutions propritaires tant lev, ce n'est que lors de la mise en
service sur la machine finale (on parle alors de mise en production) que l'on opte ventuellement pour une telle
solution.

Avant de dcouvrir et de prendre en main Tomcat, il nous reste encore quelques concepts cls aborder !

Le modle MVC : en thorie


Qu'est-ce qu'un modle de conception ?

En anglais design pattern, un modle de conception (ou encore patron de conception) est une simple bonne pratique, qui rpond
un problme de conception d'une application. C'est en quelque sorte une ligne de conduite qui permet de dcrire les grandes
lignes d'une solution. De tels modles sont issus de l'exprience des concepteurs et dveloppeurs d'applications : c'est en effet
uniquement aprs une certaine priode d'utilisation que peuvent tre mises en vidence des pratiques plus efficaces que
d'autres, pratiques qui sont alors structures en modles et considres comme standard.
Maintenant que nous sommes au point sur ce qu'est un modle, la seconde question se poser concerne bien videmment le
Java EE.
Que recommandent les dveloppeurs Java EE expriments ?

Il faut bien vous rendre compte qu' l'origine, Java EE permet plus ou moins de coder son application comme on le souhaite : en
d'autres termes, on peut coder n'importe comment ! Or on sait que dans Java EE, il y a Entreprise , et que a n'est pas l pour
faire joli ! Le dveloppement en entreprise implique entre autres :
que l'on puisse tre amen travailler plusieurs contributeurs sur un mme projet ou une mme application (travail en
quipe) ;
que l'on puisse tre amen maintenir et corriger une application que l'on n'a pas cre soi-mme ;
que l'on puisse tre amen faire voluer une application que l'on n'a pas cre soi-mme.
Pour toutes ces raisons, il est ncessaire d'adopter une architecture plus ou moins standard, que tout dveloppeur peut
reconnatre, c'est--dire dans laquelle tout dveloppeur sait se reprer.
Il a t trs vite remarqu qu'un modle permettait de rpondre ces besoins, et qu'il s'appliquait particulirement bien la
conception d'applications Java EE : le modle MVC (Modle-Vue-Contrleur).
Il dcoupe littralement l'application en couches distinctes, et de ce fait impacte trs fortement l'organisation du code ! Voici dans
les grandes lignes ce qu'impose MVC :
tout ce qui concerne le traitement, le stockage et la mise jour des donnes de l'application doit tre contenu dans la
couche nomme "Modle" (le M de MVC) ;
tout ce qui concerne l'interaction avec l'utilisateur et la prsentation des donnes (mise en forme, affichage) doit tre
contenu dans la couche nomme "Vue" (le V de MVC) ;
tout ce qui concerne le contrle des actions de l'utilisateur et des donnes doit tre contenu dans la couche nomme
"Contrle" (le C de MVC).

www.siteduzero.com

Partie 1 : Les bases du Java EE

12/345

Ce modle peut tre reprsent par le schma suivant :

MVC
Ne vous faites pas de souci si c'est encore flou dans votre esprit : nous reviendrons maintes reprises sur ces concepts au fur et
mesure que nous progresserons dans notre apprentissage.

Le modle MVC : en pratique


Le schma prcdent est trs global, afin de vous permettre de bien visualiser l'ensemble du systme. Tout cela est encore assez
abstrait, et c'est volontaire ! En effet, chaque projet prsente ses propres contraintes, et amne le dveloppeur faire des choix.
Ainsi, on observe normment de variantes ds que l'on entre un peu plus dans le dtail de chacun de ces blocs.
Prenons l'exemple du sous-bloc reprsentant les donnes (donc l'intrieur la couche Modle) :
Quel est le type de stockage dont a besoin votre application ?
Quelle est l'envergure de votre application ?
Disposez-vous d'un budget ?
La quantit de donnes produites par votre application va-t-elle tre amene fortement voluer ?

La liste de questions est souvent longue, et ralisez bien que tous ces points sont autant de paramtres qui peuvent influencer la
conception de votre application, et donc vos choix au niveau de l'architecture. Ainsi, dtailler plus finement les blocs composant
une application n'est faisable qu'au cas par cas, idem pour les relations entre ceux-ci, et dpend fortement de l'utilisation ou non
de frameworks
Qu'est-ce qu'un framework ?

Il est encore bien trop tt pour que nous nous penchions sur ce sujet. Toutefois, vous pouvez d'ores et dj retenir qu'un
framework est un ensemble de composants qui servent crer l'architecture et les grandes lignes d'une application. Vous pouvez
le voir comme une bote outils gante, conue par un ou plusieurs dveloppeurs et mise disposition d'autres dveloppeurs,
afin de faciliter leur travail. Il existe des frameworks dans beaucoup de langages et plate-formes, ce n'est pas un concept propre
Java EE ni au dveloppement web en particulier.
En ce qui concerne Java EE, nous pouvons par exemple citer JSF, Spring, Struts ou encore Hibernate. Toutes ces solutions sont
des frameworks que les dveloppeurs sont libres d'utiliser ou non dans leurs projets.
Bref, nous sommes encore loin d'tre assez l'aise avec la plate-forme Java EE pour tudier ces fameux frameworks, mais nous
pouvons d'ores et dj tudier les applications Java EE "nues", sans frameworks ni fioritures. Voici donc une courte introduction
de chacune des couches composant une telle application web suivant le modle MVC.

Modle : des traitements et des donnes


Dans le modle, on trouve la fois les donnes et les traitements appliquer ces donnes. Ce bloc contient donc des objets
Java d'une part, qui peuvent contenir des attributs (donnes) et des mthodes (traitements) qui leur sont propres, et un systme
capable de stocker des donnes d'autre part. Rien de bien transcendant ici, la complexit du code dpendra bien videmment de
la complexit des traitements effectuer par votre application.

www.siteduzero.com

Partie 1 : Les bases du Java EE

13/345

Vue : des pages JSP


Une page JSP est destine la vue. Elle est excute ct serveur et permet l'criture de gabarits (pages en langage "client"
comme HTML, CSS, Javascript, XML, etc.). Elle permet au concepteur de la page d'appeler de manire transparente des portions
de code Java, via des balises et expressions ressemblant fortement aux balises de prsentation HTML.

Contrleur : des servlets


Une servlet est un objet qui permet d'intercepter les requtes faites par un client, et qui peut personnaliser une rponse en
consquence. Il fournit pour cela des mthodes permettant de scruter les requtes HTTP. Cet objet n'agit jamais directement
sur les donnes, il faut le voir comme un simple aiguilleur : il intercepte une requte issue d'un client, appelle ventuellement
des traitements effectus par le modle, et ordonne en retour la vue d'afficher le rsultat au client.

Rien que dans ces quelques lignes, il y a beaucoup d'informations. Pas de panique, nous reviendrons sur tout cela en long, en
large et en travers dans les parties suivantes de ce cours !
Afin de bien visualiser qui fait quoi, reprenons notre schma en
mettant des noms sur nos blocs :

MVC avec Java EE

En rsum
Un serveur d'applications est constitu d'un serveur HTTP et d'un conteneur web.
Le modle de conception MVC impose une rpartition stricte des tches au sein d'une application :
la couche Modle se charge des traitements effectuer sur les donnes et de leur stockage ;
la couche Vue se charge de la prsentation des donnes pour l'utilisateur ;
la couche Contrle se charge d'aiguiller les requtes entrantes vers les traitements et vues correspondants.
Un framework est une bote outils mise disposition du dveloppeur pour lui allger certaines tches.
Dans une application Java EE sans frameworks :
la couche Modle est constitue d'objets Java ;
la couche Vue est constitue de pages JSP ;
la couche Contrle est constitue de servlets.

www.siteduzero.com

Partie 1 : Les bases du Java EE

14/345

Outils et environnement de dveloppement


La cration d'une application web avec Java EE s'effectue gnralement l'aide d'un Environnement de Dveloppement Intgr,
trs souvent raccourci l'anglaise en IDE. C'est un logiciel destin faciliter grandement le dveloppement dans son ensemble.
S'il est possible pour certains projets Java de s'en passer, en ne se servant que d'un diteur de texte pour crire le code et d'une
invite de commandes pour mettre en place l'application, ce n'est srieusement plus envisageable pour la cration d'une
application web complexe. Nous allons donc dans ce chapitre apprendre en utiliser un, et y intgrer notre serveur
d'applications.
Si malgr mes conseils, votre ct extrmiste du bloc-notes prend le dessus et que vous souhaitez tout faire la main, ne
vous inquitez pas, je prendrai le temps de dtailler ce qui se trame en coulisses lorsque c'est important !

L'IDE Eclipse
Prsentation
J'utiliserai l'IDE Eclipse tout au long de ce cours. Ce n'est pas le seul existant, c'est simplement celui que je matrise le mieux.
Massivement utilis en entreprise, c'est un outil puissant, gratuit, libre et multiplateforme. Les avantages d'un IDE dans le
dveloppement d'applications web Java EE sont multiples, et sans toutefois tre exhaustif en voici une liste :
intgration des outils ncessaires au dveloppement et au dploiement d'une application ;
paramtrage ais et centralis des composants d'une application ;
multiples moyens de visualisation de l'architecture d'une application ;
gnration automatique de portions de code ;
assistance la vole lors de l'criture du code ;
outils de dbogage

Tlchargement et installation
Comme vous pouvez le constater en vous rendant sur la page de tlchargements du site, Eclipse est dclin en plusieurs
versions. Nous avons bien entendu besoin de la version spcifique au dveloppement Java EE :

Page de tlchargement d'Eclipse pour Java EE


Cliquez sur "Eclipse IDE for Java EE Developers", puis choisissez et tlchargez la version correspondant votre systme
d'exploitation :

www.siteduzero.com

Partie 1 : Les bases du Java EE

15/345

Choix de la version correspondant votre systme d'exploitation


Une fois le logiciel tlcharg, installez-le de prfrence dans un rpertoire situ directement la racine de votre disque dur, et
dont le titre ne contient ni espaces ni caractres spciaux. Typiquement, vitez les dossiers du genre "Program Files" et consorts.
Ce n'est pas une obligation mais un simple conseil, qui vous vitera bien des ennuis par la suite. Je l'ai pour ma part install dans
un rpertoire que j'ai nomm eclipse et plac la racine de mon disque dur : on peut difficilement faire plus clair.
Pour ceux d'entre vous qui ont dj sur leur poste une version "Eclipse for Java developers" et qui ne souhaitent pas tlcharger
et installer la version pour Java EE, sachez qu'il est possible - mais bien moins agrable - d'y ajouter des plugins afin d'y
reproduire l'intgration de l'environnement Java EE. Si vous y tenez, voici les tapes suivre depuis votre fentre Eclipse :
1.
2.
3.
4.

Allez dans Help > Install New Software.


Choisissez le site "Indigo - http://download.eclipse.org/releases/indigo".
Droulez "Web, XML, and Java EE Development".
Cochez alors "JST Server Adapters" et "JST Server Adapters Extentions".

a rsoudra une partie des problmes que vous pourriez rencontrer par la suite en suivant ce cours.
Notez bien toutefois que je vous conseille de ne pas procder ainsi, et de repartir d'une version vierge d'Eclipse pour Java EE.

Configuration
Ci-dessous, je vous donne quelques conseils pour configurer votre Eclipse efficacement. Je ne vais pas vous expliquer en dtail
pourquoi ces rglages sont importants, faites-moi simplement confiance et suivez le guide !

Modification de l'encodage par dfaut


Si vous ouvrez Eclipse pour la premire fois, commencez par fermer l'onglet de bienvenue qui s'affiche. Rendez-vous alors dans la
barre de menus suprieure, et cliquez sur Window, puis Preferences. Dans la fentre qui s'affiche alors, il y a un champ vous
permettant de taper du texte en haut gauche. Saisissez-y le mot "encoding ", et dans chaque section qui apparat alors dans le
volet de gauche, changez l'encodage par dfaut (il est gnralement rgl Cp1252 ou ISO-8859-1) par la valeur UTF-8 :

Validez pour finir en cliquant sur Ok afin d'appliquer les modifications.

Dsactivation de la vrification de l'orthographe


Rendez-vous nouveau dans le menu Window > Preferences, puis dans le volet de gauche rendez-vous dans General > Editors
> Text Editors, et dans le volet de droite cochez la case "Show line numbers". Dans le volet de gauche, cliquez alors sur le sousmenu "Spelling", et dans le nouveau volet de droite qui apparat, dcochez la case "Enable spell checking".

www.siteduzero.com

Partie 1 : Les bases du Java EE

16/345

Validez pour finir en cliquant sur Ok afin d'appliquer les modifications.

Le serveur Tomcat
Prsentation
Nous l'avons dcouvert dans le second chapitre : pour faire fonctionner une application web Java EE, nous avons besoin de
mettre en place un serveur d'applications. Il en existe beaucoup sur le march : j'ai, pour le dbut de ce cours, choisi d'utiliser
Tomcat, car c'est un serveur lger, gratuit, libre, multiplateforme et assez complet pour ce que nous allons aborder. On le
rencontre d'ailleurs trs souvent dans des projets en entreprise, en phase de dveloppement comme en production.
Si vous souhaitez vous renseigner sur les autres serveurs existants et sur leurs diffrences, vous savez o chercher. Wikipdia
en propose par ailleurs une liste non exhaustive.
Pour information, sachez que Tomcat tire sa lgret du fait qu'il n'est en ralit que l'assemblage d'un serveur web
(gestion des requtes/rponses HTTP) et d'un conteneur web (nous parlerons en temps voulu de conteneur de
servlets, et reviendrons sur ce que cela signifie concrtement). Pour le moment, retenez simplement que ce n'est pas un
serveur d'applications Java EE au sens complet du terme, car il ne respecte pas entirement ses spcifications et ne
supporte pas toutes ses technologies.

Installation
Nous allons utiliser la dernire version en date ce jour, savoir Tomcat 7.0. Rendez-vous sur la page de tlchargement de
Tomcat, puis choisissez et tlchargez la version correspondant votre systme d'exploitation :

www.siteduzero.com

Partie 1 : Les bases du Java EE

17/345

Page de tlchargement de Tomcat

Sous Windows
Rcuprez la dernire version Core au format zip, puis dcompressez son contenu dans le rpertoire o vous souhaitez installer
Tomcat. Au sujet du rpertoire d'installation, mme conseil que pour Eclipse : choisissez un chemin dont les noms de dossiers ne
comportent pas d'espaces : pour ma part, je l'ai plac dans un dossier nomm tomcat7 la racine de mon disque. Un dossier
nomm apache-tomcat-7.0.xx (les deux derniers numros changeant selon la version que vous utiliserez) contient alors
l'installation. Pour information, ce dossier est souvent rfrenc dans les cours et documentations sous lappellation Tomcat
Home. Voici ce que j'obtiens sur mon poste :

www.siteduzero.com

Partie 1 : Les bases du Java EE

18/345

Rpertoire d'installation de Tomcat


Dans ce rpertoire d'installation de Tomcat, vous trouverez un dossier nomm webapps : c'est ici que seront stockes par dfaut
vos applications. Pour ceux d'entre vous qui souhaiteraient jeter un il ce qui se passe derrire les rideaux, vous trouverez
dans le dossier conf les fichiers suivants :
server.xml : contient les lments de configuration du serveur ;
context.xml : contient les directives communes toutes les applications web dployes sur le serveur ;
tomcat-users.xml : contient entre autres l'identifiant et le mot de passe permettant d'accder l'interface d'administration
de votre serveur Tomcat ;
web.xml : contient les paramtres de configuration communs toutes les applications web dployes sur le serveur.
Je ne m'attarde pas sur le contenu de chacun de ces fichiers : nous y effectuerons des modifications indirectement via
l'interface d'Eclipse au cours des exemples venir. Je n'aborde volontairement pas dans le dtail la configuration fine
d'un serveur Tomcat, ceci mritant sans aucun doute un tutoriel part entire. Vous pouvez nanmoins trouver
beaucoup d'informations sur Tomcat's Corner; bien que ce site traite des versions plus anciennes, la plupart des
concepts prsents sont toujours d'actualit. Je vous renvoie bien sr la documentation officielle de Tomcat 7, pour
plus d'exactitude.

Sous Linux
Rcuprez la dernire version Core au format tar.gz : une archive nomme apache-tomcat-7.0.xx.tar.gz est alors enregistre sur
votre poste, o xx correspond la sous-version courante. Au moment o j'cris ces lignes, la version est la 7.0.20 : pensez
adapter les commandes qui suivent la version que vous tlchargez. Dcompressez ensuite son contenu dans le rpertoire o
vous souhaitez installer Tomcat. Par exemple :
Code : Console
cd /usr/local

www.siteduzero.com

Partie 1 : Les bases du Java EE

19/345

mkdir tomcat
cd /usr/local/tomcat
cp ~/apache-tomcat-7.0.20.tar.gz .
tar -xvzf apache-tomcat-7.0.20.tar.gz

Un dossier nomm apache-tomcat-7.0.20 contient alors l'installation. Pour information, ce dossier est souvent rfrenc dans les
cours et documentations sous lappellation Tomcat Home. Vrifiez alors que l'installation s'est bien effectue :
Code : Console
cd /usr/local/tomcat/apache-tomcat-7.0.20
cd bin
./version.sh

Ce script montre que Tomcat 7.0 a t install avec succs sur votre distribution Linux :
Code : Console
Server version:
Server built:
Server number:
OS Name:

Apache Tomcat/7.0.20
Aug 28 2011 15:13:02
7.0.20.0
Linux

Sous Mac OS
Je n'ai malheureusement pas ma disposition de machine tournant sous Mac OS. Si vous tes un aficionado de la marque la
pomme, voici deux liens qui expliquent comment installer Tomcat 7 sur OS X :
Installation de Tomcat 7.0.x sur Mac OS X
Installation sous Mac OS X Snow Leopard
Bonne lecture, et n'hsitez pas me prvenir d'ventuelles erreurs ou changements dans le procd prsent, je modifierai cette
section du chapitre en consquence.

Cration du projet web avec Eclipse


Depuis Eclipse, suivez le chemin suivant : File > New > Project...
Ceci peut d'ailleurs tre raccourci en tapant au clavier Ctrl + N :

www.siteduzero.com

Partie 1 : Les bases du Java EE

20/345

Nouveau projet web sous

Eclipse
Slectionnez alors Dynamic Web Project comme le montre l'image ci-dessus, puis cliquez sur Next >. J'appelle ici mon projet
test. Remarquez ensuite le passage concernant le serveur :

www.siteduzero.com

Partie 1 : Les bases du Java EE

21/345

Mise en place de Tomcat - tape

1
Cliquez sur le bouton New Runtime... et slectionnez alors Apache Tomcat 7.0 dans la liste des possibilits :

www.siteduzero.com

Partie 1 : Les bases du Java EE

22/345

Mise en place de Tomcat - tape 2

Cochez la case comme indiqu ci-dessus, ce qui signifie que nous allons en plus du projet crer localement une nouvelle
instance d'un serveur, instance que nous utiliserons par la suite pour dployer notre application. Cliquez ensuite sur Next > et
remplissez correctement les informations relatives votre installation de Tomcat en allant chercher le rpertoire d'installation de
Tomcat sur votre poste. Les champs devraient alors ressembler ceci, le rpertoire d'installation et le numro de version de
Tomcat 7 pouvant tre diffrents chez vous selon ce que vous avez choisi et install :

www.siteduzero.com

Partie 1 : Les bases du Java EE

23/345

Mise en place de Tomcat - tape 3

Validez alors en cliquant sur Finish, puis cliquez deux fois sur Next >, jusqu' obtenir cette fentre :

www.siteduzero.com

Partie 1 : Les bases du Java EE

24/345

Mise en place de Tomcat - tape

4
Avant d'aller plus loin, il est ncessaire de parler contexte !
Souvenez-vous, je vous ai dj parl d'un fichier context.xml associ toutes les applications. Pour permettre plus de souplesse,
il est possible de spcifier un contexte propre chaque webapp. Comme je vous l'ai dj dit, ces applications web sont
empiriquement contenues dans le dossier webapps de votre Tomcat Home. C'est ici que, par dfaut, Tomcat ira chercher les
applications qu'il doit grer et dployer. Jusque-l, vous suivez
Le souci, et certains d'entre vous l'auront peut-tre dj compris, c'est que notre projet nous, cr depuis Eclipse, se trouve
dans un rpertoire de notre workspace Eclipse : il n'est pas du tout dans ce fameux rpertoire webapps de Tomcat. Pour que
notre serveur prenne en compte notre future application, il va donc falloir arranger le coup ! Plusieurs solutions s'offrent nous :
crer un rpertoire du mme nom que notre projet sous Eclipse, directement dans le dossier webapps de Tomcat, et y
copier-coller nos fichiers, et ce chaque modification de code ou configuration effectue ;
crer un nouveau projet depuis Eclipse, en utilisant directement le rpertoire webapps de votre Tomcat Home comme
workspace Eclipse ;
modifier le server.xml ou le context.xml de votre Tomcat, afin qu'il sache o chercher ;
utiliser les proprits d'un projet web dynamique sous Eclipse.

www.siteduzero.com

Partie 1 : Les bases du Java EE

25/345

tant donn la dernire fentre qui s'est affiche, vous avez probablement devin sur quelle solution notre choix va se porter. Je
vous conseille bien videmment ici d'utiliser la quatrime et dernire solution. Conservez le nom de votre projet sous Eclipse
comme contexte de dploiement sur votre serveur Tomcat ("Context root" sur l'image prcdente), afin de rester cohrent.
Utiliser les paramtres ci-dessus permet alors de ne pas avoir modifier vous-mmes le contexte de votre serveur, ou encore de
ne pas avoir utiliser le dossier webapps de votre serveur Tomcat en guise de workspace. Toute modification sur vos futures
pages et classes sera ainsi automatiquement prise en compte par votre serveur Tomcat, qui s'occupera de recharger le contexte
chaque modification sauvegarde, lorsque le serveur sera lanc.
Comme diraient les ttes claques, isn't it amazing?
Voici maintenant quoi doit ressembler votre fentre Eclipse :

Mise en place de Tomcat - tape 5


Vous noterez l'apparition d'une entre Tomcat v7.0 dans l'onglet Servers, et de l'arborescence de votre projet test dans le volet de
gauche.
Faites maintenant un clic droit sur le titre de votre projet dans l'arborescence Eclipse, et suivez Run As > Run on Server :

www.siteduzero.com

Partie 1 : Les bases du Java EE

26/345

Mise en place

de Tomcat - tape 6
Dans la fentre qui s'ouvre alors, nous allons slectionner le serveur Tomcat que nous venons de mettre en place lors de la
cration de notre projet web, et prciser que l'on souhaite associer par dfaut notre projet ce serveur :

www.siteduzero.com

Partie 1 : Les bases du Java EE

27/345

Mise en place de Tomcat - tape

7
Cliquez alors sur Next >, puis vrifiez que votre nouveau projet est bien pris en compte par votre serveur :

www.siteduzero.com

Partie 1 : Les bases du Java EE

28/345

Mise en place de Tomcat - tape

8
Validez enfin en cliquant sur Finish, et voil la mise en place de votre projet et de son serveur termine !
Pour la petite histoire, une section est ajoute dans le fichier server.xml de votre instance de Tomcat, qui est maintenant
accessible depuis le dossier Servers de votre arborescence Eclipse :

www.siteduzero.com

Partie 1 : Les bases du Java EE

29/345

Mise en

place de Tomcat - tape 9


Si vous tes curieux, ditez-le ! Vous verrez qu'il contient effectivement en fin de fichier une section de ce type :
Code : XML
<Context docBase="test" path="/test" reloadable="true"
source="org.eclipse.jst.jee.server:test"/>

Dornavant, pour piloter votre serveur Tomcat il vous suffira de vous rendre dans l'onglet Servers en bas de votre fentre
Eclipse, et d'utiliser un des boutons selon le besoin (redmarrage, arrt, debug) :

Mise

en place de Tomcat - tape 10


Sachez pour finir, que cette manipulation n'est pas limite Tomcat. Vous pouvez utiliser d'autres types de serveurs,
cela ne pose pas de problmes. De mme, une fois que vous avez correctement paramtr un serveur Tomcat depuis
Eclipse, vous n'tes pas forcs de recrer localement un nouveau serveur pour chacun de vos projets, vous pouvez
trs bien rutiliser la mme instance de Tomcat en y dployant plusieurs applications web diffrentes.

Si vous tes arrivs jusqu'ici, c'est que votre instance de serveur Tomcat est fonctionnelle et que vous pouvez la piloter depuis
Eclipse. Voyons maintenant o placer notre premier essai, et comment y accder.

Structure d'une application Java EE


www.siteduzero.com

Partie 1 : Les bases du Java EE

30/345

Structure standard
Toute application web Java EE doit respecter une structure de dossiers standard, qui est dfinie dans les spcifications de la
plate-forme :

Structure des fichiers d'une application web JSP/Servlet


Quelques prcisions :
La racine de l'application, en violet sur le schma, est le dossier qui porte le nom de votre projet et qui contient
l'intgralit des dossiers et fichiers de l'application.
Le dossier nomm WEB-INF est un dossier spcial. Il doit obligatoirement exister et tre plac juste sous la racine de
l'application. Il doit son tour obligatoirement contenir :
le fichier de configuration de l'application (web.xml) ;
un dossier nomm classes, qui contient son tour les classes compiles (fichiers .class) ;
un dossier nomm lib, qui contient son tour les bibliothques ncessaires au projet (archives .jar).
Bref, tous les dossiers et fichiers marqus en rouge sur le schma doivent obligatoirement tre nomms et placs comme
indiqu sur le schma.
Les fichiers et dossiers persos placs directement sous la racine, en bleu sur le schma, sont publics et donc accessibles
directement par le client via leurs URL. (*)
Les fichiers et dossiers persos placs sous le rpertoire WEB-INF, en orange sur le schma, sont privs et ne sont donc
pas accessibles directement par le client. (*)
(*) Nous reviendrons en temps voulu sur le caractre priv du dossier WEB-INF , et sur la distinction avec les dossiers
publics.
Voil tout concernant la structure officielle : si votre application n'est pas organise de cette manire, le serveur
d'applications ne sera pas capable de la dployer ni de la faire fonctionner correctement.

Votre premire page web


www.siteduzero.com

Partie 1 : Les bases du Java EE

31/345

Eclipse, ce fourbe !
Ce que vous devez savoir avant de continuer, c'est qu'Eclipse joue souvent au fourbe, en adaptant certaines spcificits son
mode de fonctionnement. En l'occurrence, Eclipse modifie comme suit la structure d'une application Java EE :

Structure des fichiers d'une application web sous Eclipse


Comme vous pouvez le voir en vert sur le schma, Eclipse dplace la structure standard de l'application vers un dossier nomm
WebContent, et ajoute sous la racine un dossier src qui contiendra le code source de vos classes (les fichiers .java). En outre (je
ne les ai pas reprsents ici), sachez qu'Eclipse ajoute galement sous la racine quelques fichiers de configuration qui lui
permettront, via une tambouille interne, de grer correctement l'application !
Attendez... Je viens de vous dire que si notre application n'tait pas correctement structure, notre serveur
d'applications ne saurait pas la grer. Si Eclipse vient mettre son nez dans cette histoire, comment notre application vat-elle pouvoir fonctionner ?
Eh bien comme je viens de vous l'annoncer, Eclipse se dbrouille via une tambouille interne pour que la structure qu'il a modifie
soit, malgr tout, utilisable sur le serveur d'applications que nous lui avons intgr. Ceci implique donc deux choses trs
importantes :
le dossier WebContent n'existe lgitimement qu'au sein d'Eclipse. Si vous dveloppez sans IDE, ce rpertoire ne doit pas
exister et votre application doit imprativement suivre la structure standard prsente prcdemment ;
pour cette mme raison, si vous souhaitez utiliser votre application en dehors de l'IDE, il faudra obligatoirement utiliser
l'outil d'export propos par Eclipse. Raliser un simple copier-coller des dossiers ne fonctionnera pas en dehors d'Eclipse
! L encore, nous y reviendrons plus tard.

Cration d'une page web

www.siteduzero.com

Partie 1 : Les bases du Java EE

32/345

Vous avez maintenant en mains toutes les informations pour bien dbuter. Votre projet dynamique frachement cr, vous pouvez
maintenant placer votre premire page HTML dans son dossier public, c'est--dire sous le dossier WebContent d'Eclipse (voir le
bloc bleu sur notre schma). Pour cela, tapez une nouvelle fois Ctrl + N au clavier, puis cherchez HTML File dans le dossier Web
de l'arborescence qui apparat alors. Slectionnez ensuite le dossier parent, en l'occurrence le dossier WebContent de votre
projet, puis donnez un nom votre page et enfin validez. Je nomme ici ma page test.html :

Cration d'une page HTML dans

votre projet

www.siteduzero.com

Partie 1 : Les bases du Java EE

33/345

Saisie du dossier parent et du

nom de la page HTML


Une page HTML est donc apparue dans votre projet, sous le rpertoire WebContent. Remplacez alors le code automatiquement
gnr par Eclipse dans votre page par ce code HTML basique :
Code : HTML - test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page HTML.</p>
</body>
</html>

Vous pouvez maintenant tenter d'accder votre page web frachement cre. Pour ce faire, lancez le serveur Tomcat, via le
bouton
si vous avez bien suivi les instructions que je vous ai prsentes prcdemment. Ouvrez ensuite votre navigateur
prfr, et entrez l'URL suivante afin d'accder votre serveur :
Code : URL

www.siteduzero.com

Partie 1 : Les bases du Java EE

34/345

http://localhost:8080/test/test.html

Votre page s'affiche alors sous vos yeux dus !?


C'est quoi toute cette histoire ? Tout un flan pour afficher trois mots ?

Patience, patience Notre serveur tant maintenant fonctionnel, nous voici prts entrer dans le vif du sujet.

En rsum
Un IDE permet de simplifier le dveloppement d'un projet dans son ensemble.
Tomcat n'est pas un serveur d'applications Java EE au sens complet du terme.
La configuration du serveur passe principalement par deux fichiers : server.xml et web.xml.
Une application web Java EE doit respecter une architecture bien dfinie.
Eclipse modifie l'architecture des applications pour les intgrer correctement son systme.
Nous sommes maintenant prts pour dvelopper notre premire application web. Allons-y !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

35/345

Partie 2 : Premiers pas avec Java EE


Le travail srieux commence : au programme, dcouverte & cration de votre premire servlet, de votre premire page JSP et de
votre premier JavaBean, et apprentissage du langage JSP ! Cette partie se terminera enfin par un rcapitulatif de ce que nous
serons alors capables de faire, et de ce qui nous manquera encore.

La servlet
Nous y voil enfin ! Nous allons commencer par dcouvrir ce qu'est une servlet, son rle au sein de l'application et comment elle
doit tre mise en place.
J'adopte volontairement pour ce chapitre un rythme assez lent, afin que vous preniez bien conscience des fondements de cette
technologie.
Pour ceux qui trouveraient cela barbant, comprenez bien que c'est important de commencer par l et rassurez-vous, nous ne nous
soucierons bientt plus de tous ces dtails !

Derrire les rideaux


Retour sur HTTP
Avant d'tudier le code d'une servlet, nous devons nous pencher un instant sur le fonctionnement du protocole HTTP. Pour le
moment, nous avons simplement appris que c'tait le langage qu'utilisaient le client et le serveur pour s'changer des
informations. Il nous faudrait idalement un chapitre entier pour l'tudier en dtail, mais nous ne sommes pas l pour a ! Je vais
donc tcher de faire court
Si nous observions d'un peu plus prs ce langage, nous remarquerions alors qu'il ne comprend que quelques mots, appels
mthodes HTTP. Ce sont les mots qu'utilise le navigateur pour poser des questions au serveur. Mieux encore, je vous annonce
d'emble que nous ne nous intresserons qu' trois de ces mots : GET, POST et HEAD.

GET
C'est la mthode utilise par le client pour rcuprer une ressource web du serveur via une URL. Par exemple, lorsque vous tapez
www.siteduzero.com dans la barre d'adresses de votre navigateur et que vous validez, votre navigateur envoie une requte GET
pour rcuprer la page correspondant cette adresse et le serveur la lui renvoie. La mme chose se passe lorsque vous cliquez
sur un lien.
Lorsqu'il reoit une telle demande, le serveur ne fait pas que retourner la ressource demande, il en profite pour l'accompagner
d'informations diverses son sujet, dans ce qui s'appelle les en-ttes ou headers HTTP : typiquement, on y trouve des
informations comme la longueur des donnes renvoyes ou encore la date d'envoi.
Enfin, sachez qu'il est possible de transmettre des donnes au serveur lorsque l'on effectue une requte GET, au travers de
paramtres directement placs aprs l'URL (paramtres nomms query strings) ou de cookies placs dans les en-ttes de la
requte : nous reviendrons en temps voulu sur ces deux manires de faire. La limite de ce systme est que, comme la taille d'une
URL est limite, on ne peut pas utiliser cette mthode pour envoyer des donnes volumineuses au serveur, comme par exemple
un fichier.
Les gens qui ont crit la norme dcrivant le protocole HTTP ont mis des recommandations d'usage, que les
dveloppeurs sont libres de suivre ou non. Celles-ci prcisent que via cette mthode GET, il est uniquement possible de
rcuprer ou de lire des informations, sans que cela ait un quelconque impact sur la ressource demande : ainsi, une
requte GET est cense pouvoir tre rpte indfiniment sans risques pour la ressource concerne.

POST
La taille du corps du message d'une requte POST n'est pas limite, c'est donc cette mthode qu'il faut utiliser pour soumettre au
serveur des donnes de tailles variables, ou que l'on sait volumineuses. C'est parfait pour envoyer des fichiers par exemple.
Toujours selon les recommandations d'usage, cette mthode doit tre utilise pour raliser les oprations qui ont un effet sur la
ressource, et qui ne peuvent par consquent pas tre rptes sans l'autorisation explicite de l'utilisateur. Vous avez
probablement dj reu de votre navigateur un message d'alerte aprs avoir actualis une page web, vous prvenant qu'un
rafrachissement de la page entranera un renvoi des informations : eh bien c'est simplement parce que la page que vous
souhaitez recharger a t rcupre via la mthode POST, et que le navigateur vous demande confirmation avant de renvoyer

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

36/345

nouveau la requte.

HEAD
Cette mthode est identique la mthode GET, ceci prs que le serveur n'y rpondra pas en renvoyant la ressource
accompagne des informations la concernant, mais seulement ces informations. En d'autres termes, il renvoie seulement les enttes HTTP ! Il est ainsi possible par exemple de vrifier la validit d'une URL ou de vrifier si le contenu d'une page a chang ou
non sans avoir rcuprer la ressource elle-mme : il suffit de regarder ce que contiennent les diffrents champs des en-ttes. Ne
vous inquitez pas, nous y reviendrons lorsque nous manipulerons des fichiers.

Pendant ce temps l, sur le serveur


Rappelez-vous notre schma global : la requte HTTP part du client et arrive sur le serveur.
L'lment qui entre en jeu est alors le serveur HTTP (on parle galement de serveur web), qui ne fait qu'couter les requtes
HTTP sur un certain port, en gnral le port 80.
Que fait-il lorsqu'une requte lui parvient ?

Nous savons dj qu'il la transmet un autre lment, que nous avons jusqu' prsent qualifi de conteneur : il s'agit en ralit
d'un conteneur de servlets, galement nomm conteneur web. Celui-ci va alors crer deux nouveaux objets :
HttpServletRequest : cet objet contient la requte HTTP, et donne accs toutes ses informations, telles que les
en-ttes (headers) et le corps de la requte.
HttpServletResponse : cet objet initialise la rponse HTTP qui sera renvoye au client, et permet de la
personnaliser, en initialisant par exemple les en-ttes et le corps (nous verrons comment par la suite).

Conteneur et paire d'objets requte/rponse

Et ensuite ? Que fait-il de ce couple d'objets ?

Eh bien ce moment prcis, c'est votre code qui va entrer en jeu (reprsent par la srie de rouages sur le schma). En effet, le
conteneur de servlets va les transmettre votre application, et plus prcisment aux servlets et filtres que vous avez
ventuellement mis en place. Le cheminement de la requte dans votre code commence peine, et nous devons dj nous arrter
: qu'est-ce qu'une servlet ?

Cration
Une servlet est en ralit une simple classe Java, qui a la particularit de permettre le traitement de requtes et la

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

37/345

personnalisation de rponses. Pour faire simple, dans la trs grande majorit des cas une servlet n'est rien d'autre qu'une classe
capable de recevoir une requte HTTP envoye depuis le navigateur de l'utilisateur, et de lui renvoyer une rponse HTTP. C'est
tout !
En principe, une servlet dans son sens gnrique est capable de grer n'importe quel type de requte, mais dans les
faits il s'agit principalement de requtes HTTP. Ainsi, l'usage veut qu'on ne s'embte pas prciser "servlet HTTP"
lorsque l'on parle de ces dernires, et il est donc extrmement commun d'entendre parler de servlets alors qu'il s'agit
bien en ralit de servlets HTTP. Dans la suite de ce cours, je ferai de mme.

Un des avantages de la plate-forme Java EE est sa documentation : trs fournie et offrant un bon niveau de dtails, la Javadoc
permet en un rien de temps de se renseigner sur une classe, une interface ou un package de l'API Java EE. Tout au long de ce
cours, je mettrai votre disposition des liens vers les documentations des objets importants, afin que vous puissiez facilement,
par vous-mmes, complter votre apprentissage et vous familiariser avec ce systme de documentation.
Regardons donc ce qu'elle contient au chapitre concernant le package servlet : on y trouve une quarantaine de classes et
interfaces, parmi lesquelles l'interface nomme Servlet. En regardant celle-ci de plus prs, on apprend alors qu'elle est
l'interface mre que toute servlet doit obligatoirement implmenter.
Mieux encore, on apprend en lisant sa description qu'il existe dj des classes de base qui l'implmentent, et qu'il nous suffit
donc d'hriter d'une de ces classes pour crer une servlet :

Javadoc de

l'interface Servlet
Nous souhaitons traiter des requtes HTTP, nous allons donc faire hriter notre servlet de la classe HttpServlet !
De retour sur votre projet Eclipse, faites un clic droit sur le rpertoire src, puis choisissez New > Class. Renseignez alors la
fentre qui s'ouvre comme suit :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

38/345

text

Cration d'une servlet

Renseignez le champ package par un package de votre choix : pour notre projet, j'ai choisi de le nommer
com.sdzee.servlets !
Renseignez le nom de la servlet, puis cliquez ensuite sur le bouton Browse... afin de dfinir de quelle classe doit hriter notre

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

39/345

servlet, puis allez chercher la classe HttpServlet et validez. Voici le code que vous obtenez alors automatiquement :
Code : Java - com.sdzee.servlets.Test
package com.sdzee.servlets;
import javax.servlet.http.HttpServlet;
public class Test extends HttpServlet {
}

Rien d'extraordinaire pour le moment, notre servlet tant absolument vide. D'ailleurs puisqu'elle ne fait encore rien, sautons sur
l'occasion pour prendre le temps de regarder ce que contient cette classe HttpServlet hrite, afin de voir un peu ce qui se
passe derrire. La Javadoc nous donne des informations utiles concernant le fonctionnement de cette classe : pour commencer
c'est une classe abstraite, ce qui signifie qu'on ne pourra pas l'utiliser telle quelle et qu'il sera ncessaire de passer par une servlet
qui en hrite. On apprend ensuite que la classe propose les mthodes Java ncessaires au traitement des requtes et rponses
HTTP ! Ainsi, on y trouve les mthodes :
doGet() pour grer la mthode GET ;
doPost() pour grer la mthode POST ;
doHead() pour grer la mthode HEAD.
Comment la classe fait-elle pour associer chaque type de requte HTTP la mthode Java qui lui correspond ?

Vous n'avez pas vous en soucier, ceci est gr automatiquement par sa mthode service() : c'est elle qui se charge de lire
l'objet HttpServletRequest et de distribuer la requte HTTP la mthode doXXX() correspondante.
Ce qu'il faut retenir pour le moment :
une servlet HTTP doit hriter de la classe abstraite HttpServlet ;
une servlet doit implmenter au moins une des mthodes doXXX(), afin d'tre capable de traiter une requte entrante.
Puisque ce sont elles qui prennent en charge les requtes entrantes, les servlets vont tre les points d'entre de notre
application web, c'est par elles que tout va passer. Contrairement au Java SE, il n'existe pas en Java EE de point d'entre
unique prdfini, comme pourrait l'tre la mthode main()

Mise en place
Vous le savez, les servlets jouent un rle trs particulier dans une application. Je vous ai parl d'aiguilleurs en introduction, on
peut encore les voir comme des gendarmes : si les requtes taient des vhicules, les servlets seraient charges de faire la
circulation sur le gigantesque carrefour qu'est votre application ! Eh bien pour obtenir cette autorit et tre reconnues en tant
que telles, les servlets ncessitent un traitement de faveur : il va falloir les enregistrer auprs de notre application.
Revenons notre exemple. Maintenant que nous avons cod notre premire servlet, il nous faut donc un moyen de faire
comprendre notre application que notre servlet existe, la fois pour lui donner l'autorit sur les requtes et pour la rendre
accessible au public ! Lorsque nous avions mis en place une page HTML statique dans le chapitre prcdent, le problme ne se
posait pas : nous accdions directement la page en question via une URL directe pointant vers le fichier depuis notre
navigateur.
Mais dans le cas d'une servlet qui, rappelons-le, est une classe Java, comment faire ?

Concrtement, il va falloir configurer quelque part le fait que notre servlet va tre associe une URL. Ainsi lorsque le client la
saisira, la requte HTTP sera automatiquement aiguille par notre conteneur de servlet vers la bonne servlet, celle qui est en
charge de rpondre cette requte. Ce "quelque part" se prsente sous la forme d'un simple fichier texte : le fichier web.xml.
C'est le cur de votre application : ici vont se trouver tous les paramtres qui contrlent son cycle de vie. Nous n'allons pas
apprendre d'une traite toutes les options intressantes, mais y aller par tapes. Commenons donc par apprendre lier notre
servlet une URL : aprs tous les efforts que nous avons fournis, c'est le minimum syndical que nous sommes en droit de lui

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

40/345

demander !
Ce fichier de configuration doit imprativement se nommer web.xml et se situer juste sous le rpertoire /WEB-INF de votre
application. Si vous avez suivi la lettre la procdure de cration de notre projet web, alors ce fichier est dj prsent. ditez-le,
et supprimez le contenu gnr par dfaut. Si jamais le fichier est absent de votre arborescence, crez simplement un nouveau
fichier XML en veillant bien le placer sous le rpertoire /WEB-INF et le nommer web.xml. Voici la structure vide du fichier :
Code : XML - Fichier /WEB-INF/web.xml vide
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>

L'intgralit de son contenu devra tre plac entre les balises <web-app> et </web-app>.
Pour le moment, ne prtez pas attention aux nombreux attributs prsents au sein de cette balise <web-app>, nous
reviendrons sur leur rle lorsque nous dcouvrirons les expressions EL.
La mise en place d'une servlet se droule en deux tapes : nous devons d'abord dclarer la servlet, puis lui faire correspondre
une URL.

Dfinition de la servlet
La premire chose faire est de dclarer notre servlet : en quelque sorte il s'agit de lui donner une carte d'identit, un moyen pour
le serveur de la reconnatre. Pour ce faire, il faut ajouter une section au fichier qui se prsente ainsi sous sa forme minimale :
Code : XML - Dclaration de notre servlet
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>com.sdzee.servlets.Test</servlet-class>
</servlet>

La balise responsable de la dfinition d'une servlet se nomme logiquement <servlet>, et les deux balises obligatoires de cette
section sont trs explicites :
<servlet-name> permet de donner un nom une servlet. C'est ensuite via ce nom qu'on fera rfrence la servlet en
question. Ici, j'ai nomm notre servlet Test.
<servlet-class> sert prciser le chemin de la classe de la servlet dans votre application. Ici, notre classe a bien
pour nom Test et se situe bien dans le package com.sdzee.servlets.
Bonne pratique : gardez un nom de classe et un nom de servlet identiques. Bien que ce ne soit en thorie pas
ncessaire, cela vous vitera des ennuis ou des confusions par la suite.

Il est par ailleurs possible d'insrer au sein de la dfinition d'une servlet d'autres balises facultatives :
Code : XML - Dclaration de notre servlet avec options
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>com.sdzee.servlets.Test</servlet-class>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

41/345

<description>Ma premire servlet de test.</description>


<init-param>
<param-name>auteur</param-name>
<param-value>Coyote</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

On dcouvre ici trois nouveaux blocs :


<description> permet de dcrire plus amplement le rle de la servlet. Cette description n'a aucune utilit technique
et n'est visible que dans ce fichier ;
<init-param> permet de prciser des paramtres qui seront accessibles la servlet lors de son chargement. Nous y
reviendrons en dtail plus tard dans ce cours ;
<load-on-startup> permet de forcer le chargement de la servlet ds le dmarrage du serveur. Nous reviendrons sur
cet aspect un peu plus loin dans ce chapitre.

Mapping de la servlet
Il faut ensuite faire correspondre notre servlet frachement dclare une URL, afin qu'elle soit joignable par les clients :
Code : XML - Mapping de notre servlet sur l'URL relative /toto
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/toto</url-pattern>
</servlet-mapping>

La balise responsable de la dfinition du mapping se nomme logiquement <servlet-mapping>, et les deux balises
obligatoires de cette section sont, l encore, trs explicites.
<servlet-name> permet de prciser le nom de la servlet laquelle faire rfrence. Cette information doit correspondre
avec le nom dfini dans la prcdente dclaration de la servlet.
<url-pattern> permet de prciser la ou les URL relatives au travers desquelles la servlet sera accessible. Ici, a sera
/toto !
Pourquoi un "pattern" et pas simplement une URL ?

En effet il s'agit bien d'un pattern, c'est--dire d'un modle, et pas ncessairement d'une URL fixe. Ainsi, on peut choisir de rendre
notre servlet responsable du traitement des requtes issues d'une seule URL, ou bien d'un groupe d'URL. Vous n'imaginez pour
le moment peut-tre pas de cas qui impliqueraient qu'une servlet doive traiter les requtes issues de plusieurs URL, mais
rassurez-vous nous ferons la lumire sur ce type d'utilisation dans la partie suivante de ce cours. De mme, nous dcouvrirons
qu'il est tout fait possible de dclarer plusieurs sections <servlet-mapping> pour une mme section <servlet> dans
le fichier web.xml.
Que signifie "URL relative" ?

Cela veut dire que l'URL ou le pattern que vous renseignez dans le champ <url-pattern> sont bass sur le contexte de votre
application. Dans notre cas, souvenez-vous du contexte de dploiement que nous avons prcis lorsque nous avons cr notre
projet web : nous l'avions appel test. Nous en dduisons donc que notre <url-pattern>/toto</url-pattern> fait
rfrence l'URL absolue /test/toto.
Nous y voil, notre servlet est maintenant joignable par le client via l'URL http://localhost:8080/test/toto.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

42/345

Pour information, le code final de notre fichier web.xml est donc :


Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>com.sdzee.servlets.Test</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/toto</url-pattern>
</servlet-mapping>
</web-app>

L'ordre des sections de dclaration au sein du fichier est important : il est impratif de dfinir une servlet avant de
spcifier son mapping.

Mise en service
Do you GET it?
Nous venons de crer un fichier de configuration pour notre application, nous devons donc redmarrer notre serveur pour que
ces modifications soient prises en compte. Il suffit pour cela de cliquer sur le bouton "start" de l'onglet Servers :

Bouton de

redmarrage du serveur Tomcat dans Eclipse


Faisons le test, et observons ce que nous affiche notre navigateur lorsque nous tentons d'accder l'URL
http://localhost:8080/test/toto que nous venons de mapper sur notre servlet :

Mthode HTTP non supporte


Nous voici devant notre premier code de statut HTTP. En l'occurrence, c'est la fois une bonne et une mauvaise nouvelle :
une bonne nouvelle, car cela signifie que notre mapping a fonctionn et que notre serveur a bien contact notre servlet !
une mauvaise nouvelle, car notre serveur nous retourne le code d'erreur 405 et nous prcise que la mthode GET n'est
pas supporte par la servlet que nous avons associe l'URL

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

43/345

Par qui a t gnre cette page d'erreur ?

Tout est parti du conteneur de servlets. D'ailleurs, ce dernier effectue pas mal de choses dans l'ombre, sans vous le dire ! Dans ce
cas prcis, il a :
1. reu la requte HTTP depuis le serveur web ;
2. gnr un couple d'objets requte/rponse ;
3. parcouru le fichier web.xml de votre application la recherche d'une entre correspondant l'URL contenue dans l'objet
requte ;
4. trouv et identifi la servlet que vous y avez dclare ;
5. contact votre servlet et transmis la paire d'objets requte/rponse.
Dans ce cas, pourquoi cette page d'erreur a-t-elle t gnre ?

Nous avons pourtant bien fait hriter notre servlet de la classe HttpServlet, notre servlet doit pouvoir interagir avec HTTP !
Qu'est-ce qui cloche ? Eh bien nous avons oubli une chose importante : afin que notre servlet soit capable de traiter une
requte HTTP de type GET, il faut y implmenter une mthode doGet() ! Souvenez-vous, je vous ai dj expliqu que la
mthode service() de la classe HttpServlet s'occupera alors elle-mme de transmettre la requte GET entrante vers la
mthode doGet() de notre servlet a vous revient ?
Maintenant, comment cette page d'erreur a-t-elle t gnre ?

C'est la mthode doGet() de la classe mre HttpServlet qui est en la cause. Ou plutt, disons que c'est grce elle ! En
effet, le comportement par dfaut des mthodes doXXX() de la classe HttpServlet est de renvoyer un code d'erreur HTTP
405 ! Donc si le dveloppeur a bien fait son travail, pas de problme : c'est bien la mthode doXXX() de la servlet qui sera
appele. Par contre, s'il a mal fait son travail et a oubli de surcharger la mthode doXXX() voulue, alors c'est la mthode de la
classe mre HttpServlet qui sera appele, et un code d'erreur sera gentiment et automatiquement renvoy au client. Ainsi, la
classe mre s'assure toujours que sa classe fille - votre servlet ! - surcharge bien la mthode doXXX() correspondant la
mthode HTTP traite !
Par ailleurs, votre conteneur de servlets est galement capable de gnrer lui-mme des codes d'erreur HTTP. Par
exemple, lorsqu'il parcourt le fichier web.xml de votre application la recherche d'une entre correspondant l'URL
envoye par le client, et qu'il ne trouve rien, c'est lui qui va se charger de gnrer le fameux code d'erreur 404 !

Nous voil maintenant au courant de ce qu'il nous reste faire : il nous suffit de surcharger la mthode doGet() de la classe
HttpServlet dans notre servlet Test. Voici donc le code de notre servlet :
Code : Java - Surcharge de la mthode doGet() dans notre servlet Test
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class Test extends HttpServlet {


public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
}

Comme vous pouvez le constater, l'ajout de cette seule mthode vide fait intervenir plusieurs imports qui dfinissent les objets et
exceptions prsents dans la signature de la mthode : HttpServletRequest, HttpServletResponse,

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

44/345

ServletException et IOException.
Ressayons alors de contacter notre servlet via notre URL : tout se passe comme prvu, le message d'erreur HTTP disparat.
Cela dit, notre servlet ne fait strictement rien de la requte HTTP reue : le navigateur nous affiche alors une page blanche !
Comment le client sait-il que la requte est arrive bon port ?

C'est une trs bonne remarque. En effet, si votre navigateur vous affiche une simple page blanche, c'est parce qu'il considre la
requte comme termine avec succs : si ce n'tait pas le cas, il vous afficherait un des codes et messages d'erreur HTTP Si
vous utilisez le navigateur Firefox, vous pouvez utiliser l'onglet Rseau de l'outil Firebug pour visualiser qu'effectivement, une
rponse HTTP est bien reue par votre navigateur (si vous utilisez le navigateur Chrome, vous pouvez accder un outil
similaire en appuyant sur F12 ) :

En-ttes de la rponse HTTP avec Firebug


On y observe :
un code HTTP 200 OK, qui signifie que la requte s'est effectue avec succs ;
la longueur des donnes contenues dans la rponse (Content-Length) : 0...
Eh bien encore une fois, c'est le conteneur de servlets qui a fait le boulot sans vous prvenir ! Quand il a gnr la paire d'objets
requte/rponse, il a initialis le statut de la rponse avec une valeur par dfaut : 200. C'est--dire que par dfaut, le conteneur de
servlets cre un objet rponse qui stipule que tout s'est bien pass. Ensuite, il transmet cet objet votre servlet, qui est alors
libre de le modifier sa guise. Lorsqu'il reoit nouveau l'objet en retour, si le code de statut n'a pas t modifi par la servlet,
c'est que tout s'est bien pass. En d'autres termes, le conteneur de servlets adopte une certaine philosophie : pas de nouvelles,
bonne nouvelle !

Le serveur retourne donc toujours une rponse au client, peu importe ce que fait notre servlet avec la requte ! Dans
notre cas, la servlet n'effectue aucune modification sur l'objet HttpServletResponse, et par consquent n'y insre
aucune donne et n'y modifie aucune en-tte. D'o la longueur initialise zro dans l'en-tte de la rponse, le code de
statut initialis 200 et la page blanche en guise de rsultat final !

Cycle de vie d'une servlet


www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

45/345

Dans certains cas, il peut s'avrer utile de connatre les rouages qui se cachent derrire une servlet. Toutefois, je ne
souhaite pas vous embrouiller ds maintenant : vous n'en tes qu'aux balbutiements de votre apprentissage et n'avez
pas assez d'exprience pour intervenir proprement sur l'initialisation d'une servlet. Je ne vais par consquent qu'aborder
rapidement son cycle de vie au sein du conteneur, travers ce court apart. Nous lverons le voile sur toute cette
histoire dans un chapitre en annexe de ce cours, et en profiterons pour utiliser le puissant outil de debug d'Eclipse !

Quand une servlet est demande pour la premire fois ou quand l'application web dmarre, le conteneur de servlets va crer une
instance de celle-ci et la garder en mmoire pendant toute l'existence de l'application. La mme instance sera rutilise pour
chaque requte entrante dont les URL correspondent au pattern d'URL dfini pour la servlet. Dans notre exemple, aussi
longtemps que notre serveur restera en ligne, tous nos appels vers l'URL /test/toto seront dirigs vers la mme et unique
instance de notre servlet, gnre par Tomcat lors du tout premier appel.
En fin de compte, l'instance d'une servlet est-elle cre lors du premier appel cette servlet, ou bien ds le dmarrage du
serveur ?
Ceci dpend en grande partie du serveur d'applications utilis. Dans notre cas, avec Tomcat, c'est par dfaut au premier appel
d'une servlet que son unique instance est cre.
Toutefois, ce mode de fonctionnement est configurable. Plus tt dans ce chapitre, je vous expliquais comment dclarer une
servlet dans le fichier web.xml, et j'en ai profit pour vous prsenter une balise facultative : <load-on-startup>N</loadon-startup>, o N doit tre un entier positif. Si dans la dclaration d'une servlet vous ajoutez une telle ligne, alors vous
ordonnez au serveur de charger l'instance de la servlet en question directement pendant le chargement de l'application.
Le chiffre N correspond la priorit que vous souhaitez donner au chargement de votre servlet. Dans notre projet nous
n'utilisons pour le moment qu'une seule servlet, donc nous pouvons marquer n'importe quel chiffre suprieur ou gal zro, a
ne changera rien. Mais dans le cas d'une application contenant beaucoup de servlets, cela permet de dfinir quelle servlet doit
tre charge en premier. L'ordre est tabli du plus petit au plus grand : la ou les servlets ayant un load-on-startup initialis zro
sont les premires tre charges, puis 1, 2, 3, etc.
Voil tout pour cet apart. En ce qui nous concerne, nous n'utiliserons pas cette option de chargement dans nos projets, le
chargement des servlets lors de leur premire sollicitation nous ira trs bien !

Envoyer des donnes au client


Avec tout cela, nous n'avons encore rien envoy notre client, alors qu'en mettant en place une simple page HTML nous avions
affich du texte dans le navigateur du client en un rien de temps. Patience, les rponses vont venir Utilisons notre servlet pour
reproduire la page HTML statique que nous avions cre lors de la mise en place de Tomcat. Comme je vous l'ai expliqu dans le
paragraphe prcdent, pour envoyer des donnes au client il va falloir manipuler l'objet HttpServletResponse. Regardons
d'abord ce qu'il est ncessaire d'inclure notre mthode doGet(), et analysons tout cela ensuite :
Code : Java
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
response.setContentType("text/html");
response.setCharacterEncoding( "UTF-8" );
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset=\"utf-8\" />");
out.println("<title>Test</title>");
out.println("</head>");
out.println("<body>");
out.println("<p>Ceci est une page gnre depuis une
servlet.</p>");
out.println("</body>");
out.println("</html>");
}

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

46/345

Comment procdons-nous ?
1. Nous commenons par modifier l'en-tte Content-Type de la rponse HTTP, pour prciser au client que nous allons lui
envoyer une page HTML, en faisant appel la mthode setContentType() de l'objet HttpServletResponse.
2. Par dfaut, l'encodage de la rponse envoye au client est initialis ISO-8859-1. Si vous faites quelques recherches au
sujet de cet encodage, vous apprendrez qu'il permet de grer sans problmes les caractres de notre alphabet, mais qu'il
ne permet pas de manipuler les caractres asiatiques, les alphabets arabes, cyrilliques, scandinaves ainsi que d'autres
caractres plus exotiques. Afin de permettre une gestion globale d'un maximum de caractres diffrents, il est
recommand d'utiliser l'encodage UTF-8 la place. Voil pourquoi nous modifions l'encodage par dfaut en ralisant un
appel la mthode setCharacterEncoding() de l'objet HttpServletResponse. Par ailleurs, c'est galement
pour cette raison que je vous ai fait modifier les encodages par dfaut lors de la configuration d'Eclipse !
Si vous regardez la documentation de cette mthode, vous dcouvrirez qu'il est galement possible de s'en
passer et d'initialiser l'encodage de la rponse directement via un appel la mthode setContentType(
"text/html; charset=UTF-8").
3. Nous rcuprons ensuite un objet PrintWriter qui va nous permettre d'envoyer du texte au client, via la mthode
getWriter() de l'objet HttpServletResponse. Vous devrez donc importer java.io.PrintWriter dans
votre servlet. Cet objet utilise l'encodage que nous avons dfini prcdemment, c'est--dire UTF-8.
4. Nous crivons alors du texte dans la rponse via la mthode println() de l'objet PrintWriter.
Enregistrez, testez et vous verrez enfin la page s'afficher dans votre navigateur : a y est, vous savez maintenant utiliser une
servlet et transmettre des donnes au client.

Rien que pour reproduire ce court et pauvre exemple, il nous a fallu 10 appels out.println() ! Lorsque nous
nous attaquerons des pages web un peu plus complexes que ce simple exemple, allons-nous devoir crire tout notre
code HTML l'intrieur de ces mthodes println() ?
Non, bien sr que non ! Vous imaginez un peu l'horreur si c'tait le cas ?! Si vous avez suivi le topo sur MVC, vous vous
souvenez d'ailleurs que la servlet n'est pas cense s'occuper de l'affichage, c'est la vue qui doit s'en charger ! Et c'est bien pour
a que je ne vous ai rien fait envoyer d'autre que cette simple page d'exemple HTML Toutefois, mme si nous ne procderons
plus jamais ainsi pour la cration de nos futures pages web, il tait trs important que nous dcouvrions comment cela se passe.
Pour le moment, voici ce que nous avons ralis :

Servlet seule
Note : dornavant et afin d'allger les schmas, je ne reprsenterai plus le serveur HTTP en amont du conteneur. Ici, le bloc
intitul "Serveur" correspond en ralit au conteneur de servlets.
Pour information, nous nous resservirons plus tard de cette technique d'envoi direct de donnes depuis une servlet,
lorsque nous manipulerons des fichiers.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

47/345

En rsum
Le client envoie des requtes au serveur grce aux mthodes du protocole HTTP, notamment GET, POST et HEAD.
Le conteneur web place chaque requte reue dans un objet HttpServletRequest, et place chaque rponse qu'il
initialise dans l'objet HttpServletResponse.
Le conteneur transmet chaque couple requte/rponse une servlet : c'est un objet Java assign une requte et capable
de gnrer une rponse en consquence.
La servlet est donc le point d'entre d'une application web, et se dclare dans son fichier de configuration web.xml.
Une servlet peut se charger de rpondre une requte en particulier, ou un groupe entier de requtes.
Pour pouvoir traiter une requte HTTP de type GET, une servlet doit implmenter la mthode doGet() ; pour rpondre
une requte de type POST, la mthode doPost() ; etc.
Une servlet n'est pas charge de l'affichage des donnes, elle ne doit donc pas s'occuper de la prsentation (HTML, CSS,
etc.).

La leon retenir en cette fin de chapitre est claire : le langage Java n'est pas du tout adapt la rdaction de pages web ! Notre
dernier exemple en est une excellente preuve, et il nous faut nous orienter vers quelque chose de plus efficace.
Il est maintenant grand temps de revenir au modle MVC : l'affichage de contenu HTML n'ayant rien faire dans le contrleur
(notre servlet), nous allons crer une vue et la mettre en relation avec notre servlet.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

48/345

Servlet avec vue


Le modle MVC nous conseille de placer tout ce qui touche l'affichage final (texte, mise en forme, etc.) dans une couche part :
la vue. Nous avons rapidement survol dans la premire partie de ce cours comment ceci se concrtisait en Java EE : la
technologie utilise pour raliser une vue est la page JSP. Nous allons dans ce chapitre dcouvrir comment fonctionne une telle
page, et apprendre en mettre une en place au sein de notre embryon d'application.

Introduction aux JSP


quoi ressemble une page JSP ?

C'est un document qui, premire vue, ressemble beaucoup une page HTML, mais qui en ralit en diffre par plusieurs
aspects :
l'extension d'une telle page devient .jsp et non plus .html ;
une telle page peut contenir des balises HTML, mais galement des balises JSP qui appellent de manire transparente du
code Java ;
contrairement une page HTML statique directement renvoye au client, une page JSP est excute ct serveur, et
gnre alors une page renvoye au client.
L'intrt est de rendre possible la cration de pages dynamiques : puisqu'il y a une tape de gnration sur le serveur, il devient
possible de faire varier l'affichage et dinteragir avec l'utilisateur, en fonction notamment de la requte et des donnes reues !
Bien que la syntaxe d'une page JSP soit trs proche de celle d'une page HTML, il est thoriquement possible de gnrer
n'importe quel type de format avec une page JSP : du HTML donc, mais tout aussi bien du CSS, du XML, du texte brut,
etc. Dans notre cas, dans la trs grande majorit des cas d'utilisation il s'agira de pages HTML destines l'affichage
des donnes de l'application sur le navigateur du client.

Ne vous fiez pas au titre de ce sous-chapitre, nous n'allons pas pour le moment nous intresser la technologie JSP en ellemme, ceci faisant l'objet des chapitres suivants. Nous allons nous limiter l'tude de ce qu'est une JSP, de la manire dont elle
est interprte par notre serveur et comment elle s'insre dans notre application.

Nature d'une JSP


Quoi ?
Les pages JSP sont une des technologies de la plate-forme Java EE les plus puissantes, simples utiliser et mettre en place.
Elles se prsentent sous la forme d'un simple fichier au format texte, contenant des balises respectant une syntaxe part entire.
Le langage JSP combine la fois les technologies HTML, XML, servlet et JavaBeans (nous reviendrons sur ce terme plus tard,
pour le moment retenez simplement que c'est un objet Java) en une seule solution permettant aux dveloppeurs de crer des vues
dynamiques.

Pourquoi ?
Pour commencer, mettons noir sur blanc les raisons de l'existence de cette technologie.
La technologie servlet est trop difficile d'accs et ne convient pas la gnration du code de prsentation : nous l'avons
soulign en fin de chapitre prcdent, crire une page web en langage Java est horriblement pnible. Il est ncessaire de
disposer d'une technologie qui joue le rle de simplification de l'API servlet : les pages JSP sont en quelque sorte une
abstraction "haut-niveau" de la technologie servlet.
Le modle MVC recommande une sparation nette entre le code de contrle et la prsentation. Il est thoriquement
envisageable d'utiliser certaines servlets pour effectuer le contrle, et d'autres pour effectuer l'affichage, mais nous
rejoignons alors le point prcdent : la servlet n'est pas adapte la prise en charge de l'affichage
Le modle MVC recommande une sparation nette entre le code mtier et la prsentation : dans le modle on doit
trouver le code Java responsable de la gnration des lments dynamiques, et dans la vue on doit simplement trouver
l'interface utilisateur ! Ceci afin notamment de permettre aux dveloppeurs et designers de travailler facilement sur la vue,
sans avoir y faire intervenir directement du code Java.

Comment ?

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

49/345

On peut rsumer la technologie JSP en une technologie offrant les capacits dynamiques des servlets tout en permettant une
approche naturelle pour la cration de contenu statiques. Ceci est rendu possible par :
un langage ddi : les pages JSP sont des documents au format texte, l'oppos des classes Java que sont les servlets,
qui dcrivent indirectement comment traiter une requte et construire une rponse. Elles contiennent des balises qui
combinent la fois simplicit et puissance, via une syntaxe simple, semblable au HTML et donc aisment comprhensible
par un humain ;
la simplicit d'accs aux objets Java : des balises du langage rendent l'utilisation directe d'objets au sein d'une page trs
aise ;
des mcanismes permettant l'extension du langage utilis au sein des pages JSP : il est possible de mettre en place des
balises qui n'existent pas dans le langage JSP, afin d'augmenter les fonctionnalits accessibles. Pas de panique, a parat
complexe a priori mais nous y reviendrons calmement dans la partie concernant la JSTL, et tout cela n'aura bientt plus
aucun secret pour vous !
Bon, assez gamberg ! Maintenant que nous avons une bonne ide de ce que sont les pages JSP, rentrons dans le concret en
tudiant leur vie au sein d'une application !

Mise en place d'une JSP


Cration de la vue
Le contexte tant pos, nous pouvons maintenant crer notre premire page JSP. Pour ce faire, depuis votre projet Eclipse faites
un clic droit sur le dossier WebContent de votre projet, puis choisissez New > JSP File, et dans la fentre qui apparat renseignez
le nom de votre page JSP :

Cration

d'une page JSP - tape 1

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

50/345

Cration d'une page JSP - tape 2

Une page JSP par dfaut est alors gnre par Eclipse : supprimez tout son contenu, et remplacez-le par notre modle d'exemple :
Code : HTML - test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
</body>
</html>

Rendez-vous ensuite dans la barre d'adresses de votre navigateur, et entrez l'URL correspondant la page que vous venez de
crer :
Code : URL
http://localhost:8080/test/test.jsp

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

51/345

Nous obtenons alors le rsultat suivant :

Qu'est-ce que c'est que cette horreur ? Que s'est-il pass ?

Le problme que vous voyez ici, c'est l'encodage ! Eh oui, dans le chapitre prcdent nous avions modifi l'encodage par dfaut
directement depuis notre servlet, et je ne vous avais alors pas expliqu pourquoi c'tait vraiment ncessaire de procder ainsi, je
vous avais uniquement expliqu l'intrt d'utiliser UTF-8. Cette fois dans notre JSP, nous n'avons rien modifi. Par consquent, la
rponse cre par notre page utilise la valeur par dfaut, c'est--dire l'encodage latin ISO-8859-1.

Si l'encodage latin est utilis par dfaut, alors pourquoi les lettres accentues ne s'affichent-elles pas correctement ? Ce
sont bien des caractres de notre alphabet !
Nous y voil, vous devez bien comprendre comment le principe d'encodage fonctionne. Il s'agit d'un processus en deux tapes,
avec d'une part la manire dont sont encods et grs les caractres sur le serveur, et d'autre part la manire dont les donnes
contenues dans la rponse envoye vont tre interprtes par le navigateur :
en ce qui concerne le serveur, c'est simple : si vous avez bien suivi mes conseils lors de la configuration d'Eclipse, vos
fichiers source sont tous encods en UTF-8 ;
en ce qui concerne le navigateur, celui-ci va uniquement se baser sur le contenu de l'en-tte Content-type de la rponse
HTTP afin d'interprter les donnes reues.
Or, comme je viens de vous le dire, votre page JSP a par dfaut envoy la rponse au client en spcifiant l'encodage latin dans
l'en-tte HTTP. Voil donc l'explication de l'affreux micmac observ : votre navigateur a essay d'afficher des caractres encods
en UTF-8 en utilisant l'encodage latin ISO-8859-1, et il se trouve que l'encodage des caractres accentus en ISO n'a rien voir
avec celui des caractres accentus en UTF ! D'o les symboles bizarrodes observs
Comment modifier l'en-tte HTTP depuis notre page JSP, afin de faire savoir au navigateur qu'il doit utiliser l'encodage
UTF-8 pour interprter les donnes reues ?
Pour cela, il va falloir ajouter une instruction en tte de votre page JSP. Je ne vais pas vous l'expliquer ds maintenant, je
reviendrai sur son fonctionnement dans un chapitre venir. Contentez-vous simplement d'ajouter cette ligne tout en haut du
code de votre page pour le moment :
Code : JSP
<%@ page pageEncoding="UTF-8" %>

Une fois la modification effectue et enregistre, actualisez la page dans votre navigateur et vous constaterez qu'il vous affiche
maintenant correctement le texte attendu.
Tout va bien donc, notre JSP est fonctionnelle !

Cycle de vie d'une JSP


En thorie
Tout tient en une seule phrase : quand une JSP est demande pour la premire fois, ou quand l'application web dmarre, le
conteneur de servlets va vrifier, traduire puis compiler la page JSP en une classe hritant de HttpServlet, et l'utiliser durant
l'existence de l'application.
Cela signifie-t-il qu'une JSP est littralement transforme en servlet par le serveur ?

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

52/345

C'est exactement ce qui se passe. Lors de la demande d'une JSP, le moteur de servlets va excuter la classe JSP auparavant
traduite et compile et envoyer la sortie gnre (typiquement, une page HTML/CSS/JS) depuis le serveur vers le client travers
le rseau, sortie qui sera alors affiche dans son navigateur !
Pourquoi ?

Je vous l'ai dj dit, la technologie JSP consiste en une vritable abstraction de la technologie servlet : cela signifie concrtement
que les JSP permettent au dveloppeur de faire du Java sans avoir crire de code Java ! Bien que cela paraisse magique,
rassurez-vous il n'y a pas de miracles : vous pouvez voir le code JSP crit par le dveloppeur comme une succession de
raccourcis en tous genres qui, dans les coulisses, appellent en ralit des portions de code Java toutes prtes !
Que se passe-t-il si le contenu d'une page JSP est modifi ? Que devient la servlet auto-gnre correspondante ?

C'est une trs bonne question !


une JSP :

Voici ce qui se passe au sein du conteneur de servlets lorsqu'une requte HTTP est destine

le conteneur vrifie si la JSP a dj t traduite et compile en une servlet :


si non, il vrifie la syntaxe de la page, la traduit en une servlet (du code Java) et la compile en une classe
excutable prte l'emploi ;
si oui, il vrifie que l'ge de la JSP et de la servlet sont identiques :
si non, cela signifie que la JSP est plus rcente que la servlet et donc qu'il y a eu modification, le conteneur
effectue alors nouveau les tches de vrification, traduction et compilation ;
il charge ensuite la classe gnre, en cre une instance et l'excute pour traiter la requte.
J'ai reprsent cette suite de dcisions dans le schma suivant, afin de vous faciliter la comprhension du cycle :

Cycle de vie d'une JSP

De tout cela, il faut retenir que le processus initial de vrification/traduction/compilation n'est pas effectu chaque
appel ! La servlet gnre et compile tant sauvegarde, les appels suivants la JSP sont beaucoup plus rapides : le
conteneur se contente d'excuter directement l'instance de la servlet stocke en mmoire.

En pratique
Avant de passer la suite, revenons sur cette histoire de traduction en servlet. Je vous ai dit que le conteneur de servlets, en
l'occurrence ici Tomcat, gnrait une servlet partir de votre JSP. Eh bien sachez que vous pouvez trouver le code source ainsi

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

53/345

gnr dans le rpertoire de travail du serveur : sous Tomcat, il s'agit du rpertoire /work.
Qu'en est-il de notre premire JSP ? Existe-t-il une servlet auto-gnre depuis nos quelques lignes de texte ?

La rponse est oui bien entendu, partir du moment o vous avez appel au moins une fois cette JSP depuis votre navigateur !
Cette servlet est bien prsente dans le rpertoire de travail de Tomcat, seulement comme nous grons notre serveur directement
depuis Eclipse, par dfaut ce dernier va en quelque sorte prendre la main sur Tomcat, et mettre tous les fichiers dans un
rpertoire lui ! Le fourbe...
Bref, voil o se trouve ma servlet pour cet exemple :
Code : URI

C:\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\
C:\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\

Elle doit se situer sensiblement au mme endroit chez vous, un ou deux noms de dossier prs selon la configuration que vous
avez mise en place et bien entendu selon le systme d'exploitation que vous utilisez. Vous remarquerez que Tomcat suffixe les
servlets qu'il auto-gnre partir de pages JSP avec "_jsp".
Je vous conseille alors d'diter le fichier .java et de consulter les sources gnres, c'est un exercice trs formateur pour
vous que de tenter de comprendre ce qui y est fait : n'oubliez pas, la Javadoc est votre amie pour comprendre les
mthodes qui vous sont encore inconnues. Ne prenez surtout pas peur devant ce qui s'apparente un joyeux bordel, et
passez faire un tour sur le forum Java si vous avez des questions prcises sur ce qui s'y trouve !

Sans surprise, au milieu du code gnr par Tomcat nous retrouvons bien des instructions trs semblables celles que nous
avions d crire dans notre servlet dans le chapitre prcdent, et qui correspondent cette fois ce que nous avons crit dans
notre JSP :
Code : Java - Extrait de la servlet test_jsp.java auto-gnre par Tomcat depuis notre page test.jsp
out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <meta charset=\"utf-8\" />\r\n");
out.write(" <title>Test</title>\r\n");
out.write(" </head>\r\n");
out.write(" <body>\r\n");
out.write(" <p>Ceci est une page gnre depuis une JSP.</p>\r\n");
out.write(" </body>\r\n");
out.write("</html>");

Retenez bien que c'est cette classe Java qui est compile et excute lorsque votre JSP est appele. Ce court apart se
termine ici, dornavant nous ne nous proccuperons plus de ce qui se trame dans les coulisses de notre serveur : nous
aurons bien assez de travail avec nos JSP et le reste !

Mise en relation avec notre servlet


Garder le contrle
Dans l'exemple que nous venons de raliser, nous nous sommes contents d'afficher du texte statique, et avons visualis le
rsultat en appelant directement la page JSP depuis son URL. C'tait pratique pour le coup, mais dans une application Java EE il
ne faut jamais procder ainsi ! Pourquoi ? La rponse tient en trois lettres : MVC. Ce modle de conception nous recommande en
effet la mise en place d'un contrleur, et nous allons donc tcher de toujours associer une servlet une vue.
Mais je viens de vous montrer qu'une JSP tait de toute faon traduite en servlet Quel est l'intrt de mettre en place
une autre servlet ?
Une JSP est en effet automatiquement traduite en servlet, mais attention ne pas confondre : les contrleurs du MVC sont bien

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

54/345

reprsents en Java EE par des servlets, mais cela ne signifie pas pour autant que toute servlet joue le rle d'un contrleur dans
une application Java EE. En l'occurrence, les servlets rsultant de la traduction des JSP dans une application n'ont pour rle que
de permettre la manipulation des requtes et rponses HTTP. En aucun cas elles n'interviennent dans la couche de contrle, elles
agissent de manire transparente et font bien partie de la vue : ce sont simplement des traductions en un langage que comprend
le serveur (le Java !) des vues prsentes dans votre application (de simples fichiers textes contenant de la syntaxe JSP).
Dornavant, nous allons donc systmatiquement crer une servlet lorsque nous crerons une page JSP. a peut vous
sembler pnible au dbut, mais c'est une bonne pratique prendre ds maintenant : vous gardez ainsi le contrle, en
vous assurant qu'une vue ne sera jamais appele par le client sans tre passe travers une servlet. Souvenez-vous : la
servlet est le point d'entre de votre application !

Nous allons mme pousser le vice plus loin, et dplacer notre page JSP dans le rpertoire /WEB-INF. Si vous vous souvenez de
ce que je vous ai dit dans le chapitre sur la configuration de Tomcat, vous savez que ce dossier a une particularit qui nous
intresse : il cache automatiquement les ressources qu'il contient. En d'autres termes, une page prsente sous ce rpertoire n'est
plus accessible directement par une URL ct client ! Il devient alors ncessaire de passer par une servlet ct serveur pour
donner l'accs cette page Plus d'oubli possible !
Faites le test. Essayez depuis une URL de joindre votre page JSP aprs l'avoir dplace sous /WEB-INF : vous n'y arriverez pas !
Nous devons donc associer notre servlet notre vue. Cette opration est ralise depuis la servlet, ce qui est logique puisque
c'est elle qui dcide d'appeler la vue.
Reprenons notre servlet, vidons la mthode doGet() du contenu que nous avons depuis fait migrer dans la JSP, et regardons
le code mettre en place pour effectuer l'association :
Code : Java - com.sdzee.servlets.Test
...
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException {
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}

Analysons ce qui se passe :


depuis notre instance de servlet (this), nous appelons la mthode getServletContext(). Celle-ci nous retourne
alors un objet ServletContext, qui fait rfrence au contexte commun toute l'application : celui-ci contient un
ensemble de mthodes qui permettent une servlet de communiquer avec le conteneur de servlet ;
celle qui nous intresse ici est la mthode permettant de manipuler une ressource, getRequestDispatcher(), que
nous appliquons notre page JSP. Elle retourne un objet RequestDispatcher, qui agit ici comme une enveloppe
autour de notre page JSP. Vous pouvez considrer cet objet comme la pierre angulaire de votre servlet : c'est grce lui
que notre servlet est capable de faire suivre nos objets requte et rponse une vue. Il est impratif d'y prciser le
chemin complet vers la JSP, en commenant obligatoirement par un / (voir l'avertissement et la prcision ci-dessous) ;
nous utilisons enfin ce dispatcher pour rexpdier la paire requte/rponse HTTP vers notre page JSP via sa mthode
forward().
De cette manire notre page JSP devient accessible au travers de la servlet ; d'ailleurs, notre servlet ne faisant actuellement rien
d'autre, son seul rle est de transfrer le couple requte reue et rponse vers la JSP finale.
Ne soyez pas leurrs : comme je vous l'ai dj dit lorsque je vous ai prsent la structure d'un projet, le dossier WebContent
existe uniquement dans Eclipse ! Je vous ai dj expliqu qu'il correspondait en ralit la racine de l'application, et c'est donc
pour a qu'il faut bien crire /WEB-INF/test.jsp en argument de la mthode getRequestDispatcher(), et non pas
/WebContent/WEB-INF/test.jsp !
retenir donc : nulle part dans votre code ne doit tre mentionn le rpertoire WebContent ! C'est une reprsentation
de la racine de l'application, propre Eclipse uniquement.
Si vous parcourez la documentation de l'objet HttpServletRequest, vous remarquerez qu'il contient lui aussi une
mthode getRequestDispatcher() ! Toutefois, cette dernire prsente une diffrence notable : elle peut prendre
en argument un chemin relatif, alors que sa grande sur n'accepte qu'un chemin complet. Je vous conseille, afin d'viter

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

55/345

de vous emmler les crayons, de passer par la mthode que je vous prsente ci-dessus. Quand vous serez plus l'aise
avec ces histoires de chemins relatifs et absolus, vous pourrez alors dcider d'utiliser l'une ou l'autre de ces mthodes.

Faites nouveau le test, en essayant cette fois d'appeler l'URL correspondant votre servlet (souvenez-vous, c'est celle que
nous avons mise en place dans le fichier web.xml, savoir /test/toto) : tout fonctionne, notre requte est bien achemine jusqu'
notre JSP, et en retour notre navigateur nous affiche bien le contenu de la page !
Voici ce que nous venons de raliser :

Servlet + JSP

En rsum
Une page JSP ressemble en apparence une page HTML, mais en ralit elle est bien plus proche d'une servlet : elle
contient des balises derrire lesquelles se cache du code Java.
Une page JSP est excute sur le serveur, et la page finale gnre et envoye au client est une simple page HTML : le
client ne voit pas le code de la JSP.
Idalement dans le modle MVC, une page JSP est accessible l'utilisateur travers une servlet, et non pas directement.
Le rpertoire /WEB-INF cache les fichiers qu'il contient l'extrieur de l'application.
La mthode forward() de l'objet RequestDispatcher permet depuis une servlet de rediriger la paire
requte/rponse HTTP vers une autre servlet ou vers une page JSP.
Notre projet commence prendre forme. Dans le chapitre suivant, nous allons apprendre faire circuler des donnes entre les
diffrents acteurs de notre application !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

56/345

Transmission de donnes
Nous nous sommes jusqu' prsent contents d'afficher une page web au contenu fig, comme nous l'avions fait via une simple
page HTML crite en dur en tout dbut de cours. Seulement cette fois, notre contenu est prsent dans une page JSP laquelle
nous avons associ une servlet. Nous disposons ainsi de tout ce qui est ncessaire pour ajouter du dynamisme notre projet. Il
est donc grand temps d'apprendre faire communiquer entre eux les diffrents lments constituant notre application !

Donnes issues du serveur : les attributs


Transmettre des variables de la servlet la JSP
Jusqu' prsent nous n'avons pas fait grand-chose avec notre requte HTTP, autrement dit avec notre objet
HttpServletRequest : nous nous sommes contents de le transmettre la JSP. Pourtant, vous avez d vous en apercevoir
lorsque vous avez parcouru sa documentation, ce dernier contient normment de mthodes !
Puisque notre requte HTTP passe maintenant au travers de la servlet avant d'tre transmise la vue, profitons-en pour y
apporter quelques modifications ! Utilisons donc notre servlet pour mettre en place un semblant de dynamisme dans notre
application : crons une chane de caractres depuis notre servlet, et transmettons-la notre vue pour affichage.
Code : Java - Transmission d'une variable
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
String message = "Transmission de variables : OK !";
request.setAttribute( "test", message );
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}

Comme vous pouvez le constater, le principe est trs simple et tient en une ligne (la ligne 3). Il suffit d'appeler la mthode
setAttribute() de l'objet requte pour y enregistrer un attribut ! Cette mthode prend en paramtre le nom que l'on
souhaite donner l'attribut suivi de l'objet lui-mme.
Ici, l'attribut que j'ai cr est une simple chane de caractres - un objet de type String - que j'ai choisi de nommer test lors de son
enregistrement dans la requte.
Ne confondez pas le nom que vous donnez votre objet au sein du code et le nom que vous donnez l'attribut au sein
de la requte.
Ici mon objet se nomme message, mais j'ai par la suite nomm test l'attribut qui contient cet objet dans la requte. Ct
vue, c'est par ce nom d'attribut que vous pourrez accder votre objet !

C'est tout ce qu'il est ncessaire de faire ct servlet. Regardons maintenant comment rcuprer et afficher l'objet ct vue :
Code : JSP - /WEB-INF/test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
<%
String attribut = (String) request.getAttribute("test");
out.println( attribut );
%>
</p>
</body>
</html>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

57/345

Ne paniquez pas, vous ne connaissez pas cette notation (lignes 10 13) et c'est bien normal puisque je ne vous l'ai pas encore
prsente
Voici donc une premire information concernant la technologie JSP : elle permet d'inclure du code Java dans une page en
entourant ce code des balises <% et %> . Ce sont des marqueurs qui dlimitent les portions contenant du code Java du reste
de la page, contenant ici simplement des balises HTML et du texte. l'intrieur, tout se passe comme si on crivait du code
directement dans une servlet : on fait appel la mthode println() de l'objet PrintWriter out pour afficher du contenu.
La seule diffrence rside dans le fait que depuis une JSP, il n'est plus ncessaire de spcifier le content-type de la rponse
HTTP ni d'y rcuprer l'objet PrintWriter, comme nous l'avions fait deux chapitres auparavant depuis notre servlet. Ceci est
rendu possible grce l'existence d'objets implicites, sur lesquels nous allons revenir trs bientt !
En ce qui concerne la rcupration de l'attribut depuis la requte, je pense que vous tes assez grands pour faire vous-mmes
l'analogie avec sa cration : tout comme il suffit d'appeler setAttribute() pour crer un attribut dans une requte depuis
une servlet, il suffit d'appeler la mthode getAttribute() pour en rcuprer un depuis une JSP ! Ici, je rcupre bien mon
objet nomm test .
Nous avons ici transmis un simple objet String, mais il est possible de transmettre n'importe quel objet, comme un entier
ou une liste par exemple.
Remarquez ce sujet la ncessit de convertir (cast) l'objet rcupr dans la JSP au type souhait, la mthode
getAttribute() renvoyant un objet global de type Object.

Alors c'est a une JSP ? Une autre page dans laquelle on remet une couche de Java ?

Non, bien sr que non ! crire du Java dans une JSP n'a aucun sens : l'intrt mme de ces pages est de s'affranchir du langage
Java ! ce compte-l, autant n'utiliser qu'une servlet et ne pas mettre en place de JSP
Cependant comme vous pouvez le voir, cela fonctionne trs bien ainsi : a confirme ce que je vous disais dans la premire partie
de ce cours. En Java EE, rien n'impose au dveloppeur de bien travailler, et il est possible de coder n'importe comment sans que
cela n'impacte le fonctionnement de l'application. Voil donc un premier exemple destin vous faire comprendre ds maintenant
que mettre du code Java dans une page JSP, c'est mal.
Pour ce qui est de notre exemple, ne vous y mprenez pas : si je vous fais utiliser du code Java ici, c'est uniquement parce que
nous n'avons pas encore dcouvert le langage JSP. D'ailleurs, autant vous prvenir tout de suite : partir du chapitre suivant,
nous allons tout mettre en uvre pour ne plus jamais crire de Java directement dans une JSP !

Donnes issues du client : les paramtres


Qu'est-ce qu'un paramtre de requte ?

Si vous tes assidus, vous devez vous souvenir de la description que je vous ai faite de la mthode GET du protocole HTTP :
elle permet au client de transmettre des donnes au serveur en les incluant directement dans l'URL, dans ce qui s'appelle les
paramtres ou query strings en anglais. Eh bien c'est cela que nous allons apprendre manipuler ici : nous allons rendre notre
projet interactif, en autorisant le client transmettre des informations au serveur.

La forme de l'URL
Les paramtres sont transmis au serveur directement via l'URL. Voici des exemples des diffrentes formes qu'une URL peut
prendre :
Code : HTML
<!-- URL sans paramtres -->
/page.jsp
<!-- URL avec un paramtre nomm 'cat' et ayant pour valeur 'java'
-->
/page.jsp?cat=java
<!-- URL avec deux paramtres nomms 'lang' et 'admin', et ayant
pour valeur respectivement 'fr' et 'true' -->
/page.jsp?lang=fr&admin=true

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

58/345

Il y a peu de choses retenir :


le premier paramtre est spar du reste de l'URL par le caractre ? ;
les paramtres sont spars entre eux par le caractre & ;
une valeur est attribue chaque paramtre via l'oprateur = .
Il n'existe pas d'autre moyen de dclarer des paramtres dans une requte GET, ceux-ci doivent imprativement apparatre en clair
dans l'URL demande. ce propos, souvenez-vous de ce dont je vous avais averti lors de la prsentation de cette mthode GET
: la taille d'une URL tant limite, la taille des donnes qu'il est ainsi possible d'envoyer est limite galement !
vrai dire, la norme ne spcifie pas de limite proprement parler, mais les navigateurs imposent d'eux-mmes une limite : par
exemple, la longueur maximale d'une URL est de 2 083 caractres dans Internet Explorer 8. Au-del de a, autrement dit si votre
URL est si longue qu'elle contient plus de 2 000 caractres, ce navigateur ne saura pas grer cette URL ! Vous disposez donc
d'une certaine marge de manuvre ; pour des chanes de caractres courtes comme dans notre exemple cette limite ne vous gne
absolument pas. Mais d'une manire gnrale et mme si les navigateurs rcents savent grer des URL bien plus longues,
lorsque vous avez beaucoup de contenu transmettre ou que vous ne connaissez pas l'avance la taille des donnes qui vont
tre envoyes par le client, prfrez la mthode POST.
J'en profite enfin pour vous reparler des recommandations d'usage HTTP : lorsque vous envoyez des donnes au serveur et
qu'elles vont avoir un impact sur la ressource demande, il est, l encore, prfrable de passer par la mthode POST du
protocole, plutt que par la mthode GET.
Que signifie "avoir un impact sur la ressource" ?

Eh bien cela veut dire "entraner une modification sur la ressource", et en fin de compte tout dpend de ce que vous faites de ces
donnes dans votre code. Prenons un exemple concret pour bien visualiser. Imaginons une application proposant une page
compte.jsp qui autoriserait des actions diverses sur le compte en banque de l'utilisateur. Ces actions ne se drouleraient bien
videmment pas comme cela dans une vraie application bancaire, mais c'est simplement pour que l'exemple soit parlant.
Si le code attend un paramtre prcisant le mois pour lequel l'utilisateur souhaite afficher la liste des entres et sorties
d'argent de son compte, par exemple compte.jsp?mois=avril, alors cela n'aura pas d'impact sur la ressource. En effet, nous
pouvons bien renvoyer 10 fois la requte au serveur, notre code ne fera que r-afficher les mmes donnes l'utilisateur
sans les modifier.
Si par contre le code attend des paramtres prcisant des informations ncessaires en vue de raliser un transfert
d'argent, par exemple compte.jsp?montant=100&destinataire=01K87B612, alors cela aura clairement un impact sur la
ressource : en effet, si nous renvoyons 10 fois une telle requte, notre code va effectuer 10 fois le transfert !
Ainsi, si nous suivons les recommandations d'usage, nous pouvons utiliser une requte GET pour le premier cas, et devons
utiliser une requte POST pour le second. Nous reviendrons sur les avantages de la mthode POST lorsque nous aborderons les
formulaires, dans une des parties suivantes de ce cours.
N'importe quel client peut-il envoyer des paramtres une application ?

Oui, effectivement. Par exemple, lorsque vous naviguez sur le site du zro, rien ne vous empche de rajouter des paramtres tout
droit issus de votre imagination lors de l'appel de la page d'accueil du site : par exemple, www.siteduzero.com/?mascotte=zozor.
Le site n'en fera rien, car la page n'en tient pas compte, mais le serveur les recevra bien. C'est en partie pour cela, mais nous
aurons tout le loisir d'y revenir par la suite, qu'il est impratif de bien vrifier le contenu des paramtres envoys au serveur
avant de les utiliser.

Rcupration des paramtres par le serveur


Modifions notre exemple afin d'y inclure la gestion d'un paramtre nomm auteur :
Code : Java - Servlet
public void doGet( HttpServletRequest request, HttpServletResponse

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

59/345

response ) throws ServletException, IOException{


String paramAuteur = request.getParameter( "auteur" );
String message = "Transmission de variables : OK ! " + paramAuteur;
request.setAttribute( "test", message );
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}

La seule ligne ncessaire pour cela est la ligne 2 : il suffit de faire appel la mthode getParameter() de l'objet requte, en
lui passant comme argument le nom du paramtre que l'on souhaite rcuprer. La mthode retournant directement le contenu du
paramtre, je l'ai ici insr dans une String que j'ai nomme paramAuteur.
Pour vous montrer que notre servlet rcupre bien les donnes envoyes par le client, j'ai ajout le contenu de cette String au
message que je transmets ensuite la JSP pour affichage. Si vous appelez nouveau votre servlet depuis votre navigateur, rien
ne va changer. Mais si cette fois vous l'appelez en ajoutant un paramtre nomm auteur l'URL, par exemple :
Code : URL
http://localhost:8080/test/toto?auteur=Coyote

Alors vous observerez que le message affich dans le navigateur contient bien la valeur du paramtre prcis dans l'URL :
Code : HTML - Contenu de la page finale
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
Transmission de variables : OK ! Coyote
</p>
</body>
</html>

Vous avez donc ici la preuve que votre paramtre bien t rcupr par la servlet. Comprenez galement que lorsque vous
envoyez un paramtre, il reste prsent dans la requte HTTP durant tout son cheminement. Par exemple, nous pouvons trs bien
y accder depuis notre page JSP sans passer par la servlet, de la manire suivante :
Code : JSP - /WEB-INF/test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
<%
String attribut = (String) request.getAttribute("test");
out.println( attribut );

</p>

String parametre = request.getParameter( "auteur" );


out.println( parametre );
%>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

60/345

</body>
</html>

En procdant ainsi, lorsque nous appelons l'URL en y prcisant un paramtre nomm auteur, nous obtenons bien le rsultat
escompt : notre JSP affiche une seconde fois "Coyote", cette fois en rcuprant directement la valeur du paramtre depuis la
requte HTTP.
Si vous ne prcisez pas de paramtre auteur dans l'URL, alors la mthode getParameter() renverra null en lieu et place du
contenu attendu.
Note : il est trs imprudent de procder l'utilisation ou l'affichage d'un paramtre transmis par le client sans en
contrler et ventuellement scuriser son contenu auparavant. Ici il s'agit d'un simple exemple, nous ne nous
proccupons pas encore des problmes potentiels. Mais c'est une bonne pratique de toujours contrler ce qu'on
affiche au client. Nous y reviendrons plusieurs reprises dans la suite du cours dans des cas plus concrets, et vous
comprendrez alors mieux de quoi il retourne.

Nous allons nous arrter l pour le moment. L'utilisation la plus courante des paramtres dans une application web est la
rcupration de donnes envoyes par le client via des formulaires, mais nous ne sommes pas encore prts pour cela. Avant de
passer la suite, une dernire petite prcision s'impose.
Quelle est la diffrence entre ces paramtres et les attributs que nous avons dcouverts en dbut de chapitre ?

Il ne faut pas faire de confusion ici :


les paramtres de requte sont un concept appartenant au protocole HTTP. Ils sont envoys par le client au serveur
directement au sein de l'URL, et donc sous forme de chanes de caractres. Il n'est pas possible de forger des paramtres
dans l'objet HttpServletRequest, il est uniquement possible d'y accder en lecture. Ce concept n'tant absolument
pas spcifique la plate-forme Java EE mais commun toutes les technologies web, il ne peut pas tre "objectifi". C'est
la raison pour laquelle la mthode getParameter() retourne quoi qu'il arrive un objet de type String, et il n'est pas
possible d'ajouter une quelconque logique supplmentaire un tel objet.
les attributs de requte sont un concept appartenant au conteneur Java, et sont donc crs ct serveur : c'est au sein
du code de l'application que l'on procde leur initialisation, et qu'on les insre dans la version "objectifie" de la
requte, savoir l'objet HttpServletRequest. Contrairement aux paramtres, ils ne sont pas prsents directement
dans la requte HTTP mais uniquement dans l'objet Java qui l'enveloppe, et peuvent contenir n'importe quel type de
donnes. Ils sont utiliss pour permettre une servlet de communiquer avec d'autres servlets ou pages JSP.
En rsum, les paramtres de requte sont propres au protocole HTTP et font partie intgrante de l'URL d'une requte,
alors que les attributs sont des objets purement Java crs et grs par le biais du conteneur.

En rsum
Un attribut de requte est en ralit un objet stock dans l'objet HttpServletRequest, et peut contenir n'importe
quel type de donnes.
Les attributs de requte sont utiliss pour permettre une servlet de transmettre des donnes d'autres servlets ou des
pages JSP.
Un paramtre de requte est une chane de caractres place par le client la fin de l'URL de la requte HTTP.
Les paramtres de requte sont utiliss pour permettre un client de transmettre des donnes au serveur.

Prochaine tape : l'apprentissage de la technologie JSP. Les prochains chapitres y sont entirement consacrs, avec au
programme la dcouverte de la syntaxe, des balises, etc. Bref, tout le ncessaire pour crer des vues dynamiques sans avoir
crire de Java (ou presque) !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

61/345

Le JavaBean
Ce court chapitre a pour unique objectif de vous prsenter un type d'objet un peu particulier : le JavaBean. Souvent raccourci en
"bean", un JavaBean dsigne tout simplement un composant rutilisable. Il est construit selon certains standards, dfinis dans
les spcifications de la plate-forme et du langage Java eux-mmes : un bean n'a donc rien de spcifique au Java EE.
Autrement dit, aucun concept nouveau n'intervient dans la cration d'un bean : si vous connaissez les bases du langage Java,
vous tes dj capables de comprendre et de crer un bean sans problme particulier. Son utilisation ne requiert aucune
bibliothque ; de mme, il nexiste pas de superclasse dfinissant ce qu'est un bean, ni d'API.
Ainsi, tout objet conforme ces quelques rgles peut tre appel un bean. Dcouvrons pour commencer quels sont les objectifs
d'un bean, puis quels sont ces standards d'criture dont je viens de vous parler. Enfin, dcouvrons comment l'utiliser dans un
projet !

Objectifs
Pourquoi le JavaBean ?
Avant d'tudier sa structure, intressons-nous au pourquoi d'un bean. En ralit, un bean est un simple objet Java qui suit
certaines contraintes, et reprsente gnralement des donnes du monde rel.
Voici un rcapitulatif des principaux concepts mis en jeu. Je vous donne ici des dfinitions plutt abstraites, mais il faut bien en
passer par l.
Les proprits : un bean est conu pour tre paramtrable. On appelle "proprits" les champs non publics prsents
dans un bean. Qu'elles soient de type primitif ou objets, les proprits permettent de paramtrer le bean, en y stockant
des donnes.
La srialisation : un bean est conu pour pouvoir tre persistant. La srialisation est un processus qui permet de
sauvegarder l'tat d'un bean, et donne ainsi la possibilit de le restaurer par la suite. Ce mcanisme permet une
persistance des donnes, voire de l'application elle-mme.
La rutilisation : un bean est un composant conu pour tre rutilisable. Ne contenant que des donnes ou du code
mtier, un tel composant n'a en effet pas de lien direct avec la couche de prsentation, et peut galement tre distant de la
couche d'accs aux donnes (nous verrons cela avec le modle de conception DAO). C'est cette indpendance qui lui
donne ce caractre rutilisable.
L'introspection : un bean est conu pour tre paramtrable de manire dynamique. L'introspection est un processus qui
permet de connatre le contenu d'un composant (attributs, mthodes et vnements) de manire dynamique, sans
disposer de son code source. C'est ce processus, coupl certaines rgles de normalisation, qui rend possible une
dcouverte et un paramtrage dynamique du bean !
Dans le cas d'une application Java EE, oublions les concepts lis aux vnements, ceux-ci ne nous concernent pas.
Tout le reste est valable, et permet de construire des applications de manire efficace : la simplicit inhrente la
conception d'un bean rend la construction d'une application base sur des beans relativement aise, et le caractre
rutilisable d'un bean permet de minimiser les duplications de logiques dans une application.

Un JavaBean n'est pas un EJB


Certains d'entre vous ont peut-tre dj entendu parler d'un composant Java EE nomm EJB , signifiant Enterprise JavaBean.
Si ce nom ressemble trs fortement aux beans que nous tudions ici, ne tombez pas dans le pige et ne confondez pas les deux :
les EJB suivent un concept compltement diffrent. Je ne m'attarde pas sur le sujet mais ne vous inquitez pas, nous reviendrons
sur ce que sont ces fameux EJB en temps voulu.

Structure
Un bean :
doit tre une classe publique ;
doit avoir au moins un constructeur par dfaut, public et sans paramtres. Java l'ajoutera de lui-mme si aucun
constructeur n'est explicit ;
peut implmenter l'interface Serializable, il devient ainsi persistant et son tat peut tre sauvegard ;
ne doit pas avoir de champs publics ;
peut dfinir des proprits (des champs non publics), qui doivent tre accessibles via des mthodes publiques getter et
setter, suivant des rgles de nommage.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

62/345

Voici un exemple illustrant cette structure :


Code : Java - Exemple
/* Cet objet est une classe publique */
public class MonBean{
/* Cet objet ne possde aucun constructeur, Java lui assigne donc
un constructeur par dfaut public et sans paramtre. */
/* Les champs de l'objet ne sont pas publics (ce sont donc des
proprits) */
private String proprieteNumero1;
private int proprieteNumero2;
/* Les proprits de l'objet sont accessibles via des getters et
setters publics */
public String getProprieteNumero1() {
return this.proprieteNumero1;
}
public int getProprieteNumero2() {
return this.proprieteNumero2;
}
public void setProprieteNumero1( String proprieteNumero1 ) {
this.proprieteNumero1 = proprieteNumero1;
}
public void setProprieteNumero2( int proprieteNumero2 ) {
this.proprieteNumero2 = proprieteNumero2;
}
/* Cet objet suit donc bien la structure nonce : c'est un bean !
*/
}

Ce paragraphe se termine dj : comme je vous le disais en introduction, un bean ne fait rien intervenir de nouveau. Voil donc
tout ce qui dfinit un bean, c'est tout ce que vous devez savoir et retenir. En outre, nous n'allons pas pour le moment utiliser la
srialisation dans nos projets : si vous n'tes pas familiers avec le concept, ne vous arrachez pas les cheveux et mettez cela de
ct !
Plutt que de paraphraser, passons directement la partie qui nous intressera dans ce cours, savoir la mise en place de beans
dans notre application web !

Mise en place
J'imagine que certains d'entre vous, ceux qui n'ont que trs peu, voire jamais, dvelopp d'applications Java ou Java EE, peinent
comprendre exactement quel niveau et comment nous allons faire intervenir un objet Java dans notre projet web. Voyons
donc tout d'abord comment mettre en place un bean dans un projet web sous Eclipse, afin de le rendre utilisable depuis le reste
de notre application.

Cration de notre bean d'exemple


Dfinissons pour commencer un bean simple qui servira de base nos exemples :
Code : Java - com.sdzee.beans.Coyote
package com.sdzee.beans;
public class Coyote {
private String nom;

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

63/345

private String prenom;


private boolean genius;
public String getNom() {
return this.nom;
}
public String getPrenom() {
return this.prenom;
}
public boolean isGenius() {
return this.genius;
}
public void setNom( String nom ) {
this.nom = nom;
}
public void setPrenom( String prenom ) {
this.prenom = prenom;
}
public void setGenius( boolean genius ) {
/* Wile E. Coyote fait toujours preuve d'une ingniosit hors du
commun, c'est indniable ! Bip bip... */
this.genius = true;
}
}

Rien de compliqu ici, c'est du pur Java sans aucune fioriture !


J'ai ici cr un bean contenant seulement trois proprits, savoir les trois champs non publics nom, prenom et genius. Inutile de
s'attarder sur la nature des types utiliss ici, ceci n'est qu'un exemple totalement bidon qui ne sert rien d'autre qu' vous
permettre de bien visualiser le concept.
Maintenant, passons aux informations utiles. Vous pouvez remarquer que cet objet respecte bien les rgles qui rgissent
l'existence d'un bean :
un couple de getter/setter publics pour chaque champ priv ;
aucun champ public ;
un constructeur public sans paramtres (aucun constructeur tout court en l'occurrence).
Cet objet doit tre plac dans le rpertoire des sources "src" de notre projet web. J'ai ici, dans notre exemple, prcis le package
com.sdzee.beans.
Jetez un il aux copies d'cran ci-dessous pour visualiser la dmarche sous Eclipse :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

64/345

Mise en place d'un

bean sous Eclipse - tape 1

Mise en place d'un bean sous

Eclipse - tape 2

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

65/345

Vous savez dornavant comment mettre en place des beans dans vos projets web. Cela dit, il reste encore une tape cruciale afin
de rendre ces objets accessibles notre application ! En effet, actuellement vous avez certes plac vos fichiers sources au bon
endroit, mais vous savez trs bien que votre application ne peut pas se baser sur ces fichiers sources, elle ne comprend que les
classes compiles !

Configuration du projet sous Eclipse


Afin de rendre vos objets accessibles votre application, il faut que les classes compiles partir de vos fichiers sources soient
places dans un dossier "classes", lui-mme plac sous le rpertoire /WEB-INF. Souvenez-vous, nous en avions dj parl dans
le troisime chapitre de la premire partie.
Par dfaut Eclipse, toujours aussi fourbe, ne procde pas ainsi et envoie automatiquement vos classes compiles dans un
dossier nomm "build".
Afin de changer ce comportement, il va falloir modifier le Build Path de notre application.
Pour ce faire, faites un clic droit sur le dossier du projet, slectionnez "Build Path" puis "Configure Build Path..." :

Configuration du build

path d'un projet sous Eclipse - tape 1


Slectionnez alors l'onglet "source", puis regardez en bas le champ "Default output folder" :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

66/345

Configuration du build path d'un projet sous Eclipse - tape 2


C'est ici qu'il faut prciser le chemin vers WEB-INF/classes afin que nos classes, lors de leur compilation, soient
automatiquement dposes dans le dossier pris en compte par notre serveur d'applications. Le rpertoire souhait n'existant pas
par dfaut, Eclipse va le crer automatiquement pour nous.
Validez, et c'est termin ! Votre application est prte, vos classes compiles seront bien dposes dans le rpertoire de
l'application, et vous allez ainsi pouvoir manipuler vos beans directement depuis vos servlets et vos JSP !
Par dfaut, Eclipse ne vous montre pas ce rpertoire "classes" dans l'arborescence du projet, simplement parce que a
n'intresse pas le dveloppeur de visualiser les fichiers .class. Tout ce dont il a besoin depuis son IDE est de pouvoir
travailler sur les fichiers sources .java ! Si toutefois vous souhaitez vrifier que le dossier est bien prsent dans votre
projet, il vous suffit d'ouvrir le volet "Navigator" :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

67/345

Visualisation du rpertoire contenant les classes sous Eclipse

Mise en service dans notre application


Notre objet tant bien insr dans notre application, nous pouvons commencer le manipuler. Reprenons notre servlet d'exemple
prcdente :
Code : Java - com.sdzee.servlets.Test
...
import com.sdzee.beans.Coyote;
...
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Cration et initialisation du message. */
String paramAuteur = request.getParameter( "auteur" );
String message = "Transmission de variables : OK ! " + paramAuteur;
/* Cration du bean */
Coyote premierBean = new Coyote();
/* Initialisation de ses proprits */
premierBean.setNom( "Coyote" );
premierBean.setPrenom( "Wile E." );
/* Stockage du message et du bean dans l'objet request */
request.setAttribute( "test", message );
request.setAttribute( "coyote", premierBean );
/* Transmission de la paire d'objets request/response notre JSP
*/
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}

Et modifions ensuite notre JSP pour qu'elle ralise l'affichage des proprits du bean. Nous n'avons pas encore dcouvert le
langage JSP, et ne savons pas encore comment rcuprer proprement un bean Utilisons donc une nouvelle fois, faute de mieux
pour le moment, du langage Java directement dans notre page JSP :
Code : JSP - /WEB-INF/test.jsp

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

68/345

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
<%
String attribut = (String) request.getAttribute("test");
out.println( attribut );

</p>
<p>

String parametre = request.getParameter( "auteur" );


out.println( parametre );
%>

Rcupration du bean :
<%
com.sdzee.beans.Coyote notreBean = (com.sdzee.beans.Coyote)
request.getAttribute("coyote");
out.println( notreBean.getPrenom() );
out.println( notreBean.getNom() );
%>
</p>
</body>
</html>

Remarquez ici la ncessit de prciser le chemin complet (incluant le package) afin de pouvoir utiliser notre bean de type
Coyote.
Retournez alors sur votre navigateur et ouvrez http://localhost:8080/test/toto. Vous observez alors :
Citation
Ceci est une page gnre depuis une JSP.
Transmission de variables : OK !
Rcupration du bean : Wile E. Coyote
Tout se passe comme prvu : nous retrouvons bien les valeurs que nous avions donnes aux proprits nom et prenom de notre
bean, lors de son initialisation dans la servlet !

En rsum
Un bean est un objet Java rutilisable qui reprsente une entit, et dont les donnes sont reprsentes par des
proprits.
Un bean est une classe publique et doit avoir au moins un constructeur par dfaut, public et sans paramtres.
Une proprit d'un bean est un champ non public, qui doit tre accessible travers un couple de getter/setter.
Il faut configurer le build-path d'un projet web sous Eclipse pour qu'il y dpose automatiquement les classes compiles
depuis les codes sources Java de vos objets.
Un bean peut par exemple tre transmis d'une servlet vers une page JSP (ou une autre servlet) en tant qu'attribut de
requte.

L'objectif de ce chapitre est modeste : je ne vous offre ici qu'une prsentation concise de ce que sont les beans, de leur rles et
utilisations dans une application Java EE. Encore une fois, comme pour beaucoup de concepts intervenant dans ce cours, il
faudrait un tutoriel entier pour aborder toutes leurs spcificits, et couvrir en dtail chacun des points importants mis en jeu.
Retenez toutefois que l'utilisation des beans n'est absolument pas limite aux applications web : on peut en effet trouver ces
composants dans de nombreux domaines, notamment dans les solutions graphiques bases sur les composants Swing et AWT
(on parle alors de composant visuel).

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

69/345

Maintenant que nous sommes au point sur le concept, revenons nos moutons : il est temps d'apprendre utiliser un bean
depuis une page JSP sans utiliser de code Java !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

70/345

La technologie JSP (1/2)


Cet ensemble est consacr l'apprentissage de la technologie JSP : nous y tudierons la syntaxe des balises, directives et
actions JSP ainsi que le fonctionnement des expressions EL, et enfin nous tablirons une liste de documentations utiles sur le
sujet. Trop volumineux pour entrer dans un unique chapitre, j'ai d le scinder en deux chapitres distincts.
Ce premier opus a pour objectif de vous prsenter les bases de la syntaxe JSP et ses actions dites standard, toutes illustres par
de brefs exemples.

Les balises
Balises de commentaire
Tout comme dans les langages Java et HTML, il est possible d'crire des commentaires dans le code de vos pages JSP. Ils
doivent tre compris entre les balises <%-- et --%>. Vous pouvez les placer o vous voulez dans votre code source. Ils sont
uniquement destins au(x) dveloppeur(s), et ne sont donc pas visibles par l'utilisateur final dans la page HTML gnre :
Code : JSP
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Exemple</title>
</head>
<body>
<%-- Ceci est un commentaire JSP, non visible dans la page
HTML finale. --%>
<!-- Ceci est un simple commentaire HTML. -->
<p>Ceci est un simple texte.</p>
</body>
</html>

Balises de dclaration
Cette balise vous permet de dclarer une variable l'intrieur d'une JSP. Vous savez dj et nous y reviendrons par la suite qu'il
est dconseill d'crire du code Java dans vos JSP mais, la balise existant, je prfre vous la prsenter. Si vous tombez dessus un
jour, ne soyez pas dstabiliss :
Code : JSP
<%! String chaine = "Salut les zros.";

%>

Il est possible d'effectuer plusieurs dclarations au sein d'un mme bloc. Ci-dessous, les dclarations d'une variable puis d'une
mthode :
Code : JSP
<%! String test = null;
public boolean jeSuisUnZero() {
return true;
}
%>

Balises de scriptlet
Derrire ce mot trange, un mlange atroce entre "script" et "servlet", se cache simplement du code Java. Cette balise vous la
connaissez dj, puisque nous l'avons utilise dans le chapitre prcdent. Elle sert en effet inclure du code Java au sein de vos

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

71/345

pages mais, tout comme la balise prcdente, elle est proscrire dans la mesure du possible ! titre d'information seulement
donc, voici le tag en question, ici au sein d'une balise HTML <form> :
Code : JSP
<form action="/tirage" method="post">
<%
for(int i = 1; i < 3; i++){
out.println("Numro " + i + ": <select
name=\"number"+i+"\">");
for(int j = 1; j <= 10; j++){
out.println("<option value=\""+j+"\">"+ j + "</option>");
}
out.println("</select><br />");
}
%>
<br />
<input type="submit" value="Valider" />
</form>

Oui je sais, c'est un exemple trs moche, car il y a du code Java dans une JSP, code qui contient son tour des lments de
prsentation HTML Mais c'est juste pour l'exemple ! Je vous prviens : le premier que je vois coder comme a, je le pends un
arbre !

Balises d'expression
La balise d'expression est en quelque sorte un raccourci de la scriptlet suivante :
Code : JSP
<% out.println("Bip bip !"); %>

Elle retourne simplement le contenu d'une chane. Voici sa syntaxe :


Code : JSP
<%= "Bip bip !" %>

Notez bien l'absence de point-virgule lors de l'utilisation de ce raccourci.

Les directives
Les directives JSP permettent :
d'importer un package ;
d'inclure d'autres pages JSP ;
d'inclure des bibliothques de balises (nous y reviendrons dans un prochain chapitre) ;
de dfinir des proprits et informations relatives une page JSP.
Pour gnraliser, elles contrlent comment le conteneur de servlets va grer votre JSP. Il en existe trois : taglib, page et include.
Elles sont toujours comprises entre les balises <%@ et %>, et hormis la directive d'inclusion de page qui peut tre place
n'importe o, elles sont placer en tte de page JSP.

Directive taglib
Le code ci-dessous inclut une bibliothque personnalise nomme maTagLib :
Code : JSP
<%@ taglib uri="maTagLib.tld" prefix="tagExemple" %>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

72/345

Je ne dtaille pas, nous reviendrons plus tard sur ce qu'est exactement une bibliothque et sur cet attribut "prefix".

Directive page
La directive page dfinit des informations relatives la page JSP. Voici par exemple comment importer des classes Java :
Code : JSP
<%@ page import="java.util.List, java.util.Date"

%>

Ici, l'import de deux classes est ralis : List et Date. Cette fonctionnalit n'est utile que si vous mettez en place du code Java
dans votre page JSP, afin de rendre disponibles les diffrentes classes et interfaces des API Java. En ce qui nous concerne,
puisque notre objectif est de faire disparatre le Java de nos vues, nous allons trs vite apprendre nous en passer !
D'autres options sont utilisables via cette balise page, comme le contentType ou l'activation de la session. Toutes ont des valeurs
par dfaut, et je ne vais pas m'attarder sur les dtails de chacune d'elles ici. Vous ne vous en servirez que dans des cas trs
spcifiques que nous dcouvrirons au cas par cas dans ce cours. Voici titre d'information l'ensemble des proprits accessibles
via cette directive :
Code : JSP
<%@ page

%>

language="..."
extends="..."
import="..."
session="true | false"
buffer="none | 8kb | sizekb"
autoFlush="true | false"
isThreadSafe="true | false"
isELIgnored ="true | false"
info="..."
errorPage="..."
contentType="..."
pageEncoding="..."
isErrorPage="true | false"

Vous retrouvez ici celle que je vous ai fait utiliser lors de la mise en place de votre premire JSP : le pageEncoding. C'est travers
cette option que vous pouvez spcifier l'encodage qui va tre prcis dans l'en-tte de la rponse HTTP envoye par votre page
JSP.

Directive include
Lorsque vous dveloppez une vue, elle correspond rarement une JSP constitue d'un seul bloc. En pratique, il est trs courant
de dcouper littralement une page web en plusieurs fragments, qui sont ensuite rassembls dans la page finale destination de
l'utilisateur. Cela permet notamment de pouvoir rutiliser certains blocs dans plusieurs vues diffrentes ! Regardez par exemple le
menu des cours sur le site du zro : c'est un bloc part entire, qui est rutilis dans l'ensemble des pages du site.
Pour permettre un tel dcoupage, la technologie JSP met votre disposition une balise qui inclut le contenu d'un autre fichier
dans le fichier courant. Via le code suivant par exemple, vous allez inclure une page interne votre application (en l'occurrence
une page JSP nomme uneAutreJSP, mais cela pourrait trs bien tre une page HTML ou autre) dans votre JSP courante :
Code : JSP
<%@ include file="uneAutreJSP.jsp" %>

La subtilit retenir, c'est que cette directive ne doit tre utilise que pour inclure du contenu "statique" dans votre page :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

73/345

l'exemple le plus courant pour un site web tant par exemple le header ou le footer de la page, trs souvent identiques sur
l'intgralit des pages du site.
Attention, ici quand je vous parle de contenu "statique", je n'insinue pas que ce contenu est fig et ne peut pas
contenir de code dynamique Non, si je vous parle d'inclusion "statique", c'est parce qu'en utilisant cette directive
pour inclure un fichier, l'inclusion est ralise au moment de la compilation ; par consquent, si le code du fichier est
chang par la suite, les rpercussions sur la page l'incluant n'auront lieu qu'aprs une nouvelle compilation !
Pour simplifier, cette directive peut tre vue comme un simple copier/coller d'un fichier dans l'autre : c'est comme si vous
preniez l'intgralit de votre premier fichier, et que vous le colliez dans le second. Vous pouvez donc bien visualiser ici qu'il est
ncessaire de procder cette copie avant la compilation de la page : on ne va pas copier un morceau de page JSP dans une
servlet dj compile

Action standard include


Une autre balise d'inclusion dite "standard" existe, et permet d'inclure du contenu de manire "dynamique". Le contenu sera ici
charg l'excution, et non la compilation comme c'est le cas avec la directive prcdente :
Code : JSP
<%-- L'inclusion dynamique d'une page fonctionne par URL relative :
--%>
<jsp:include page="page.jsp" />
<%-- Son quivalent en code Java est : --%>
<% request.getRequestDispatcher( "page.jsp" ).include( request,
response ); %>
<%-- Et il est impossible d'inclure une page externe comme
ci-dessous : --%>
<jsp:include page="http://www.siteduzero.com" />

Cela dit, ce type d'inclusion a un autre inconvnient : il ne prend pas en compte les imports et inclusions faits dans la page
rceptrice. Pour clarifier, prenons un exemple. Si vous utilisez un type List dans une premire page, et que vous comptez
utiliser une liste dans une seconde page que vous souhaitez inclure dans cette premire page, il vous faudra importer le type
List dans cette seconde page
Je vous ai perdus ?
Voyons tout cela au travers d'un exemple trs simple. Crez une page test_inc.jsp contenant le code
suivant, sous le rpertoire WebContent de votre projet Eclipse, c'est--dire la racine de votre application :
Code : JSP - /test_inc.jsp
<%
ArrayList<Integer> liste = new ArrayList<Integer>();
liste.add( 12 );
out.println( liste.get( 0 ) );
%>

Ce code ne fait qu'ajouter un entier une liste vide, puis l'affiche. Cependant cette page ne contient pas de directive d'import, et
ne peut par consquent pas fonctionner directement : l'import de la classe ArrayList doit obligatoirement tre ralis
auparavant pour que nous puissions l'utiliser dans le code. Si vous tentez d'accder directement cette page via
http://localhost:8080/test/test_inc.jsp, vous aurez droit une jolie exception :
Citation : Exception
org.apache.jasper.JasperException: Unable to compile class for JSP:
An error occurred at line: 2 in the jsp file: /test_inc.jsp
ArrayList cannot be resolved to a type

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

74/345

Crez maintenant une page test_host.jsp, toujours la racine de votre application, qui va raliser l'import de la classe
ArrayList puis inclure la page test_inc.jsp :
Code : JSP - test_host.jsp
<%@ page import="java.util.ArrayList" %>
<%@ include file="test_inc.jsp" %>

Pour commencer, vous dcouvrez ici en premire ligne une application de la directive page, utilise ici pour importer la classe
ArrayList. la seconde ligne, comme je vous l'ai expliqu plus haut, la directive d'inclusion peut tre vue comme un
copier/coller : ici, le contenu de la page test_inc.jsp est copi dans la page test_host.jsp, puis la nouvelle page test_host.jsp
contenant tout le code est compile. Vous pouvez donc appeler la page test_host.jsp, et la page web finale affichera bien "12" !
Mais si maintenant nous dcidons de remplacer la directive prsente dans notre page test_host.jsp par la balise standard
d'inclusion :
Code : JSP - test_host.jsp
<%@ page import="java.util.ArrayList" %>
<jsp:include page="test_inc.jsp" />

Eh bien lorsque nous allons tenter d'accder la page test_host.jsp, nous retrouverons la mme erreur que lorsque nous avons
tent d'accder directement test_inc.jsp ! La raison est la suivante : les deux pages sont compiles sparment, et l'inclusion ne
se fera que lors de lexcution. Ainsi fatalement, la compilation de la page test_inc.jsp ne peut qu'chouer, puisque l'import
ncessaire au bon fonctionnement du code n'est ralis que dans la page hte.
Pour faire simple, les pages incluses via la balise <jsp:include ... /> doivent en quelque sorte tre
"indpendantes" ; elles ne peuvent pas dpendre les unes des autres et doivent pouvoir tre compiles sparment. Ce
n'est pas le cas des pages incluses via la directive <%@ include ... %> .

Pour terminer sur ces problmatiques d'inclusions, je vous donne ici quelques informations et conseils supplmentaires.
Certains serveurs d'applications sont capables de recompiler une page JSP incluant une autre page via la directive
d'inclusion, et ainsi clipser sa principale contrainte. Ce n'est toutefois pas toujours le cas, et a reste donc viter si
vous n'tes pas srs de votre coup
Pour inclure un mme header et un mme footer dans toutes les pages de votre application ou site web, il est prfrable
de ne pas utiliser ces techniques d'inclusion, mais de spcifier directement ces portions communes dans le fichier
web.xml de votre projet. J'en reparlerai dans un prochain chapitre.
Trs bientt, nous allons dcouvrir une meilleure technique d'inclusion de pages avec la JSTL !

La porte des objets


Un concept important intervient dans la gestion des objets par la technologie JSP : la porte des objets. Souvent appele
visibilit, ou scope en anglais, elle dfinit tout simplement leur dure de vie.
Dans le chapitre traitant de la transmission de donnes, nous avions dcouvert un premier type d'attributs : les attributs de
requte. Eh bien de tels objets, qui je vous le rappelle sont accessibles via l'objet HttpServletRequest, ne sont visibles
que durant le traitement d'une mme requte. Ils sont crs par le conteneur lors de la rception d'une requte HTTP, et
disparaissent ds lors que le traitement de la requte est termin.
Ainsi, nous avions donc sans le savoir cr des objets ayant pour porte la requte !

Il existe au total quatre portes diffrentes dans une application :


page (JSP seulement) : les objets possdant cette porte sont uniquement accessibles dans la page JSP en question ;
requte : les objets possdant cette porte sont uniquement accessibles durant l'existence de la requte en cours ;
session : les objets possdant cette porte sont accessibles durant l'existence de la session en cours ;
application : les objets possdant cette porte sont accessibles durant toute l'existence de l'application.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

75/345

Pourquoi prciser "JSP seulement" pour la porte page ?

Eh bien c'est trs simple : il est possible de crer et manipuler des objets de portes requte, session ou application depuis une
page JSP ou depuis une servlet. Nous avions d'ailleurs dans le chapitre traitant de la transmission de donnes cr un objet de
porte requte depuis notre servlet, puis utilis cet objet depuis notre page JSP. En revanche, il n'est possible de crer et
manipuler des objets de porte page que depuis une page JSP, ce n'est pas possible via une servlet.
Qu'est-ce qu'une session ?

Une session est un objet associ un utilisateur en particulier. Elle existe pour la dure pendant laquelle un visiteur va utiliser
l'application, cette dure se terminant lorsque l'utilisateur ferme son navigateur, reste inactif trop longtemps, ou encore lorsqu'il
se dconnecte du site.
Ainsi, il est possible de garder en mmoire des donnes concernant un visiteur d'une requte l'autre, autrement dit de page en
page : la session permet donc de garder une trace de la visite effectue. Plus prcisment, une session correspond en ralit un
navigateur particulier, plutt qu' un utilisateur : par exemple, si un mme instant vous utilisez deux navigateurs diffrents pour
vous rendre sur le mme site, le site crera deux sessions distinctes, une pour chacun des navigateurs.
Un objet session concernant un utilisateur est conserv jusqu' ce qu'une certaine dure dinactivit soit atteinte. Pass ce dlai,
le conteneur considre que ce client n'est plus en train de visiter le site, et dtruit alors sa session.
Pour que vous visualisiez bien le principe, voici un schma regroupant les diffrentes portes existantes :

Portes des objets


Remarquez bien les points suivants :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

76/345

un objet de porte page n'est accessible que sur une page JSP donne ;
un objet de porte requte n'est accessible que durant le cheminement d'une requte dans l'application, et n'existe plus
ds lors qu'une rponse est renvoye au client ;
un objet de porte session est accessible durant l'intgralit de la visite d'un client donn, condition bien sr que le
temps d'inactivit dfini par le conteneur ne soit pas dpass durant cette visite ;
un objet de porte application est accessible durant toute l'existence de l'application et par tous les clients.
Vous devez bien raliser que l'utilisation dans votre code d'objets ayant pour porte l'application est dlicate. Rendezvous compte : ces objets sont accessibles partout, tout le temps et par tout le monde ! Afin d'viter notamment des
problmes de modifications concurrentes, si vous avez besoin de mettre en place de tels objets, il est recommand de
les initialiser ds le chargement de l'application, puis de ne plus toucher leur contenu et d'y accder depuis vos
classes et pages uniquement en lecture seule. Nous tudierons ce scnario dans un prochain chapitre.
Nous reviendrons au cas par cas sur chacune de ces portes dans certains exemples des chapitres venir.

Les actions standard


Autant vous prvenir tout de suite, le droulement de ce chapitre peut vous perturber : je vais dans cette partie du
chapitre vous prsenter une certaine manire de faire pour accder des objets depuis une page JSP. Ensuite, je vais
vous expliquer dans la partie suivante qu'il existe un autre moyen, plus simple et plus propre, et que nous n'utiliserons
alors plus jamais cette premire faon de faire

Maintenant que vous connaissez les beans et les portes, vous avez presque tout en main pour constituer le modle de votre
application (le M de MVC) ! C'est lui et uniquement lui qui va contenir les donnes de votre application, et les traitements y
appliquer. La seule chose qui vous manque encore, c'est la manipulation de ces beans depuis une page JSP.
Vous avez dj fait connaissance avec l'action standard <jsp:include>, je vais vous en prsenter quatre autres :
<jsp:useBean>, <jsp:getProperty>, <jsp:setProperty> et enfin <jsp:forward>.

L'action standard useBean


Voici pour commencer l'action standard permettant d'utiliser un bean, ou de le crer s'il n'existe pas, depuis une page JSP :
Code : JSP
<%-- L'action suivante rcupre un bean de type Coyote et nomm
"coyote" dans
la porte requte s'il existe, ou en cre un sinon. --%>
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote"
scope="request" />
<%-- Elle a le mme effet que le code Java suivant : --%>
<%
com.sdzee.beans.Coyote coyote = (com.sdzee.beans.Coyote)
request.getAttribute( "coyote" );
if ( coyote == null ){
coyote = new com.sdzee.beans.Coyote();
request.setAttribute( "coyote", coyote );
}
%>

tudions les diffrents attributs de cette action.


La valeur de l'attribut id est le nom du bean rcuprer, ou le nom que vous souhaitez donner au bean crer.
L'attribut class correspond logiquement la classe du bean. Il doit obligatoirement tre spcifi si vous souhaitez crer
un bean, mais pas si vous souhaitez simplement rcuprer un bean existant.
L'attribut optionnel scope correspond la porte de l'objet. Si un bean du nom spcifi en id existe dj dans ce scope, et
qu'il est du type ou de la classe prcis(e), alors il est rcupr, sinon une erreur survient. Si aucun bean de ce nom
n'existe dans ce scope, alors un nouveau bean est cr. Enfin, si cet attribut n'est pas renseign, alors le scope par
dfaut sera limit la page en cours.
L'attribut optionnel type doit indiquer le type de dclaration du bean. Il doit tre une superclasse de la classe du bean, ou

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

77/345

une interface implmente par le bean. Cet attribut doit tre spcifi si class ne l'est pas, et vice-versa.
En rsum, cette action permet de stocker un bean (nouveau ou existant) dans une variable, qui sera identifie par la valeur saisie
dans l'attribut id.
Il est galement possible de donner un corps cette balise, qui ne sera excut que si le bean est cr :
Code : JSP
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote">
<%-- Ici, vous pouvez placer ce que vous voulez :
dfinir des proprits, crer d'autres objets, etc. --%>
<p>Nouveau bean !</p>
</jsp:useBean>

Ici, le texte qui est prsent entre les balises ne sera affich que si un bean est bel et bien cr, autrement dit si la balise
<jsp:useBean> est appele avec succs. l'inverse, si un bean du mme nom existe dj dans cette page, alors le bean sera
simplement rcupr et le texte ne sera pas affich.

L'action standard getProperty


Lorsque l'on utilise un bean au sein d'une page, il est possible par le biais de cette action d'obtenir la valeur d'une de ses
proprits :
Code : JSP
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote" />
<%-- L'action suivante affiche le contenu de la proprit 'prenom'
du bean 'coyote' : --%>
<jsp:getProperty name="coyote" property="prenom" />
<%-- Elle a le mme effet que le code Java suivant : --%>
<%= coyote.getPrenom() %>

Faites bien attention la subtilit suivante ! Alors que <jsp:useBean> rcupre une instance dans une variable accessible
par l'id dfini, cette action standard ne rcupre rien, mais ralise seulement l'affichage du contenu de la proprit cible. Deux
attributs sont utiles ici :
name : contient le nom rel du bean, en l'occurrence l'id que l'on a saisi auparavant dans la balise de rcupration du bean
;
property : contient le nom de la proprit dont on souhaite afficher le contenu.

L'action standard setProperty


Il est enfin possible de modifier une proprit du bean utilis. Il existe pour cela quatre faons de faire via l'action standard
ddie cette tche :
Code : JSP - Syntaxe 1
<%-- L'action suivante associe une valeur la proprit 'prenom' du
bean 'coyote' : --%>
<jsp:setProperty name="coyote" property="prenom" value="Wile E." />
<%-- Elle a le mme effet que le code Java suivant : --%>
<% coyote.setPrenom("Wile E."); %>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

78/345

Code : JSP - Syntaxe 2


<%-- L'action suivante associe directement la valeur rcupre
depuis le paramtre de la requte nomm ici 'prenomCoyote' la
proprit 'prenom' : --%>
<jsp:setProperty name="coyote" property="prenom"
param="prenomCoyote"/>
<%-- Elle a le mme effet que le code Java suivant : --%>
<% coyote.setPrenom( request.getParameter("prenomCoyote") ); %>

Code : JSP - Syntaxe 3


<%-- L'action suivante associe directement la valeur rcupre
depuis le paramtre de la requte nomm ici 'prenom' la proprit
de mme nom : --%>
<jsp:setProperty name="coyote" property="prenom" />
<%-- Elle a le mme effet que le code Java suivant : --%>
<% coyote.setPrenom( request.getParameter("prenom") ); %>

Code : JSP - Syntaxe 4


<%-- L'action suivante associe automatiquement la valeur rcupre
depuis chaque paramtre de la requte la proprit de mme nom : -%>
<jsp:setProperty name="coyote" property="*" />
<%-- Elle a le mme effet que le code Java suivant : --%>
<% coyote.setNom( request.getParameter("nom") ); %>
<% coyote.setPrenom( request.getParameter("prenom") ); %>
<% coyote.setGenius( (boolean) request.getParameter("genius") ); %>

L'action standard forward


La dernire action que nous allons dcouvrir permet d'effectuer une redirection vers une autre page. Comme toutes les actions
standard, elle s'effectue ct serveur et pour cette raison il est impossible via cette balise de rediriger vers une page extrieure
l'application. L'action de forwarding est ainsi limite aux pages prsentes dans le contexte de la servlet ou de la JSP utilise :
Code : JSP
<%-- Le forwarding vers une page de l'application fonctionne par URL
relative : --%>
<jsp:forward url="/page.jsp" />
<%-- Son quivalent en code Java est : --%>
<% request.getRequestDispatcher( "/page.jsp" ).forward( request,
response ); %>
<%-- Et il est impossible de rediriger vers un site externe comme
ci-dessous : --%>
<jsp:forward url="http://www.siteduzero.com" />

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

79/345

Une particularit du forwarding est qu'il n'implique pas d'aller/retour passant par le navigateur de l'utilisateur final. Autrement
dit, l'utilisateur final n'est pas au courant que sa requte a t redirige vers une ou plusieurs JSP diffrentes, puisque l'URL qui
est affiche dans son navigateur ne change pas. Pas d'inquitude, nous y reviendrons en dtail lorsque nous tudierons un cas
particulier, dans le chapitre concernant les sessions.
Sachez enfin que lorsque vous utilisez le forwarding , le code prsent aprs cette balise dans la page n'est pas excut.
Je vous prsente toutes ces notations afin que vous sachiez qu'elles existent, mais vous devez comprendre que la plupart de
celles-ci taient d'actualit il y a une petite dizaine d'annes maintenant ! Depuis, d'importantes volutions ont chang la
donne et tout cela n'est aujourd'hui utilis que dans des cas bien spcifiques.
La vraie puissance de la technologie JSP, c'est dans le chapitre suivant que vous allez la dcouvrir !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

80/345

La technologie JSP (2/2)


Nous allons dans ce chapitre terminer l'apprentissage de la technologie JSP, travers la dcouverte des expression EL et des
objets implicites.

Expression Language
Prsentation
Dans cette seconde moiti, nous allons dcouvrir ensemble les bases de l'Expression Language, que l'on raccourcit trs souvent
EL.
Je rpte ce dont je vous ai averti dans la partie prcdente : une fois que vous aurez assimil cette technologie, vous
n'aurez plus jamais utiliser les actions standard d'utilisation des beans que nous venons de dcouvrir ! Rassurezvous, je ne vous les ai pas prsentes juste pour le plaisir : il est important que vous connaissiez ce mode de
fonctionnement, afin de ne pas tre surpris si un jour vous tombez dessus. Seulement c'est une approche diffrente du
modle MVC, une approche qui n'est pas compatible avec ce que nous apprenons ici.

En quoi consistent les expressions EL ?

Ces expressions sont indispensables une utilisation optimale des JSP. C'est grce elles que l'on peut s'affranchir
dfinitivement de l'criture de scriptlets (du code Java, pour ceux qui n'ont pas suivi) dans nos belles pages JSP. Pour faire simple
et concis, les expressions EL permettent via une syntaxe trs pure d'effectuer des tests basiques sur des expressions, et de
manipuler simplement des objets et attributs dans une page, et cela sans ncessiter l'utilisation de code ni de script Java ! La
maintenance de vos pages JSP, en fournissant des notations simples et surtout standard, est ainsi grandement facilite.
Avant tout, tudions la forme et la syntaxe d'une telle expression :
Code : JSP
${ expression }

Ce type de notation ne devrait pas tre inconnu ceux d'entre vous qui ont dj programm en Perl. Ce qu'il faut bien retenir,
c'est que ce qui est situ entre les accolades va tre interprt : lorsqu'il va analyser votre page JSP, le conteneur va reprer ces
expressions entoures d'accolades et il saura ainsi qu'il doit en interprter le contenu. Aussi, ne vous tonnez pas si dans la suite
de ce chapitre j'voque l'intrieur d'une expression EL : je parle tout simplement de ce qui est situ entre les accolades !

La ralisation de tests
La premire chose que vous devez savoir, c'est qu' l'intrieur d'une expression vous pouvez effectuer diverses sortes de tests.
Pour raliser ces tests, il vous est possible d'inclure tout une srie d'oprateurs. Parmi ceux-ci, on retrouve les traditionnels :
oprateurs arithmtiques, applicables des nombres : +, -, *, /, % ;
oprateurs logiques, applicables des boolens : &&, ||, ! ;
oprateurs relationnels, bass sur l'utilisation des mthodes equals() et compareTo() des objets compars : == ou
eq, != ou ne, < ou lt, > ou gt, <= ou le, >= ou ge.
Voyons concrtement ce que tout cela donne travers quelques exemples. Crez pour l'occasion une page nomme test_el.jsp
la racine de votre application, et placez-y ces quelques lignes :
Code : JSP - /test_el.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des expressions EL</title>
</head>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

81/345

<body>
<p>
<!-- Logiques sur des boolens -->
${ true && true } <br /> <!-- Affiche true -->
${ true && false } <br /> <!-- Affiche false -->
${ !true || false } <br /> <!-- Affiche false -->
<!-- Calculs arithmtiques -->
${ 10 / 4 } <br /> <!-- Affiche 2.5 -->
${ 10 mod 4 } <br /> <!-- Affiche le reste de la division
entire, soit 2 -->
${ 10 % 4 } <br /> <!-- Affiche le reste de la division
entire, soit 2 -->
${ 6 * 7 } <br /> <!-- Affiche 42 -->
${ 63 - 8 } <br /> <!-- Affiche 55 -->
${ 12 / -8 } <br /> <!-- Affiche -1.5 -->
${ 7 / 0 } <br /> <!-- Affiche Infinity -->
<!-- Compare les caractres 'a' et 'b'. Le caractre 'a'
tant bien situ avant le caractre 'b' dans l'alphabet ASCII,
cette EL affiche true. -->
${ 'a' < 'b' } <br />
<!-- Compare les chanes 'hip' et 'hit'. Puisque 'p' < 't',
cette EL affiche false. -->
${ 'hip' gt 'hit' } <br />
<!-- Compare les caractres 'a' et 'b', puis les chanes
'hip' et 'hit'. Puisque le premier test renvoie true et le second
false, le rsultat est false. -->
${ 'a' < 'b' && 'hip' gt 'hit' } <br />
<!-- Compare le rsultat d'un calcul une valeur fixe.
Ici, 6 x 7 vaut 42 et non pas 48, le rsultat est false. -->
${ 6 * 7 == 48 } <br />
</p>
</body>
</html>

Rendez-vous alors sur http://localhost:8080/test/test_el.jsp, et vrifiez que les rsultats obtenus correspondent bien aux
commentaires que j'ai placs sur chaque ligne.
Remarquez la subtilit dvoile ici dans l'exemple de la ligne 27, au niveau des chanes de caractres : contrairement du code
Java, dans lequel vous ne pouvez dclarer une String qu'en utilisant des double quotes (guillemets), vous pouvez utiliser
galement des simple quotes (apostrophes) dans une expression EL. Pour information, ceci a t rendu possible afin de simplifier
l'intgration des expressions EL dans les balises JSP : celles-ci contenant dj bien souvent leurs propres guillemets, cela vite
au dveloppeur de s'emmler les crayons ! Pas de panique, vous comprendrez o je veux en venir dans la partie suivante, lorsque
nous pratiquerons la JSTL !
Attention ici aux oprateurs relationnels :
si vous souhaitez vrifier l'galit d'objets de type non standard via une EL, il vous faudra probablement r-implmenter
les mthodes cites dans le troisime point de la liste prcdente ;
si vous souhaitez effectuer une comparaison, il vous faudra vrifier que votre objet implmente bien l'interface
Comparable.
Autrement dit, pas besoin de vous casser la tte pour un objet de type String ou Integer, pour lesquels tout est dj prt
nativement, mais pour des objets de votre propre cration et/ou de types personnaliss, pensez-y !
Les oprateurs suivent comme toujours un ordre de priorit : comme on a d vous l'apprendre en cours lmentaire, la
multiplication est prioritaire sur l'addition, etc.
J'omets ici volontairement certaines informations, notamment
certains oprateurs que je ne juge pas utile de vous prsenter ; je vous renvoie vers la documentation officielle pour
plus d'informations. Les applications que nous verrons dans ce cours ne mettront pas en jeu d'expressions EL trs
complexes, et vous serez par la suite assez l'aise avec le concept pour comprendre par vous-mme les subtilits de
leur utilisation dans des cas plus labors.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

82/345

En outre, deux autres types de test sont frquemment utiliss au sein des expressions EL :
les conditions ternaires, de la forme : test ? si oui : sinon ;
les vrifications si vide ou null, grce l'oprateur empty.
Trs pratiques, ils se prsentent sous cette forme :
Code : JSP
<!-- Vrifications si vide ou null -->
${ empty 'test' } <!-- La chane teste n'est pas vide, le rsultat
est false -->
${ empty '' } <!-- La chane teste est vide, le rsultat est true
-->
${ !empty '' } <!-- La chane teste est vide, le rsultat est
false -->
<!-- Conditions ternaires -->
${ true ? 'vrai' : 'faux' } <!-- Le boolen test vaut true, vrai
est affich -->
${ 'a' > 'b' ? 'oui' : 'non' } <!-- Le rsultat de la comparaison
vaut false, non est affich -->
${ empty 'test' ? 'vide' : 'non vide' } <!-- La chane teste
n'est pas vide, non vide est affich -->

Pour terminer, sachez enfin que la valeur retourne par une expression EL positionne dans un texte ou un contenu statique sera
insre l'endroit mme o est situe l'expression :
Code : JSP
<!-- La ligne suivante : -->
<p>12 est infrieur 8 : ${ 12 lt 8 }.</p>
<!-- Sera rendue ainsi aprs interprtation de l'expression, 12
n'tant pas infrieur 8 : -->
<p>12 est infrieur 8 : false.</p>

La manipulation d'objets
Toutes ces fonctionnalits semblent intressantes, mais ne nous serviraient pas grand-chose si elles ne pouvaient s'appliquer
qu' des valeurs crites en dur dans le code de nos pages, comme nous l'avons fait l'instant dans nos exemples. La vraie
puissance des expressions EL, leur vritable intrt, c'est le fait qu'elles permettent de manipuler des objets et de leur appliquer
tous ces tests ! Quels types d'objets ? Voyons cela au cas par cas

Des beans
Sous la couverture, la technologie EL est base sur les spcifications des JavaBeans. Qu'est-ce que cela signifie concrtement ?
Eh bien tout simplement qu'il est possible via une expression EL d'accder directement une proprit d'un bean ! Pour illustrer
cette fonctionnalit sans trop compliquer notre exemple, nous allons utiliser les actions standard que nous avons dcouvertes
dans le chapitre prcdent. ditez le fichier test_el.jsp que nous avons mis en place, et remplacez son contenu par ce code :
Code : JSP - /test_el.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

83/345

<title>Test des expressions EL</title>


</head>
<body>
<p>
<!-- Initialisation d'un bean de type Coyote avec une
action standard, pour l'exemple : -->
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote" />
<!-- Initialisation de sa proprit 'prnom' : -->
<jsp:setProperty name="coyote" property="prenom" value="Wile
E."/>
<!-- Et affichage de sa valeur : -->
<jsp:getProperty name="coyote" property="prenom" />
</p>
</body>
</html>

Grce aux deux premires actions (lignes 10 et 12), la base de notre exemple est pose : nous crons un bean de type Coyote dans
notre page JSP, et initialisons sa proprit prenom avec la valeur "Wile E.".
Vous retrouvez ensuite la ligne 14 l'action qui affiche le contenu de cette proprit, et lorsque vous vous rendez sur
http://localhost:8080/test/test_el.jsp, le rsultat affich par le navigateur est logiquement "Wile E.".
Maintenant, remplacez cette ligne 14 par l'expression EL suivante :
Code : JSP
${ coyote.prenom }

Actualisez alors la page de tests dans votre navigateur, et vous observerez que le contenu n'a pas chang, la valeur de la
proprit prnom est toujours correctement affiche. Eh bien oui, c'est tout ce qu'il est ncessaire d'crire avec la technologie EL
! Cette expression retourne le contenu de la proprit prenom du bean nomm coyote. Remarquez bien la syntaxe et la convention
employes :
coyote est le nom du bean, que nous avions ici dfini dans l'attribut id de l'action <jsp:useBean> ;
prenom est un champ priv du bean (une proprit) accessible par sa mthode publique getPrenom() ;
l'oprateur point permet de sparer le bean vis de sa proprit.
Ainsi de manire gnrale, il suffit d'crire ${ bean.propriete } pour accder une proprit d'un bean. Simple et efficace
!
Pour information, mais nous y reviendrons un peu plus tard, voici ce quoi ressemble le code Java qui est mis en uvre dans les
coulisses lors de l'interprtation de l'expression ${ coyote.prenom } :
Code : Java
Coyote bean = (Coyote) pageContext.findAttribute( "coyote" );
if ( bean != null ) {
String prenom = bean.getPrenom();
if ( prenom != null ) {
out.print( prenom );
}
}

Peu importe que nous la comparions avec une scriptlet Java ou avec une action standard, l'expression EL simplifie l'criture de
manire frappante ! Ci-dessous, je vous propose d'tudier quelques exemples des utilisations et erreurs de syntaxe les plus
courantes :
Code : JSP

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

84/345

<!-- Syntaxe conseille pour rcuprer la proprit 'prenom' du


bean 'coyote'. -->
${ coyote.prenom }
<!-- Syntaxe correcte, car il est possible d'expliciter la mthode
d'accs la proprit. Prfrez toutefois la notation prcdente.
-->
${ coyote.getPrenom() }
<!-- Syntaxe errone : la premire lettre de la proprit doit tre
une minuscule. -->
${ coyote.Prenom }

Voil pour la syntaxe employer pour accder des objets. Maintenant comme je vous l'annonais en dbut de paragraphe, la
vraie puissance de la technologie EL rside non seulement dans le fait qu'elle permet de manipuler des beans, mais galement
dans le fait qu'elle permet de les faire intervenir au sein de tests ! Voici quelques exemples d'utilisations, toujours bass sur la
proprit prenom du bean coyote :
Code : JSP
<!-- Comparaison d'galit entre la proprit prenom et la chane
"Jean-Paul" -->
${ coyote.prenom == "Jean-Paul" }
<!-- Vrification si la proprit prenom est vide ou nulle -->
${ empty coyote.prenom }
<!-- Condition ternaire qui affiche la proprit prnom si elle
n'est ni vide ni nulle, et la chane "Veuillez prciser un prnom"
sinon -->
${ !empty coyote.prenom ? coyote.prenom : "Veuillez prciser un
prnom" }

En outre, sachez galement que les expressions EL sont protges contre un ventuel retour null :
Code : JSP
<!-- La scriptlet suivante affiche "null" si la proprit "prenom"
n'a pas t initialise,
et provoque une erreur la compilation si l'objet "coyote" n'a pas
t initialis : -->
<%= coyote.getPrenom() %>
<!-- L'action suivante affiche "null" si la proprit "prenom" n'a
pas t initialise,
et provoque une erreur l'excution si l'objet "coyote" n'a pas
t initialis : -->
<jsp:getProperty name="coyote" property="prenom" />
<!-- L'expression EL suivante n'affiche rien si la proprit
"prenom" n'a pas t initialise,
et n'affiche rien si l'objet "coyote" n'a pas t initialis : -->
${ coyote.prenom }

Des collections
Les beans ne sont pas les seuls objets manipulables dans une expression EL, il est galement possible d'accder aux collections

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

85/345

au sens large. Cela inclut donc tous les objets de type java.util.List, java.util.Set, java.util.Map, etc.
Nous allons pour commencer reprendre notre page test_el.jsp, et remplacer son code par cet exemple illustrant l'accs aux
lments d'une liste :
Code : JSP - /test_el.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des expressions EL</title>
</head>
<body>
<p>
<%
/* Cration d'une liste de lgumes et insertion de quatre
lments */
java.util.List<String> legumes = new
java.util.ArrayList<String>();
legumes.add( "poireau" );
legumes.add( "haricot" );
legumes.add( "carotte");
legumes.add( "pomme de terre" );
request.setAttribute( "legumes" , legumes );
%>
<!-- Les quatre syntaxes suivantes retournent le deuxime
lment de la liste de lgumes -->
${ legumes.get(1) }<br />
${ legumes[1] }<br />
${ legumes['1'] }<br />
${ legumes["1"] }<br />
</p>
</body>
</html>

Toujours afin de ne pas compliquer l'exemple, j'initialise directement une liste de lgumes l'aide d'une scriptlet Java. Rappelezvous bien que je procde ainsi uniquement pour gagner du temps dans la mise en place de notre exemple, et que lors du
dveloppement d'une vraie application, il est hors de question d'crire une page JSP aussi sale.
Vous dcouvrez aux lignes 20 23 quatre nouvelles notations :
l'appel une mthode de l'objet legumes. En l'occurrence notre objet est une liste, et nous appelons sa mthode get()
en lui passant l'indice de l'lment voulu ;
l'utilisation de crochets la place de l'oprateur point, contenant directement l'indice de l'lment voulu ;
l'utilisation de crochets la place de l'oprateur point, contenant l'indice de l'lment entour d'apostrophes ;
l'utilisation de crochets la place de l'oprateur point, contenant l'indice de l'lment entour de guillemets.
Chacune d'elles est valide, et retourne bien le second lment de la liste de lgumes que nous avons initialise (souvenez-vous,
l'indice du premier lment d'une collection est 0 et non pas 1). Rendez-vous sur la page http://localhost:8080/test/test_el.jsp et
constatez par vous-mmes !
Remplacez ensuite le code de l'exemple par le suivant, illustrant l'accs aux lments d'un tableau :
Code : JSP - /test_el.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des expressions EL</title>
</head>
<body>
<p>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

86/345

<%
/* Cration d'un tableau */
String[] animaux = {"chien", "chat", "souris", "cheval"};
request.setAttribute("animaux" , animaux);
%>
<!-- Les trois syntaxes suivantes retournent le troisime
lment du tableau -->
${ animaux[2] }<br />
${ animaux['2'] }<br />
${ animaux["2"] }<br />
</p>
</body>
</html>

Rendez-vous nouveau sur la page de tests depuis votre navigateur, et vous constaterez que les trois notations avec les
crochets, appliques une liste dans le prcdent exemple, fonctionnent de la mme manire avec un tableau.
Sachez par ailleurs qu'il est impossible d'utiliser directement l'oprateur point pour accder un lment d'une liste ou
d'un tableau. Les syntaxes ${entiers.1} ou ${animaux.2} enverront une expression l'excution.

Enfin, remplacez le code de l'exemple par le suivant, illustrant l'accs aux lments d'une Map :
Code : JSP - /test_el.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des expressions EL</title>
</head>
<body>
<p>
<%
/* Cration d'une Map */
java.util.Map<String,Integer> desserts = new
java.util.HashMap<String, Integer>();
desserts.put("cookies", 8);
desserts.put("glaces", 3);
desserts.put("muffins", 6);
desserts.put("tartes aux pommes", 2);
request.setAttribute("desserts" , desserts);
%>
<!-- Les quatre syntaxes suivantes retournent la valeur
associe la cl "cookies" de la Map de desserts -->
${ desserts.cookies }<br />
${ desserts.get("cookies") }<br />
${ desserts['cookies'] }<br />
${ desserts["cookies"] }<br />
<%
/* Cration d'une chane nomme "element" et contenant le
mot "cookies" */
String element = "cookies";
request.setAttribute("element",element);
%>
<!-- Il est galement possible d'utiliser un objet au lieu
d'initialiser la cl souhaite directement dans l'expression -->
${ desserts[element] }<br />
</p>
</body>
</html>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

87/345

Rendez-vous une nouvelle fois sur la page de tests depuis votre navigateur, et remarquez deux choses importantes :
la notation avec l'oprateur point fonctionne, la ligne 21, de la mme manire que lors de l'accs une proprit d'un
bean ;
une expression peut en cacher une autre ! En l'occurrence la ligne 32, lorsque le conteneur va analyser l'expression EL il
va d'abord rcuprer l'attribut de requte element, puis utiliser son contenu en guise de cl afin d'accder la valeur
associe dans la Map de desserts.
Par ailleurs, faites bien attention la syntaxe ${desserts[element]} employe dans ce dernier cas :
il est impratif de ne pas entourer le nom de l'objet d'apostrophes ou de guillemets au sein des crochets. En effet, crire
${desserts["element"]} reviendrait essayer d'accder la valeur associe la cl nomme "element", ce qui
n'est pas le comportement souhait ici ;
il ne faut pas entourer l'expression contenue dans l'expression englobante avec des accolades. Autrement dit, il ne faut
pas crire ${desserts[${element}]}, cette syntaxe n'est pas valide. Une seule paire d'accolades suffit !

Puisque les notations avec l'oprateur point et avec les crochets fonctionnent toutes deux dans le cas d'une Map,
quelle est la notation recommande ?
Une pratique efficace veut que l'on rserve la notation avec l'oprateur point pour l'accs aux proprits d'un bean, et que l'on
utilise les crochets pour accder aux contenus d'une Map. Ainsi en lisant le code d'une page JSP, il devient trs simple de savoir
si l'objet manipul dans une expression EL est un bean ou une Map.
Toutefois, ce n'est pas une obligation et vous tes libres de suivre ou non cette bonne pratique dans vos projets, je ne vous
conseille rien de particulier ce sujet. Personnellement j'utilise ds que j'en ai l'occasion la notation avec l'oprateur point, car je
trouve qu'elle a tendance moins surcharger visuellement les expressions EL dans le code de mes pages JSP.

Pour clore sur ce sujet, je ne vous l'ai pas dit lorsque nous avons dcouvert la manipulation des beans dans une
expression EL, mais sachez que l'oprateur point n'est pas la seule manire d'accder une proprits d'un bean, il est
galement possible d'utiliser la notation avec les crochets : ${bean["proprit"]}.

Dsactiver l'valuation des expressions EL


Le format utilis par le langage EL, savoir ${ ... }, n'tait pas dfini dans les premires versions de la technologie JSP.
Ainsi, si vous travaillez sur de vieilles applications non mises jour, il est possible que vous soyez amens empcher de telles
expressions d'tre interprtes, afin d'assurer la rtro-compatibilit avec le code. C'est pour cela qu'il est possible de dsactiver
lvaluation des expressions EL :
au cas par cas, grce la directive page que nous avons brivement dcouverte dans le chapitre prcdent ;
sur tout ou partie des pages, grce une section ajouter dans le fichier web.xml.

Avec la directive page


La directive suivante dsactive l'valuation des EL dans une page JSP :
Code : JSP - Directive placer en tte d'une page JSP
<%@ page isELIgnored ="true" %>

Les seules valeurs acceptes par l'attribut isELIgnored sont true et false :
s'il est initialis true, alors les expressions EL seront ignores et apparatront en tant que simples chanes de
caractres ;
s'il est initialis false, alors elles seront interprtes par le conteneur.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

88/345

Vous pouvez d'ailleurs faire le test dans votre page test_el.jsp. ditez le fichier et insrez-y en premire ligne la directive.
Enregistrez la modification et actualisez alors l'affichage de la page dans votre navigateur. Vous observerez que vos expressions
ne sont plus values, elles sont cette fois simplement affiches telles quelles.

Avec le fichier web.xml


Vous pouvez dsactiver l'valuation des expressions EL sur tout un ensemble de pages JSP dans une application grce l'option
<el-ignored> du fichier web.xml. Elle se prsente dans une section de cette forme :
Code : XML - Section ajouter dans le fichier web.xml
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>

Vous connaissez dj le principe du champ <url-pattern>, que nous avons dcouvert lorsque nous avons mis en place
notre premire servlet. Pour rappel donc, il permet de dfinir sur quelles pages appliquer ce comportement. En l'occurrence, la
notation *.jsp ici utilise signifie que toutes les pages JSP de l'application seront impactes par cette configuration.
Le champ <el-ignored> permet logiquement de dfinir la valeur de l'option. Le comportement est bien entendu le mme
qu'avec la directive prcdente : si true est prcis alors les EL seront ignores, et si false est prcis elles seront
interprtes.

Comportement par dfaut


Si vous ne mettez pas de configuration spcifique en place, comme celles que nous venons l'instant de dcouvrir, la valeur de
l'option isELIgnored va dpendre de la version de l'API servlet utilis par votre application :
si la version est suprieure ou gale 2.4, alors les expressions EL seront values par dfaut ;
si la version est infrieure 2.4, alors il est possible que les expressions EL soient ignores par dfaut, pour assurer la
rtro-compatibilit dont je vous ai dj parl.
Comment savoir si une application permet d'utiliser les expressions EL ou non ?

Pour commencer, il faut s'assurer de la version de l'API servlet supporte par le conteneur qui fait tourner l'application. En
l'occurrence, nous utilisons Tomcat 7 et celui-ci implmente la version 3.0 : tout va bien de ce ct, notre conteneur est capable
de grer les expression EL.
Ensuite, il faut s'assurer que l'application est dclare correctement pour utiliser cette version. Cela se passe au niveau de la
balise <web-app> du fichier web.xml. Lorsque nous avions mis en place celui de notre projet, je vous avais dit de ne pas vous
soucier des dtails et de vous contenter d'crire :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
...
</web-app>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

89/345

La mise en place de tous ces attributs implique que notre application va se baser sur la version 3.0 de l'API servlet.
Ainsi, puisque notre conteneur le supporte et que notre application est correctement configure, nous pouvons en dduire que
les expressions EL seront interprtes par dfaut dans notre application.

Si nous changeons de serveur d'applications, que va-t-il se passer ?

Eh oui, si jamais vous dployez votre application sur un autre serveur que Tomcat 7, il est tout fait envisageable que la version
supporte par le conteneur utilis soit diffrente. Si par exemple vous travaillez sur une application un peu ancienne tournant sur
un conteneur Tomcat 6, alors la version maximum de l'API servlet supporte est 2.5. Voici alors comment vous devrez dclarer
votre application :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
...
</web-app>

Cette introduction la technologie EL se termine l. Il y en a bien assez dire sur le sujet pour crire un tutoriel entier, mais ce
que nous avons appris ici nous suffira dans la plupart des cas. Retenez bien que ces expressions vont vous permettre de ne plus
faire intervenir de Java dans vos JSP, et puisque vous savez maintenant de quoi il retourne, vous ne serez pas surpris de
retrouver la syntaxe ${...} dans tous les futurs exemples de ce cours.

Les objets implicites

Il nous reste un concept important aborder avant de passer la pratique : les objets implicites. Il en existe deux types :
ceux qui sont mis disposition via la technologie JSP ;
ceux qui sont mis disposition via la technologie EL.

Les objets de la technologie JSP


Pour illustrer ce nouveau concept, revenons sur la premire JSP que nous avions crite dans le chapitre sur la transmission des
donnes :
Code : JSP - /WEB-INF/test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
<%
String attribut = (String) request.getAttribute("test");
out.println( attribut );
%>
</p>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

90/345

</body>
</html>

Je vous avais alors fait remarquer qu' la ligne 12, nous avions directement utilis l'objet out sans jamais l'avoir instanci
auparavant. De mme, la ligne 10 nous accdions directement la mthode request.getAttribute() sans jamais avoir
instanci d'objet nomm request
Comment est-ce possible ?

Pour rpondre cette question, nous devons nous intresser une nouvelle fois au code de la servlet auto-gnre par Tomcat,
comme nous l'avions fait dans le second chapitre de cette partie. Retournons donc dans le rpertoire work du serveur, qui
rappelez-vous est subtilis par Eclipse, et analysons nouveau le code du fichier test_jsp.java :
Code : Java - Extrait de la servlet auto-gnre par Tomcat
...
public void _jspService(final
javax.servlet.http.HttpServletRequest request, final
javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request,
response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <meta charset=\"utf-8\" />\r\n");
out.write(" <title>Test</title>\r\n");
out.write(" </head>\r\n");
out.write(" <body>\r\n");
out.write(" <p>Ceci est une page gnre depuis une
JSP.</p>\r\n");
out.write(" <p>\r\n");
out.write(" ");
String attribut = (String) request.getAttribute("test");
out.println( attribut );
out.write("\r\n");
out.write(" </p>\r\n");
out.write(" </body>\r\n");
out.write("</html>");

}
...

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

91/345

Analysons ce qui se passe dans le cas de l'objet out :


la ligne 10, un objet nomm out et de type JspWriter est cr ;
la ligne 24, il est initialis avec l'objet writer rcupr depuis la rponse ;
la ligne 39, c'est tout simplement notre ligne de code Java, base sur l'objet out, qui est recopie telle quelle de la JSP
vers la servlet auto-gnre !
Pour l'objet request, c'est un peu diffrent. Comme je vous l'ai dj expliqu dans le second chapitre, notre JSP est ici transforme
en servlet. Si elle en diffre par certains aspects, sa structure globale ressemble toutefois beaucoup celle de la servlet que nous
avons cre et manipule dans nos exemples jusqu' prsent. Regardez la ligne 3 : le traitement de la paire requte/rponse est
contenu dans une mthode qui prend pour arguments les objets HttpServletRequest et HttpServletResponse,
exactement comme le fait notre mthode doGet() ! Voil pourquoi il est possible d'utiliser directement les objets request et
response depuis une JSP.
Vous devez maintenant comprendre pourquoi vous n'avez pas besoin d'instancier ou de rcuprer les objets out et
request avant de les utiliser dans le code de votre JSP : dans les coulisses, le conteneur s'en charge pour vous
lorsqu'il traduit votre page en servlet ! Et c'est pour cette raison que ces objets sont dits "implicites" : vous n'avez pas
besoin de les dclarer de manire explicite. Logique, non ?

Par ailleurs, si vous regardez attentivement le code ci-dessus, vous constaterez que les lignes 6 13 correspondent en ralit
toutes des initialisations d'objets : pageContext, session, application En fin de compte, le conteneur met votre disposition
toute une srie d'objets implicites, tous accessibles directement depuis vos pages JSP. En voici la liste :
Identifiant

Type de l'objet

Description

pageContext PageContext

Il fournit des informations utiles relatives au contexte d'excution. Entre autres, il


permet d'accder aux attributs prsents dans les diffrentes portes de
l'application. Il contient galement une rfrence vers tous les objets implicites
suivants.

application

ServletContext

Il permet depuis une page JSP d'obtenir ou de modifier des informations relatives
l'application dans laquelle elle est excute.

session

HttpSession

Il reprsente une session associe un client. Il est utilis pour lire ou placer des
objets dans la session de l'utilisateur courant.

request

HttpServletRequest

Il reprsente la requte faite par le client. Il est gnralement utilis pour accder
aux paramtres et aux attributs de la requte, ainsi qu' ses en-ttes.

response

Il reprsente la rponse qui va tre envoye au client. Il est gnralement utilis


HttpServletResponse pour dfinir le Content-Type de la rponse, lui ajouter des en-ttes ou encore
pour rediriger le client.

exception

Throwable

Il est uniquement disponible dans les pages d'erreur JSP. Il reprsente l'exception
qui a conduit la page d'erreur en question.

out

JspWriter

Il reprsente le contenu de la rponse qui va tre envoye au client. Il est utilis


pour crire dans le corps de la rponse.

config

ServletConfig

Il permet depuis une page JSP d'obtenir les ventuels paramtres d'initialisation
disponibles.

page

objet this

Il est l'quivalent de la rfrence this et reprsente la page JSP courante. Il est


dconseill de l'utiliser, pour des raisons de dgradation des performances
notamment.

De la mme manire que nous avons utilis les objets request et out dans notre exemple prcdent, il est possible d'utiliser
n'importe lequel de ces neuf objets travers le code Java que nous crivons dans nos pages JSP
Hein ?! Encore du code Java dans nos pages JSP ?

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

92/345

Eh oui, tout cela est bien aimable de la part de notre cher conteneur, mais des objets sous cette forme ne vont pas nous servir
grand-chose ! Souvenez-vous : nous avons pour objectif de ne plus crire de code Java directement dans nos pages.

Les objets de la technologie EL


J'en vois dj quelques-uns au fond qui sortent les cordes
Vous avez peine digr les objets implicites de la technologie
JSP, je vous annonce maintenant qu'il en existe d'autres rendus disponibles par les expressions EL ! Pas de panique, reprenons
tout cela calmement. En ralit, et heureusement pour nous, la technologie EL va apporter une solution lgante au problme que
nous venons de soulever : nous allons grce elle pouvoir profiter des objets implicites sans crire de code Java !
Dans les coulisses, le concept est sensiblement le mme que pour les objets implicites JSP : il s'agit d'objets grs
automatiquement par le conteneur lors de l'valuation des expressions EL, et auxquels nous pouvons directement accder depuis
nos expressions sans les dclarer auparavant. Voici un tableau des diffrents objets implicites mis disposition par la
technologie EL :
Catgorie
JSP

Identifiant
pageContext

Objet contenant des informations sur


l'environnement du serveur.

pageScope

Une Map qui associe les noms et valeurs des attributs


ayant pour porte la page.

requestScope

Une Map qui associe les noms et valeurs des attributs


ayant pour porte la requte.

sessionScope

Une Map qui associe les noms et valeurs des attributs


ayant pour porte la session.

applicationScope

Une Map qui associe les noms et valeurs des attributs


ayant pour porte l'application.

param

Une Map qui associe les noms et valeurs des paramtres


de la requte.

paramValues

Une Map qui associe les noms et multiples valeurs ** des paramtres
de la requte sous forme de tableaux de String.

header

Une Map qui associe les noms et valeurs des paramtres


des en-ttes HTTP.

headerValues

Une Map qui associe les noms et multiples valeurs ** des paramtres
des en-ttes HTTP sous forme de tableaux de String.

cookie

Une Map qui associe les noms et instances des cookies.

Portes

Paramtres de requte

En-ttes de requte

Cookies

Description

Paramtres dinitialisation initParam

Une Map qui associe les donnes contenues dans les


champs <param-name> et <param-value> de
la section <init-param> du fichier web.xml.

La premire chose remarquer dans ce tableau, c'est que le seul objet implicite en commun entre les JSP et les expressions EL est
le pageContext. Je ne m'attarde pas plus longtemps sur cet aspect, nous allons y revenir dans le chapitre suivant.
La seconde, c'est la diffrence flagrante avec les objets implicites JSP : tous les autres objets implicites de la technologie EL sont
des Map !
D'ailleurs, qu'est-ce que c'est que toute cette histoire de Map et d'associations entre des noms et des valeurs ?

a peut vous paratre compliqu, mais en ralit c'est trs simple. C'est un outil incontournable en Java, et nous venons d'en
manipuler une lorsque nous avons dcouvert les expressions EL. Mais si jamais vous ne vous souvenez pas bien des collections
Java, sachez qu'une Map est un objet qui peut se reprsenter comme un tableau deux colonnes :
la premire colonne contient ce que l'on nomme les cls, qui doivent obligatoirement tre uniques ;

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

93/345

la seconde contient les valeurs, qui peuvent quant elles tre associes plusieurs cls.
Chaque ligne du tableau ne peut contenir qu'une cl et une valeur. Voici un exemple d'une Map<String, String>
reprsentant une liste d'aliments et leurs types :
Aliments (Cls) Types (Valeurs)
pomme

fruit

carotte

lgume

boeuf

viande

aubergine

lgume

Vous voyez bien ici qu'un mme type peut tre associ diffrents aliments, mais qu'un mme aliment ne peut exister qu'une
seule fois dans la liste. Eh bien c'est a le principe d'une Map : c'est un ensemble d'lments uniques auxquels on peut associer
n'importe quelle valeur.
Quel est le rapport avec la technologie EL ?

Le rapport, c'est que comme nous venons de le dcouvrir, nos expressions EL sont capables d'accder au contenu d'une Map, de
la mme manire qu'elles sont capables d'accder aux proprits d'un bean. En guise de rappel, continuons notre exemple avec la
liste d'aliments, et crons une page test_map.jsp, dans laquelle nous allons implmenter rapidement cette Map d'aliments :
Code : JSP - /test_map.jsp
<%@ page import="java.util.Map, java.util.HashMap" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des Maps et EL</title>
</head>
<body>
<p>
<%
Map<String, String> aliments = new HashMap<String,
String>();
aliments.put( "pomme","fruit" );
aliments.put( "carotte","lgume" );
aliments.put( "boeuf","viande" );
aliments.put( "aubergine","lgume" );
request.setAttribute( "aliments", aliments );
%>
${ aliments.pomme } <br /> <!-- affiche fruit -->
${ aliments.carotte } <br /> <!-- affiche lgume -->
${ aliments.boeuf } <br /> <!-- affiche viande -->
${ aliments.aubergine } <br /><!-- affiche lgume -->
</p>
</body>
</html>

J'utilise ici une scriptlet Java pour initialiser rapidement la Map et la placer dans un attribut de la requte nomm aliments. Ne
prenez bien videmment pas cette habitude, je ne procde ainsi que pour l'exemple et vous rappelle que nous cherchons
liminer le code Java de nos pages JSP ! Rendez-vous alors sur http://localhost:8080/test/test_map.jsp, et observez le bon
affichage des valeurs. Comme je vous l'ai annonc un peu plus tt, j'utilise la notation avec l'oprateur point - ici dans les lignes
18 21 - pour accder aux valeurs contenues dans la Map, mais il est tout fait possible d'utiliser la notation avec les crochets.
D'accord, avec des expressions EL, nous pouvons accder au contenu d'objets de type Map. Mais a, nous le savions
dj Quel est le rapport avec les objets implicites EL ?

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

94/345

Le rapport, c'est que tous ces objets sont des Map, et que par consquent nous sommes capables d'y accder depuis des
expressions EL, de la mme manire que nous venons de parcourir notre Map d'aliments ! Pour illustrer le principe, nous allons
laisser tomber nos fruits et lgumes et crer une page nomme test_obj_impl.jsp, encore et toujours la racine de notre session,
application, et y placer le code suivant :
Code : JSP - /test_obj_impl.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des objets implicites EL</title>
</head>
<body>
<p>
<%
String paramLangue = request.getParameter("langue");
out.println( "Langue : " + paramLangue );
%>
<br />
<%
String paramArticle = request.getParameter("article");
out.println( "Article : " + paramArticle );
%>
</p>
</body>
</html>

Vous reconnaissez aux lignes 10 et 15 la mthode request.getParameter() permettant de rcuprer les paramtres
transmis au serveur par le client travers l'URL. Ainsi, il vous suffit de vous rendre sur http://localhost:8080/test/test_obj_im [...]
r&article=782 pour que votre navigateur vous affiche :

Cherchez maintenant, dans le tableau fourni prcdemment, l'objet implicite EL ddi l'accs aux paramtres de requte
Trouv ? Il s'agit de la Map nomme param. La technologie EL va ainsi vous mettre disposition un objet dont le contenu peut,
dans le cas de notre exemple, tre reprsent sous cette forme :
Nom du paramtre (Cl) Valeur du paramtre (Valeur)
langue

fr

article

782

Si vous avez compris l'exemple avec les fruits et lgumes, alors vous avez galement compris comment accder nos paramtres
de requtes depuis des expressions EL, et vous tes capables de rcrire notre prcdente page d'exemple sans utiliser de code
Java ! ditez votre fichier test_obj_impl.jsp et remplacez le code prcdent par le suivant :
Code : JSP - /test_obj_impl.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test des objets implicites EL</title>
</head>
<body>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

95/345

<p>
Langue : ${ param.langue }
<br />
Article : ${ param.article }
</p>
</body>
</html>

Actualisez la page dans votre navigateur, et observez le mme affichage que dans l'exemple prcdent.
Pratique et lgant, n'est-ce pas ?
D'accord, dans ce cas cela fonctionne bien : chaque paramtre a un nom unique, et est associ une seule valeur
quelconque. Mais qu'en est-il des lignes marques avec ** dans le tableau ? Est-il possible d'associer un unique
paramtre plusieurs valeurs la fois ?
Oui, il est tout fait possible d'associer une cl des valeurs multiples. C'est d'ailleurs tout fait logique, puisque derrire les
rideaux il s'agit tout simplement d'objets de type Map ! L'unique diffrence entre les objets implicites param et paramValues,
ainsi qu'entre header et headerValues, se situe au niveau de la nature de l'objet utilis dans la Map et des valeurs qui y sont
stockes :
pour param et header, une seule valeur est associe chaque nom de paramtre, via une Map<String,String> ;
pour paramValues et headerValues par contre, ce sont plusieurs valeurs qui vont tre associes un mme nom de
paramtre, via une Map<String,String[]>.
Quand pouvons-nous rencontrer plusieurs valeurs pour un seul et mme paramtre ?

Tout simplement en prcisant plusieurs fois un paramtre d'URL avec des valeurs diffrentes ! Par exemple, accdez cette fois la
page de tests avec l'URL http://localhost:8080/test/test_obj_im [...] 782&langue=zh. Cette fois, la technologie EL va vous mettre
disposition un objet dont le contenu peut tre reprsent ainsi :
Nom du paramtre (Cl) Valeur du paramtre (Valeur)
langue

[fr,zh]

article

782

La Map permettant d'accder aux valeur du paramtre langue n'est plus une Map<String,String>, mais une
Map<String,String[]>. Si vous ne modifiez pas le code de l'expression EL dans votre page JSP, alors vous ne pourrez
qu'afficher la premire valeur du tableau des langues, retourne par dfaut lorsque vous utilisez l'expression
${param.langue}.
Afin d'afficher la seconde valeur, il faut cette fois non plus utiliser l'objet implicite param, mais utiliser l'objet implicite nomm
paramValues. Remplacez la ligne 9 de votre fichier test_obj_impl.jsp l'expression ${param.langue} par l'expression
${paramValues.langue[1]}. Actualisez alors la page dans votre navigateur, et vous verrez alors s'afficher la valeur zh !
Le principe est simple : alors qu'auparavant en crivant ${param.langue} vous accdiez directement la String
associe au paramtre langue, cette fois en crivant ${paramValues.langue} vous accdez non plus une
String, mais un tableau de String. Voil pourquoi il est ncessaire d'utiliser la notation avec crochets pour
accder aux diffrents lments de ce tableau !

En l'occurrence, puisque seules deux langues ont t prcises dans l'URL, il n'existe que les lments d'indices 0 et 1 dans le
tableau, contenant les valeurs fr et zh. Si vous essayez d'accder un lment non dfini, par exemple en crivant
${paramValues.langue[4]}, alors l'expression EL dtectera une valeur nulle et n'affichera rien. De mme, vous devez
obligatoirement cibler un des lments du tableau ici. Si vous n'crivez que ${paramValues.langue}, alors l'expression EL
vous affichera la rfrence de l'objet Java contenant votre tableau
Par ailleurs, sachez qu'il existe d'autres cas impliquant plusieurs valeurs pour un mme paramtre. Prenons un exemple HTML trs
simple : un <select> choix multiples !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

96/345

Code : HTML
<form method="post" action="">
<p>
<label for="pays">Dans quel(s) pays avez-vous dj voyag
?</label><br />
<select name="pays" id="pays" multiple="true">
<option value="france">France</option>
<option value="espagne">Espagne</option>
<option value="italie">Italie</option>
<option value="royaume-uni">Royaume-Uni</option>
<option value="canada">Canada</option>
<option value="etats-unis">Etats-Unis</option>
<option value="chine" selected="selected">Chine</option>
<option value="japon">Japon</option>
</select>
</p>
</form>

Alors que via un <select> classique, il n'est possible de choisir qu'une seule valeur dans la liste droulante, dans cet exemple
grce l'option multiple="true", il est tout fait possible de slectionner plusieurs valeurs pour le seul paramtre nomm
pays. Eh bien dans ce genre de cas, l'utilisation de l'objet implicite paramValues est ncessaire galement : c'est le seul moyen de
rcuprer la liste des valeurs associes au seul paramtre nomm pays !
Pour ce qui est de l'objet implicite headerValues par contre, sa relle utilit est discutable. En effet, s'il est possible de dfinir
plusieurs valeurs pour un seul paramtre d'une en-tte HTTP, celles-ci sont la plupart du temps spares par de simples pointvirgules et concatnes dans une seule et mme String, rendant l'emploi de cet objet implicite inutile. Bref, dans 99 % des cas,
utiliser la simple Map header est suffisant. Ci-dessous un exemple d'en-ttes HTTP :
Code : HTTP
GET / HTTP/1.1
Host: www.google.fr
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; enUS; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 ( .NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive

Vous remarquez bien dans cet exemple que chaque paramtre (Host, User-Agent, Accept, etc.) n'est dfini qu'une seule fois, et
que les valeurs sont simplement concatnes les unes la suite des autres sur la mme ligne.

Voil donc la solution notre problme : les objets implicites EL sont des raccourcis qui rendent l'accs aux diffrentes
portes et aux diffrents concepts lis HTTP extrmement pratiques !

Nous allons nous arrter l pour les explications sur les objets implicites, l'important pour le moment est que vous compreniez
bien leur mode de fonctionnement. Ne vous inquitez pas si vous ne saisissez pas l'utilit de chacun d'entre eux, c'est tout fait
normal, certains concepts vous sont encore inconnus. La pratique vous fera prendre de l'aisance, et j'apporterai de plus amples
explications au cas par cas dans les exemples de ce cours. Avant de passer la suite, un petit avertissement quant aux nommage
de vos objets.
Faites bien attention aux noms des objets implicites lists ci-dessus. Il est fortement dconseill de dclarer une
variable portant le mme nom qu'un objet implicite, par exemple param ou cookie. En effet, ces noms sont dj utiliss
pour identifier des objets implicites, et cela pourrait causer des comportements plutt inattendus dans vos pages et
expressions EL. Bref, ne cherchez pas les ennuis : ne donnez pas vos variables un nom dj utilis par un objet

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

97/345

implicite.

Beaucoup de nouvelles notations vous ont t prsentes, prenez le temps de bien comprendre les exemples illustrant
l'utilisation des balises et des expressions. Lorsque vous vous sentez prts, passez avec moi au chapitre suivant, et tentez alors
de rcrire notre prcdente page d'exemple JSP, en y faisant cette fois intervenir uniquement ce que nous venons d'apprendre !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

98/345

Des problmes de vue ?


Passons sur ce subtil jeu de mot, et revenons un instant sur notre premier exemple de page dynamique. Maintenant que nous
connaissons la technologie JSP et les EL, nous sommes capables de remplacer le code Java que nous avions crit en dur dans
notre vue par quelque chose de propre, lisible et qui suit les recommandations MVC !

Nettoyons notre exemple


Pour rappel, voici o nous en tions aprs l'introduction d'un bean dans notre exemple :
Code : JSP - /WEB-INF/test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
<%
String attribut = (String) request.getAttribute("test");
out.println( attribut );

</p>
<p>

String parametre = request.getParameter( "auteur" );


out.println( parametre );
%>

Rcupration du bean :
<%
com.sdzee.beans.Coyote notreBean = (com.sdzee.beans.Coyote)
request.getAttribute("coyote");
out.println( notreBean.getPrenom() );
out.println( notreBean.getNom() );
%>
</p>
</body>
</html>

Avec tout ce que nous avons appris, nous sommes maintenant capables de modifier cette page JSP pour qu'elle ne contienne
plus de langage Java !
Pour bien couvrir l'ensemble des mthodes existantes, divisons le travail en deux tapes : avec des scripts et balises JSP pour
commencer, puis avec des EL.

Avec des scripts et balises JSP


Code : JSP - /WEB-INF/test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
<% String attribut = (String)
request.getAttribute("test"); %>
<%= attribut %>
%>

<% String parametre = request.getParameter( "auteur" );

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE


%>
</p>
<p>

99/345

<%= parametre %>

Rcupration du bean :
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote"
scope="request" />
<jsp:getProperty name="coyote" property="prenom" />
<jsp:getProperty name="coyote" property="nom" />
</p>
</body>
</html>

Vous pouvez remarquer :


l'affichage de l'attribut et du paramtre via la balise d'expression <%= ... %>;
la rcupration du bean depuis la requte via la balise <jsp:useBean> ;
l'affichage du contenu des proprits via les balises <jsp:getProperty>.
Quel est l'objet implicite utilis ici pour rcuprer le bean "coyote" ?

Lorsque vous utilisez l'action :


Code : JSP
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote"
scope="request" />

Celle-ci s'appuie derrire les rideaux sur l'objet implicite request (HttpServletRequest) : elle cherche un bean nomm
"coyote" dans la requte, et si elle n'en trouve pas elle en cre un et l'y enregistre. De mme, si vous aviez prcis "session" ou
"application" dans l'attribut scope de l'action, alors elle aurait cherch respectivement dans les objets session (HttpSession)
et application (ServletContext).
Enfin, lorsque vous ne prcisez pas d'attribut scope :
Code : JSP
<jsp:useBean id="coyote" class="com.sdzee.beans.Coyote" />

Alors l'action s'appuie par dfaut sur l'objet implicite page (this) : elle cherche un bean nomm "coyote" dans la page courante,
et si elle n'en trouve pas elle en cre un et l'y enregistre.
En fin de compte notre exemple est dj bien plus propre qu'avant, mais nous avons toujours besoin de faire appel du code
Java pour rcuprer et afficher nos attribut et paramtre depuis la requte...

Avec des EL
Code : JSP - /WEB-INF/test.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

</p>
<p>

</p>
</body>
</html>

100/345

${test}
${param.auteur}
Rcupration du bean :
${coyote.prenom}
${coyote.nom}

a se passe de commentaires... Vous comprenez maintenant pourquoi je vous ai annonc dans le chapitre prcdent qu'une fois
les EL dcouvertes, vous n'utiliserez plus jamais le reste ?
Leur simplicit d'utilisation est dconcertante, et notre page ne contient dsormais plus une seule ligne de Java !
Pourquoi est-ce que nous n'utilisons aucun objet implicite pour accder aux attributs test et coyote ?

J'ai jusqu' prsent lchement vit ce sujet pour ne pas vous embrouiller, mais cette question mrite effectivement d'tre pose :
comment notre expression EL est-elle capable de trouver nos diffrents objets ? Quand nous avions dcouvert les actions
standards, le problme ne se posait pas car il tait ncessaire de prciser dans quelle porte nous souhaitions rcuprer un objet,
sans quoi l'action cherchait par dfaut dans la porte page...
Eh bien le fonctionnement de la technologie EL est fondamentalement diffrent de celui des actions standards : dans une
expression EL, lorsque vous accdez un objet prsent dans une des quatre portes de votre application, vous n'avez pas
besoin de spcifier l'objet implicite (c'est--dire la porte) auquel vous souhaitez accder. D'ailleurs vous le voyez bien dans notre
exemple, nous n'avons pas crit ${request.test} pour accder l'objet test prsent dans la porte request, ni
${request.coyote.prenom} pour accder au bean coyote prsent lui aussi dans la porte request.
D'ailleurs, si vous aviez fait ainsi... a n'aurait pas fonctionn ! N'oubliez pas, l'objet implicite request ne reprsente pas la porte
request, mais directement l'objet requte en cours d'utilisation. En ralit, le mcanisme de la technologie EL est un peu volu :
une expression est capable de raliser d'elle-mme un parcours automatique des diffrentes portes accessibles la recherche
d'un objet portant le nom prcis, de la plus petite la plus grande porte.
Comment ce mcanisme fonctionne-t-il ?

Vous vous souvenez de l'objet implicite pageContext ? Je vous l'avais prsent comme celui qui donne accs toutes les
portes...
Eh bien concrtement, lorsque vous crivez par exemple l'expression ${test} dans votre JSP, derrire les rideaux le conteneur
va se rendre compte qu'il ne s'agit pas d'un objet implicite mais bien d'un objet de votre cration, et va appeler la mthode
findAttribute() de l'objet PageContext. Et cette mthode va son tour parcourir chacune des portes - page, puis
request, puis session et enfin application - et va retourner le premier objet nomm "test" trouv !
La bonne pratique de dveloppement est de ne jamais donner le mme nom des objets existant dans des portes
diffrentes ! Par exemple, si vous crivez l'expression ${test} pour cibler un objet nomm "test" que vous avez
enregistr en session, alors qu'il existe un autre objet nomm "test" en requte, puisque la porte request sera toujours
parcoure avant la porte session lors de la recherche automatique du mcanisme EL, c'est l'objet enregistr dans la
requte qui vous sera renvoy...

Dans ce cas, comment viter ce parcours automatique et cibler directement une porte ?

Pour cela, il faut utiliser les objets implicites fournis par la technologie EL donnant accs aux attributs existant : pageScope,
requestScope, sessionScope et applicationScope. Ainsi, dans notre prcdent exemple nous aurions trs bien pu crire
${requestScope.test} la place de ${test}, et cela aurait fonctionn tout aussi bien. Lors de l'analyse de l'expression
EL, le conteneur aurait ainsi reconnu l'objet implicite requestScope, et n'aurait pas effectu le parcours des portes : il aurait
directement recherch un objet nomm "test" au sein de la porte request uniquement.
La bonne pratique veut qu'en complment de la rigueur dans le nommage des objets conseille prcdemment, le

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

101/345

dveloppeur prcise toujours la porte qu'il souhaite cibler dans une expression EL. Ainsi pour accder un objet
prsent par exemple dans la porte request, cette pratique recommande non pas d'crire ${test}, mais
${requestScope.test}. En procdant ainsi, le dveloppeur s'assure qu'aucun objet ne sera cibl par erreur.

En ce qui me concerne dans la suite de ce cours, je prendrai toujours garde ne jamais donner le mme nom deux objets
diffrents. Je me passerai donc de prciser la porte dans chacune des expressions EL que j'crirai dans mes exemples, afin de ne
pas les alourdir. Il va de soi que lors du dveloppement d'une vraie application web, je vous recommande de suivre les bonnes
pratiques que je vous ai nonces l'instant.

Qu'en est-il du paramtre "auteur" ?

Notez bien que lorsque vous souhaitez cibler un objet qui n'est pas prsent dans une des quatre portes, il est bien entendu
ncessaire d'expliciter l'objet implicite qui permet d'y accder au sein de l'expression EL. Voil pourquoi pour accder au paramtre
de requte auteur, nous devons bien prciser ${param.auteur}. Si nous avions simplement crit ${auteur}, cela n'aurait
pas fonctionn car le mcanisme de recherche automatique aurait tent de trouver un objet nomm "auteur" dans une des quatre
portes - page, request, session puis application - et n'aurait logiquement rien trouv. Eh oui car en l'occurrence, rappelez-vous
bien qu'un paramtre de requte est diffrent d'un attribut de requte !
Enfin, comprenez bien que je prends ici l'exemple d'un paramtre de requte pour illustrer le principe, mais que ceci est valable
pour tout objet implicite diffrent des quatre portes : param comme nous venons de le voir, mais galement header, cookie,
paramValues, etc.

Compltons notre exemple...


Tout cela se goupille plutt bien pour le moment, oui mais voil... il y a un "mais". Et un gros mme !
Vous ne vous en tes peut-tre pas encore aperus mais les EL, mmes couples des balises JSP, ne permettent pas de mettre
en place tout ce dont nous aurons couramment besoin dans une vue.
Prenons deux exemples pourtant trs simples :
nous souhaitons afficher le contenu d'une liste ou d'un tableau l'aide d'une boucle ;
nous souhaitons afficher un texte diffrent selon que le jour du mois est pair ou impair.
Eh bien a, nous ne savons pas encore le faire sans Java !

Manipulation d'une liste


Reprenons notre exemple, en crant une liste depuis une servlet et en essayant d'afficher son contenu depuis la JSP :
Code : Java - Ajout d'une liste depuis la servlet
...
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Cration et initialisation du message. */
String paramAuteur = request.getParameter( "auteur" );
String message = "Transmission de variables : OK ! " + paramAuteur;
/* Cration du bean et initialisation de ses proprits */
Coyote premierBean = new Coyote();
premierBean.setNom( "Coyote" );
premierBean.setPrenom( "Wile E." );
/* Cration de la liste et insertion de quatre lments */
List<Integer> premiereListe = new ArrayList<Integer>();
premiereListe.add( 27 );
premiereListe.add( 12 );
premiereListe.add( 138 );
premiereListe.add( 6 );

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

102/345

/* Stockage du message, du bean et de la liste dans l'objet


request */
request.setAttribute( "test", message );
request.setAttribute( "coyote", premierBean );
request.setAttribute( "liste", premiereListe );
/* Transmission de la paire d'objets request/response notre JSP
*/
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}

Rien de problmatique ici, c'est encore le mme principe : nous initialisons notre objet, et le stockons dans l'objet requte pour
transmission la JSP. Regardons maintenant comment raliser l'affichage des lments de cette liste :
Code : JSP - Rcupration et affichage du contenu de la liste depuis la JSP
<%@ page import="java.util.List" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
${test}
${param.auteur}
</p>
<p>
Rcupration du bean :
${coyote.prenom}
${coyote.nom}
</p>
<p>
Rcupration de la liste :
<%
List<Integer> liste = (List<Integer>)
request.getAttribute( "liste" );
for( Integer i : liste ){
out.println(i + " : ");
}
%>
</p>
</body>
</html>

Voil quoi nous en sommes rduits : raliser un import avec la directive page, pour pouvoir utiliser ensuite le type List lors de
la rcupration de notre liste depuis l'objet requte, et afficher son contenu via une boucle for. Certes, ce code fonctionne, vous
pouvez regarder le rsultat obtenu depuis votre navigateur. Mais nous savons d'ores et dj que cela va l'encontre du modle
MVC : souvenez-vous, le Java dans une page JSP, c'est mal !

Utilisation d'une condition


Voyons maintenant comment raliser notre second exemple.
Puisque la mise en place d'une condition n'a vraiment rien de passionnant (vous savez tous crire un if !), je profite de
ce petit exemple pour vous faire dcouvrir une API trs utile ds lors que votre projet fait intervenir la manipulation de
dates : JodaTime.
Si vous avez dj programm en Java, vous avez trs certainement dj remarqu ce problme : la manipulation de dates en Java
est horriblement peu intuitive ! Que ce soit via l'objet Date ou via l'objet Calendar, c'est trs dcevant et trs loin de ce que

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

103/345

l'on est en droit d'attendre d'une plate-forme volue comme Java !


Afin de pouvoir utiliser les mthodes et objets de cette API, il vous faut :
1. tlcharger l'archive nomme joda-time-2.1-dist disponible sur cette page, par exemple au format zip ;
2. la dcompresser et y chercher le fichier joda-time-2.1.jar ;
3. l'inclure votre application, en le plaant sous le rpertoire /WEB-INF/lib/ de votre projet (un simple glisser-dposer
depuis votre fichier vers Eclipse suffit, voir copie d'cran ci-dessous).

Mise en place de l'API JodaTime dans un projet Eclipse


Une fois le fichier .jar en place, vous pouvez alors utiliser l'API depuis votre projet.
Code : Java - Rcupration du jour du mois depuis la servlet
...
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Cration et initialisation du message. */
String paramAuteur = request.getParameter( "auteur" );
String message = "Transmission de variables : OK ! " + paramAuteur;
/* Cration du bean et initialisation de ses proprits */
Coyote premierBean = new Coyote();
premierBean.setNom( "Coyote" );
premierBean.setPrenom( "Wile E." );
/* Cration de la liste et insertion de quatre lments */
List<Integer> premiereListe = new ArrayList<Integer>();
premiereListe.add( 27 );
premiereListe.add( 12 );
premiereListe.add( 138 );
premiereListe.add( 6 );
/** On utilise ici la libraire Joda pour manipuler les dates, pour
deux raisons :
* - c'est tellement plus simple et limpide que de travailler avec
les objets Date ou Calendar !
* - c'est (probablement) un futur standard de l'API Java.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

104/345

*/
DateTime dt = new DateTime();
Integer jourDuMois = dt.getDayOfMonth();
/* Stockage du message, du bean, de la liste et du jour du mois
dans l'objet request */
request.setAttribute( "test", message );
request.setAttribute( "coyote", premierBean );
request.setAttribute( "liste", premiereListe );
request.setAttribute( "jour", jourDuMois );
/* Transmission de la paire d'objets request/response notre JSP
*/
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}

Remarquez la facilit d'utilisation de l'API Joda. N'hsitez pas parcourir par vous-mmes les autres objets et mthodes
proposes, c'est d'une simplicit impressionnante.
Code : JSP - Rcupration du jour du mois et affichage d'un message dpendant de sa parit
<%@ page import="java.util.List" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
${test}
${param.auteur}
</p>
<p>
Rcupration du bean :
${coyote.prenom}
${coyote.nom}
</p>
<p>
Rcupration de la liste :
<%
List<Integer> liste = (List<Integer>)
request.getAttribute( "liste" );
for( Integer i : liste ){
out.println(i + " : ");
}
%>
</p>
<p>
Rcupration du jour du mois :
<%
Integer jourDuMois = (Integer) request.getAttribute(
"jour" );
if ( jourDuMois % 2 == 0 ){
out.println("Jour pair : " + jourDuMois);
} else {
out.println("Jour impair : " + jourDuMois);
}
%>
</p>
</body>
</html>

Encore une fois, voil quoi nous en sommes rduits ct JSP : crire du code Java pour faire un simple test sur un entier...

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

105/345

D'autant plus que je ne vous ai ici propos que deux exemples basiques, mais nous pourrions lister bien d'autres fonctionnalits
qu'il serait intressant de pouvoir utiliser dans nos vues, et qui ne nous sont pas accessibles travers la technologie JSP sans
utiliser de scriptlets !
Dans ce cas, comment faire ? Comment ne pas crire de code Java dans nos pages JSP ?

Eh bien des dveloppeurs se sont poss la mme question il y a plus de dix ans dj , et ont imagin la JSTL : une bibliothque
de balises prconues, qui permettent la manire des balises JSP de mettre en place les fonctionnalits dont nous avons besoin
couramment dans une vue, mais qui ne sont pas accessibles nativement au sein de la technologie JSP.

Le point sur ce qu'il nous manque


Avant d'attaquer l'apprentissage de cette fameuse JSTL, prenons deux minutes pour faire le point sur les limites de ce que nous
avons appris jusqu' prsent.

La vue
Nous devons imprativement nettoyer nos lunettes ! Nous savons afficher des choses basiques, mais ds que notre vue se
complexifie un minimum, nous ne savons plus faire. Vous tes dj au courant, c'est vers la JSTL que nous allons nous tourner :
l'intgralit de la partie suivante lui est d'ailleurs consacre.

L'interaction
Vous ne vous en tes peut-tre pas encore rendus compte, mais nous n'avons qu'effleur la rcupration de donnes envoyes
par le client ! Nous devons mettre en place de l'interaction : une application web qui ne demande rien l'utilisateur, c'est un site
statique, et nous ce que nous souhaitons c'est une application dynamique ! Pour le moment, nous avons uniquement dvelopp
des vues basiques, couples des servlets qui ne faisaient presque rien. Trs bientt, nous allons dcouvrir que les servlets
auront pour objectif de TOUT contrler : tout ce qui arrivera dans notre application et tout ce qui en sortira passera par nos
servlets.

Les donnes
Nous devons apprendre grer nos donnes : pour le moment, nous avons uniquement dcouvert ce qu'tait un bean. Nous
avons une vague ide de comment seront reprsentes nos donnes au sein du modle : chaque entit de donnes
correspondra un bean... Toutefois, nous nous heurtons ici de belles inconnues : d'o vont venir nos donnes ? Qu'allons nous
mettre dans nos beans ? Comment allons-nous sauvegarder les donnes qu'ils contiendront ? Comment enregistrer ce que nous
transmet le client ? Nous devrons pour rpondre tout cela apprendre manipuler une base de donnes depuis notre
application. Ainsi, nous allons dcouvrir que notre modle sera en ralit constitu non pas d'une seule couche, mais de deux !
Miam !

Documentation
On n'insistera jamais assez sur l'importance, pour tout zro souhaitant apprendre quoi que ce soit, d'avoir recours aux
documentations et ressources externes en gnral. Le site du zro n'est pas une bible, tout n'y est pas ; pire, des lments sont
parfois volontairement omis ou simplifis afin de bien vous faire comprendre certains points au dtriment d'autres, jugs moins
cruciaux.
Les tutoriaux d'auteurs diffrents vous feront profiter de nouveaux points de vue et angles d'attaque, et les documentations
officielles vous permettront un accs des informations justes et maintenues jour (en principe).

Liens utiles
Base de connaissances portant sur Tomcat et les serveurs d'applications, sur Tomcat's Corner
propos des servlets, sur stackoverflow.com
propos des JSP, sur stackoverflow.com
propos des expressions EL, sur stackoverflow.com
Base de connaissances portant sur les servlets, sur novocode.com
FAQ gnrale propos du dveloppement autour de Java, sur jguru.com
Tutoriel sur les Expression Language, dans la documentation officielle J2EE 1.4 sur sun.com
La syntaxe JSP, sur sun.com

Vous l'aurez compris, cette liste ne se veut pas exhaustive, et je vous recommande d'aller chercher par vous mme l'information

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

106/345

sur les forums et sites du web. En outre, faites bien attention aux dates de cration des documents que vous lisez : les
ressources primes font lgion sur le web, notamment au sujet de la plate-forme Java EE, en constante volution. N'hsitez
pas demander la communaut sur le forum Java du Site du Zro, si vous ne parvenez pas trouver l'information que vous
cherchez.

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

107/345

TP Fil rouge - tape 1


Comme je vous lannonais en avant-propos, vous tes ici pour apprendre crer un projet web, en y ajoutant de la complexit
au fur et mesure que le cours avance. Avec tout ce que vous venez de dcouvrir, vous voici prts pour poser la premire pierre
de l'difice ! Je vous propose, dans cette premire tape de notre TP fil rouge qui vous accompagnera jusqu'au terme de votre
apprentissage, de revoir et appliquer l'ensemble des notions abordes jusqu' prsent.

Objectifs
Contexte
J'ai choisi la thmatique du commerce en ligne comme source d'inspiration : vous allez crer un embryon d'application qui va
permettre la cration et la visualisation de clients et de commandes. C'est la fois assez global pour ne pas impliquer d'lments
qui vous sont encore inconnus, et assez spcifique pour coller avec ce que vous avez appris dans ces chapitres et tes capables
de raliser.
L'objectif premier de cette tape, c'est de vous familiariser avec le dveloppement web sous Eclipse. Vous allez devoir mettre en
place un projet depuis zro dans votre environnement, et y crer vos diffrents fichiers. Le second objectif est de vous faire
prendre de l'aise avec l'utilisation de servlets, de pages JSP et de beans, et de manire gnrale avec le principe gnral d'une
application Java EE.

Fonctionnalits
Cration de client
travers notre petite application, l'utilisateur devra pouvoir crer un client en saisissant des donnes depuis un formulaire, et
visualiser la fiche client en rsultant. Puisque vous n'avez pas encore dcouvert les formulaires, je vais vous fournir cette page
qui vous servira de base. Votre travail sera de coder :
un bean, reprsentant un client ;
une servlet, charge de rcuprer les donnes envoyes par le formulaire, de les enregistrer dans le bean et de les
transmettre une JSP ;
une JSP, charge d'afficher la fiche du client cr, c'est--dire les donnes transmises par la servlet.

Cration de commande
L'utilisateur devra galement pouvoir crer une commande, en saisissant des donnes depuis un formulaire, et visualiser la fiche
en rsultant. De mme ici, puisque vous n'avez pas encore dcouvert les formulaires, je vais vous fournir cette page qui vous
servira de base. Votre travail sera de coder :
un bean, reprsentant une commande ;
une servlet, charge de rcuprer les donnes envoyes par le formulaire, de les enregistrer dans le bean et de les
transmettre une JSP ;
une JSP, charge d'afficher la fiche de la commande cre, c'est--dire les donnes transmises par la servlet.

Contraintes
Comme je viens de vous l'annoncer, vous devez utilisez ces deux formulaires en guise de base pour votre application. Vous les
placerez directement la racine de votre application, sous le rpertoire WebContent d'Eclipse.

Cration de client
Code : JSP - /creerClient.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cration d'un client</title>
<link type="text/css" rel="stylesheet" href="inc/style.css"
/>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

108/345

</head>
<body>
<div>
<form method="get" action="creationClient">
<fieldset>
<legend>Informations client</legend>
<label for="nomClient">Nom <span
class="requis">*</span></label>
<input type="text" id="nomClient"
name="nomClient" value="" size="20" maxlength="20" />
<br />
<label for="prenomClient">Prenom </label>
<input type="text" id="prenomClient"
name="prenomClient" value="" size="20" maxlength="20" />
<br />
<label for="adresseClient">Adresse de livraison
<span class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="" size="20" maxlength="20" />
<br />
<label for="telephoneClient">Numro de tlphone
<span class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="" size="20" maxlength="20" />
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient"
name="emailClient" value="" size="20" maxlength="60" />
<br />
</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br
/>
</form>
</div>
</body>
</html>

Cration de commande
Code : JSP - /creerCommande.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cration d'une commande</title>
<link type="text/css" rel="stylesheet" href="inc/style.css"
/>
</head>
<body>
<div>
<form method="get" action="creationCommande">
<fieldset>
<legend>Informations client</legend>
<label for="nomClient">Nom <span
class="requis">*</span></label>
<input type="text" id="nomClient"
name="nomClient" value="" size="20" maxlength="20" />
<br />

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

109/345

<label for="prenomClient">Prenom </label>


<input type="text" id="prenomClient"
name="prenomClient" value="" size="20" maxlength="20" />
<br />
<label for="adresseClient">Adresse de livraison
<span class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="" size="20" maxlength="20" />
<br />
<label for="telephoneClient">Numro de tlphone
<span class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="" size="20" maxlength="20" />
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient"
name="emailClient" value="" size="20" maxlength="60" />
<br />
</fieldset>
<fieldset>
<legend>Informations commande</legend>
<label for="dateCommande">Date <span
class="requis">*</span></label>
<input type="text" id="dateCommande"
name="dateCommande" value="" size="20" maxlength="20" disabled />
<br />
<label for="montantCommande">Montant <span
class="requis">*</span></label>
<input type="text" id="montantCommande"
name="montantCommande" value="" size="20" maxlength="20" />
<br />
<label for="modePaiementCommande">Mode de
paiement <span class="requis">*</span></label>
<input type="text" id="modePaiementCommande"
name="modePaiementCommande" value="" size="20" maxlength="20" />
<br />
paiement</label>

<label for="statutPaiementCommande">Statut du

<input type="text" id="statutPaiementCommande"


name="statutPaiementCommande" value="" size="20" maxlength="20" />
<br />
<label for="modeLivraisonCommande">Mode de
livraison <span class="requis">*</span></label>
<input type="text" id="modeLivraisonCommande"
name="modeLivraisonCommande" value="" size="20" maxlength="20" />
<br />
la livraison</label>

<label for="statutLivraisonCommande">Statut de

<input type="text" id="statutLivraisonCommande"


name="statutLivraisonCommande" value="" size="20" maxlength="20" />
<br />
</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br
/>
</form>
</div>
</body>
</html>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

110/345

Feuille de style
Voici pour finir une feuille de style que je vous propose d'utiliser pour ce TP. Toutefois, si vous tes motivs vous pouvez trs
bien crer et utiliser vos propres styles, cela n'a pas d'importance.
Code : CSS - /inc/style.css
/* Gnral ------------------------------------------------------------------------------------ */
body, p, legend, label, input {
font: normal 8pt verdana, helvetica, sans-serif;
}
/* Forms -------------------------------------------------------------------------------------- */
fieldset {
padding: 10px;
border: 1px #0568CD solid;
margin: 10px;
}
legend {
font-weight: bold;
color: #0568CD;
}
form label {
float: left;
width: 200px;
margin: 3px 0px 0px 0px;
}
form input {
margin: 3px 3px 0px 0px;
border: 1px #999 solid;
}
form input.sansLabel {
margin-left: 200px;
}
/* Styles et couleurs ------------------------------------------------------------------------- */
.requis {
color: #c00;
}
.erreur {
color: #900;
}
.succes {
color: #090;
}
.info {
font-style: italic;
color: #E8A22B;
}

Conseils
propos des formulaires
www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

111/345

Voici les seules informations que vous devez connatre pour attaquer :
ces deux formulaires sont configurs pour envoyer les donnes saisies vers les adresses /creationClient et
/creationCommande. Lorsque vous mettrez en place vos deux servlets, vous devrez donc effectuer un mapping
respectivement sur chacune de ces deux adresses dans votre fichier web.xml ;
les donnes seront envoyes via la mthode GET du protocole HTTP, vous devrez donc implmenter la mthode
doGet() dans vos servlets ;
le nom des paramtres crs lors de l'envoi des donnes correspond au contenu des attributs "name" de chaque balise
<input> des formulaires. Par exemple, le nom du client tant saisi dans la balise <input name="nomClient"...
/> du formulaire, il sera accessible depuis votre servlet par un appel request.getParameter("nomClient").
Etc.
j'ai volontairement dsactiv le champ de saisie de la date dans le formulaire de cration d'une commande. Nous
intgrerons bien plus tard un petit calendrier permettant le choix d'une date, mais pour le moment nous ferons sans.

Le modle
Vous n'allez travailler que sur deux entits, savoir un client et une commande. Ainsi, deux objets suffiront :
un bean Client reprsentant les donnes rcupres depuis le formulaire creerClient.jsp (nom, prnom, adresse, etc.) ;
un bean Commande reprsentant les donnes rcupres depuis la seconde partie du formulaire creerCommande.jsp
(date, montant, mode de paiement, etc.).
N'hsitez pas relire le chapitre sur les Javabeans pour vous rafrachir la mmoire sur leur structure.
Note 1 : au sujet du type des proprits de vos beans, je vous conseille de toutes les dclarer de type String, sauf le montant
de la commande que vous pouvez ventuellement dclarer de type double.
Note 2 : lors de la cration d'une commande, l'utilisateur va devoir saisir des informations relatives au client. Plutt que de crer
une proprit pour chaque champ relatif au client (nom, prnom, adresse, etc.) dans votre bean Commande, vous pouvez
directement y inclure une proprit de type Client, qui son tour contiendra les proprits nom, prnom, etc..

Les contrleurs
Les deux formulaires que je vous fournis sont paramtrs pour envoyer les donnes saisies au serveur par le biais d'une requte
de type GET. Vous allez donc devoir crer deux servlets, que vous pouvez par exemple nommer CreationClient et
CreationCommande, qui vont pour chaque formulaire :
rcuprer les paramtres saisis, en appelant request.getParameter() sur les noms des diffrents champs ;
les convertir dans le type souhait si certaines des proprits de vos beans ne sont pas des String, puis les enregistrer
dans le bean correspondant ;
vrifier si l'utilisateur a oubli de saisir certains paramtres requis (ceux marqus d'une toile sur le formulaire de saisie) :
si oui, alors transmettre les beans et un message d'erreur une page JSP pour affichage ;
si non, alors transmettre les beans et un message de succs une page JSP pour affichage.
Puisque le champ de saisie de la date est dsactiv, vous allez devoir initialiser la proprit date du bean Commande avec la date
courante. Autrement dit, vous allez considrer que la date d'une commande est simplement la date courante lors de la validation
du formulaire. Vous allez donc devoir rcuprer directement la date courante depuis votre servlet et l'enregistrer au format
String dans le bean.

Les vues
Je vous fournis les deux pages JSP contenant les formulaires de saisie des donnes. Les seules vues que vous avez
dvelopper sont celles qui afficheront les donnes saisies, aprs validation du formulaire. Vous pouvez par exemple les nommer
afficherClient.jsp et afficherCommande.jsp. Elles vont recevoir un ou plusieurs beans et un message depuis leur servlet
respective, et devront afficher les donnes contenues dans ces objets. Vous l'avez probablement dj devin, les expressions EL
sont la solution idale ici !
Vous tes libres au niveau de la mise en forme des donnes et des messages affichs, ce qui importe ce n'est pas le rendu
graphique de vos pages, mais bien leur capacit afficher correctement ce qu'on attend d'elles !

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

112/345

Cration du projet
Avant de vous lcher dans la nature, revenons rapidement sur la mise en place du projet. N'hsitez pas relire le chapitre sur la
configuration d'un projet si vous avez encore des incertitudes ce sujet. Je vous conseille de crer un projet dynamique partir
de zro dans Eclipse, que vous pouvez par exemple nommer tp1, bas sur le serveur Tomcat 7 que nous avons dj mis en place
dans le cadre du cours. Vous devrez alors configurer le build-path comme nous avons appris le faire dans le chapitre sur les
Javabeans. Vous allez par ailleurs devoir manipuler une date lors de la cration d'une commande : je vous encourage pour cela
utiliser la bibliothque JodaTime que nous avons dcouverte dans le chapitre prcdent.
Pour conclure, voici quoi est suppose ressembler l'architecture de votre projet fini si vous avez suivi mes conseils et exemples
de nommage :

Vous pouvez observer en encadr sur cette image le positionnement des trois fichiers dont je vous ai fourni le code.

Illustration du comportement attendu


Voici sous forme d'un schma ce que vous devez raliser dans le cas de la cration d'un client :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

113/345

Je ne vous illustre pas la cration d'une commande, le principe tant trs similaire !

Exemples de rendu du comportement attendu


Cration d'un client
Avec succs :

Saisie de donnes valides dans le

formulaire

Affichage du message de

succs et des donnes


Avec erreur :

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

114/345

Oubli d'un champ obligatoire

dans le formulaire

Affichage du message d'erreur

et des donnes

Cration d'une commande


Avec succs :

Saisie de donnes valides dans

le formulaire

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

115/345

Affichage du message de

succs et des donnes


Avec erreur :

Oubli de champs obligatoires et

saisie d'un montant erron dans le formulaire

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

116/345

Affichage du message d'erreur

et des donnes

Correction
Je vous propose cette solution en guise de correction. Ce n'est pas la seule manire de faire, ne vous inquitez pas si vous avez
procd diffremment, si vous avez nomm vos objets diffremment ou si vous avez bloqu sur certains lments. Le code est
comment et vous est parfaitement accessible : il ne contient que des instructions et expressions que nous avons dj abordes
dans les chapitres prcdents.
Prenez le temps de crer votre projet depuis zro, puis de chercher et coder par vous-mmes. Si besoin, n'hsitez pas
relire le sujet ou retourner lire certains chapitres. La pratique est trs importante, ne vous jetez pas sur la solution
avant d'avoir essay russi !

Le code des beans


Secret (cliquez pour afficher)
Code : Java - com.sdzee.tp.beans.Client
package com.sdzee.tp.beans;
public class Client {
/* Proprits du bean */
private String nom;
private String prenom;
private String adresse;
private String telephone;
private String email;
public void setNom( String nom ) {
this.nom = nom;
}
public String getNom() {
return nom;
}
public void setPrenom( String prenom ) {
this.prenom = prenom;
}

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

117/345

public String getPrenom() {


return prenom;
}
public void setAdresse( String adresse ) {
this.adresse = adresse;
}
public String getAdresse() {
return adresse;
}
public String getTelephone() {
return telephone;
}
public void setTelephone( String telephone ) {
this.telephone = telephone;
}
public void setEmail( String email ) {
this.email = email;
}

public String getEmail() {


return email;
}

Code : Java - com.sdzee.tp.beans.Commande


package com.sdzee.tp.beans;
public class Commande {
/* Proprits du bean */
private Client client;
private String date;
private Double montant;
private String modePaiement;
private String statutPaiement;
private String modeLivraison;
private String statutLivraison;
public Client getClient() {
return client;
}
public void setClient( Client client ) {
this.client = client;
}
public String getDate() {
return date;
}
public void setDate( String date ) {
this.date = date;
}
public Double getMontant() {
return montant;
}

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

118/345

public void setMontant( Double montant ) {


this.montant = montant;
}
public String getModePaiement() {
return modePaiement;
}
public void setModePaiement( String modePaiement ) {
this.modePaiement = modePaiement;
}
public String getStatutPaiement() {
return statutPaiement;
}
public void setStatutPaiement( String statutPaiement ) {
this.statutPaiement = statutPaiement;
}
public String getModeLivraison() {
return modeLivraison;
}
public void setModeLivraison( String modeLivraison ) {
this.modeLivraison = modeLivraison;
}
public String getStatutLivraison() {
return statutLivraison;
}

public void setStatutLivraison( String statutLivraison ) {


this.statutLivraison = statutLivraison;
}

Le code des servlets


Secret (cliquez pour afficher)
Configuration des servlets dans le fichier web.xml :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>CreationClient</servlet-name>
<servlet-class>com.sdzee.tp.servlets.CreationClient</servletclass>
</servlet>
<servlet>
<servlet-name>CreationCommande</servlet-name>
<servlet-class>com.sdzee.tp.servlets.CreationCommande</servletclass>
</servlet>
<servlet-mapping>
<servlet-name>CreationClient</servlet-name>
<url-pattern>/creationClient</url-pattern>
</servlet-mapping>
<servlet-mapping>

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

119/345

<servlet-name>CreationCommande</servlet-name>
<url-pattern>/creationCommande</url-pattern>
</servlet-mapping>
</web-app>

Servlet grant le formulaire de cration de client :


Code : Java - com.sdzee.tp.servlets.CreationClient
package com.sdzee.tp.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import com.sdzee.tp.beans.Client;
public class CreationClient extends HttpServlet {
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException {
/*
* Rcupration des donnes saisies, envoyes en tant que
paramtres de
* la requte GET gnre la validation du formulaire
*/
String nom = request.getParameter( "nomClient" );
String prenom = request.getParameter( "prenomClient" );
String adresse = request.getParameter( "adresseClient" );
String telephone = request.getParameter( "telephoneClient"
);
String email = request.getParameter( "emailClient" );
String message;
/*
* Initialisation du message afficher : si un des champs
obligatoires
* du formulaire n'est pas renseign, alors on affiche un message
* d'erreur, sinon on affiche un message de succs
*/
if ( nom.trim().isEmpty() || adresse.trim().isEmpty() ||
telephone.trim().isEmpty() ) {
message = "Erreur - Vous n'avez pas rempli tous les
champs obligatoires. <br> <a href=\"creerClient.jsp\">Cliquez
ici</a> pour accder au formulaire de cration d'un client.";
} else {
message = "Client cr avec succs !";
}
/*
* Cration du bean Client et initialisation avec les donnes
rcupres
*/
Client client = new Client();
client.setNom( nom );
client.setPrenom( prenom );
client.setAdresse( adresse );
client.setTelephone( telephone );
client.setEmail( email );
/* Ajout du bean et du message l'objet requte */
request.setAttribute( "client", client );
request.setAttribute( "message", message );

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

120/345

/* Transmission la page JSP en charge de l'affichage


des donnes */
this.getServletContext().getRequestDispatcher(
"/afficherClient.jsp" ).forward( request, response );
}
}

Servlet grant le formulaire de cration de commande :


Code : Java - com.sdzee.tp.servlets.CreationCommande
package com.sdzee.tp.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.sdzee.tp.beans.Client;
import com.sdzee.tp.beans.Commande;
public class CreationCommande extends HttpServlet {
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException {
/*
* Rcupration des donnes saisies, envoyes en tant que
paramtres de
* la requte GET gnre la validation du formulaire
*/
String nom = request.getParameter( "nomClient" );
String prenom = request.getParameter( "prenomClient" );
String adresse = request.getParameter( "adresseClient" );
String telephone = request.getParameter( "telephoneClient"
);
String email = request.getParameter( "emailClient" );
/* Rcupration de la date courante */
DateTime dt = new DateTime();
/* Conversion de la date en String selon le format
dfini */
DateTimeFormatter formatter = DateTimeFormat.forPattern(
"dd/MM/yyyy HH:mm:ss" );
String date = dt.toString( formatter );
double montant;
try {
/* Rcupration du montant */
montant = Double.parseDouble( request.getParameter(
"montantCommande" ) );
} catch ( NumberFormatException e ) {
/* Initialisation -1 si le montant n'est pas un
nombre correct */
montant = -1;
}
String modePaiement = request.getParameter(
"modePaiementCommande" );
String statutPaiement = request.getParameter(
"statutPaiementCommande" );

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

121/345

String modeLivraison = request.getParameter(


"modeLivraisonCommande" );
String statutLivraison = request.getParameter(
"statutLivraisonCommande" );
String message;
/*
* Initialisation du message afficher : si un des champs
obligatoires
* du formulaire n'est pas renseign, alors on affiche un message
* d'erreur, sinon on affiche un message de succs
*/
if ( nom.trim().isEmpty() || adresse.trim().isEmpty() ||
telephone.trim().isEmpty() || montant == -1
|| modePaiement.isEmpty() ||
modeLivraison.isEmpty() ) {
message = "Erreur - Vous n'avez pas rempli tous les
champs obligatoires. <br> <a href=\"creerCommande.jsp\">Cliquez
ici</a> pour accder au formulaire de cration d'une commande.";
} else {
message = "Commande cre avec succs !";
}
/*
* Cration des beans Client et Commande et initialisation avec
les
* donnes rcupres
*/
Client client = new Client();
client.setNom( nom );
client.setPrenom( prenom );
client.setAdresse( adresse );
client.setTelephone( telephone );
client.setEmail( email );
Commande commande = new Commande();
commande.setClient( client );
commande.setDate( date );
commande.setMontant( montant );
commande.setModePaiement( modePaiement );
commande.setStatutPaiement( statutPaiement );
commande.setModeLivraison( modeLivraison );
commande.setStatutLivraison( statutLivraison );
/* Ajout du bean et du message l'objet requte */
request.setAttribute( "commande", commande );
request.setAttribute( "message", message );
/* Transmission la page JSP en charge de l'affichage
des donnes */
this.getServletContext().getRequestDispatcher(
"/afficherCommande.jsp" ).forward( request, response );
}
}

Le code des JSP


Secret (cliquez pour afficher)
Page d'affichage d'un client :
Code : JSP - afficherClient.jsp

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

122/345

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Affichage d'un client</title>
<link type="text/css" rel="stylesheet"
href="inc/style.css" />
</head>
<body>
<%-- Affichage de la chaine "message" transmise par la
servlet --%>
<p class="info">${ message }</p>
<%-- Puis affichage des donnes enregistres dans le bean
"client" transmis par la servlet --%>
<p>Nom : ${ client.nom }</p>
<p>Prenom : ${ client.prenom }</p>
<p>Adresse : ${ client.adresse }</p>
<p>Numro de tlphone : ${ client.telephone }</p>
<p>Email : ${ client.email }</p>
</body>
</html>

Page d'affichage d'une commande :


Code : JSP - afficherCommande.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Affichage d'une commande</title>
<link type="text/css" rel="stylesheet"
href="inc/style.css" />
</head>
<body>
<%-- Affichage de la chaine "message" transmise par la
servlet --%>
<p class="info">${ message }</p>
<%-- Puis affichage des donnes enregistres dans le bean
"commande" transmis par la servlet --%>
<p>Client</p>
<%-- Les 5 expressions suivantes accdent aux proprits
du client, qui est lui-mme une proprit du bean commande --%>
<p>Nom : ${ commande.client.nom }</p>
<p>Prenom : ${ commande.client.prenom }</p>
<p>Adresse : ${ commande.client.adresse }</p>
<p>Numro de tlphone : ${ commande.client.telephone
}</p>
<p>Email : ${ commande.client.email }</p>
<p>Commande</p>
<p>Date : ${ commande.date }</p>
<p>Montant : ${ commande.montant }</p>
<p>Mode de paiement : ${ commande.modePaiement }</p>
<p>Statut du paiement : ${ commande.statutPaiement }</p>
<p>Mode de livraison : ${ commande.modeLivraison }</p>
<p>Statut de la livraison : ${ commande.statutLivraison
}</p>
</body>
</html>

Encore une fois prenez votre temps, lisez bien et analysez attentivement les codes. Si jamais vous ne comprenez pas certains

www.siteduzero.com

Partie 2 : Premiers pas avec Java EE

123/345

points, n'hsitez pas me prciser ce qui vous bloque par MP ou dans les commentaires du chapitre !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

124/345

Partie 3 : Une bonne vue grce la JSTL


Aprs une brve introduction sur les objectifs de la JSTL, dcouvrez-ici sa mise en place dans un projet, les bases de sa
bibliothque principale et la manipulation de documents XML.

Objectifs et configuration
Aprs une brve introduction sur quelques concepts intervenant dans la suite de ce cours, et sur les versions de la JSTL,
dcouvrez-ici les fichiers de configuration cls de votre projet ainsi que les paramtres importants modifier pour mettre en place
la bibliothque dans votre projet web Java EE.

C'est sa raison d'tre...


La JSTL est une bibliothque, une collection regroupant des balises implmentant des fonctionnalits des fins gnrales
communes aux applications web. Citons par exemple la mise en place de boucles, de tests conditionnels, le formatage des
donnes ou encore la manipulation de donnes XML. Son objectif est de permettre au dveloppeur d'viter l'utilisation de code
Java dans les pages JSP, et ainsi de respecter au mieux le dcoupage en couche recommand par le modle MVC. En apparence,
ces balises ressemblent comme deux gouttes d'eau aux balises JSP que vous avez dcouvertes dans les chapitres prcdents !
La liste d'avantages que je vous prsente ci-dessous n'est probablement pas exhaustive. Je vais tenter de vous faire comprendre
l'intrt de l'utilisation de balises en vous exposant les aspects positifs qui me semblent les plus importants, et vous illustrer
pourquoi l'utilisation de code Java dans vos pages JSP est dconseille.

Lisibilit du code produit


Un des gros avantages de l'utilisation des balises JSTL, c'est sans aucun doute la lisibilit du code, et donc sa maintenabilit. Un
exemple tant bien plus parlant que des mots, voici une simple boucle dans une JSP en Java d'abord ( base de scriptlet donc), et
via des balises JSTL ensuite. Ne vous inquitez pas de voir apparatre des notations qui vous sont pour le moment inconnues,
les explications viendront par la suite :

Une boucle avec une scriptlet Java


Code : JSP
<%@ page import="java.util.List, java.util.ArrayList" %>
<%
List<Integer> list =
(ArrayList<Integer>)request.getAttribute("tirage");
for(int i = 0; i < list.size();i++){
out.println(list.get(i));
}
%>

Pas besoin de vous faire un dessin : c'est du Java...

La mme boucle avec des tags JSTL


Code : JSP
<c:forEach var="item" items="${tirage}" >
<c:out value="${item}" />
</c:forEach>

La boucle ainsi ralise est nettement plus lisible, ne fait plus intervenir d'attributs et mthodes Java comme size(), get() ou
encore des dclarations de variable ni de types d'objets (List, ArrayList, Date, etc.) , mais uniquement des balises la syntaxe
proche du XML qui ne gnent absolument pas la lecture du code et de la structure de la page.
Pour information, mais vous le saurez bien assez tt, la bibliothque de balises (on parle souvent de tags) ici utilise, indique
par le prfixe c:, est la bibliothque Core, que vous dcouvrirez dans le chapitre suivant.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

125/345

Moins de code crire


Un autre gros avantage de l'utilisation des balises issues des bibliothques standard est la rduction de la quantit de code
crire. En effet, le moins vous aurez crire de code, le moins vous serez susceptible d'introduire des erreurs dans vos pages. La
syntaxe de nombreuses actions est simplifie et raccourcie en utilisant la JSTL, ce qui permet d'viter les problmes dus de
btes fautes de frappe ou d'inattention dans des scripts en Java.
En outre, l'usage des scriptlets (le code Java entour de <% %>) est fortement dconseill, et ce depuis l'apparition des TagLibs
(notamment la JSTL) et des EL, soit depuis une dizaine d'annes maintenant. Les principaux maux dont souffrent les scriptlets
sont :
1. Rutilisation : il est impossible de rutiliser une scriptlet dans une autre page, il faut la dupliquer. Cela signifie que
lorsque vous avez besoin d'effectuer le mme traitement dans une autre page JSP, vous n'aurez pas d'autre choix que de
recopier le morceau de code dans l'autre page, et ce pour chaque page ncessitant ce bout de code. La duplication de
code dans une application est bien entendu l'ennemi du bien : cela compromet normment la maintenance de
l'application.
2. Interface : il est impossible de rendre une scriptlet abstract.
3. POO : il est impossible dans une scriptlet de tirer parti de l'hritage ou de la composition.
4. Debug : si une scriptlet envoie une exception en cours d'excution, tout s'arrte et l'utilisateur rcupre une page
blanche...
5. Tests : on ne peut pas crire de tests unitaires pour tester les scriptlets. Lorsqu'un dveloppeur travaille sur une
application relativement large, il doit s'assurer que ses modifications n'impactent pas le code existant et utilise pour cela
une batterie de tests dits "unitaires", qui ont pour objectif de vrifier le fonctionnement des diffrentes mthodes
implmentes. Eh bien ceux-ci ne peuvent pas s'appliquer au code Java crit dans une page JSP : l encore, cela
compromet normment la maintenance et l'volutivit de l'application.
6. Maintenance : inluctablement, il faut passer normment plus de temps maintenir un code mlang, encombr,
dupliqu et non testable !

titre informatif, la maison mre Oracle elle-mme recommande dans ses JSP coding conventions d'viter l'utilisation de code
Java dans une JSP autant que possible, notamment via l'utilisation de balises :
Citation : Extrait des conventions de codage JSP
Where possible, avoid JSP scriptlets whenever tag libraries provide equivalent functionality. This makes pages easier to
read and maintain, helps to separate business logic from presentation logic, and will make your pages easier to evolve
[...]

Vous avez dit MVC ?


Ne plus crire de Java directement dans vos JSP
Vous l'avez probablement remarqu dans les exemples prcdents : le Java complique normment la lecture d'une page JSP.
Alors certes, ici je ne vous ai prsent qu'une gentille petite boucle, donc la diffrence n'est pas si flagrante. Mais imaginez que
vous travailliez sur un projet de plus grande envergure, mettant en jeu des pages HTML avec un contenu autrement plus riche,
voire sur un projet dans le cadre duquel vous n'tes pas l'auteur des pages que vous avez maintenir ou modifier : que
prfreriez-vous aborder ? Sans aucune hsitation, lorsque les balises JSTL sont utilises, la taille des pages est fortement
rduite et leurs comprhension et maintenance s'en retrouvent grandement facilites.

Rendre la Vue son vrai rle


Soyez bien conscients d'une chose : je ne vous demande pas de proscrire le Java de vos pages JSP juste pour le plaisir des yeux
!
Si je vous encourage procder ainsi, c'est pour vous faire prendre de bonnes habitudes : la vue, en l'occurrence nos JSP, ne
doit se consacrer qu' l'affichage. Ne pas avoir dclarer de mthodes dans une JSP, ne pas modifier directement des donnes
depuis une JSP, ne pas y insrer de traitement mtier... Tout cela est recommand, mais la frontire peut paratre bien mince si on
se laisse aller utiliser des scriptlets Java ds que l'occasion s'en prsente. Avec les tags JSTL, la sparation est bien plus nette.
Un autre point positif, qui ne vous concerne pas vraiment si vous ne travaillez pas en entreprise sur des projets de grande

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

126/345

envergure, est que le modle MVC permet une meilleure sparation des couches de l'application. Par exemple, imaginez une
application dont le code Java est bien cach dans la couche mtier (au hasard, dans des beans) : le(s) programmeur(s) UI trs
performant(s) en interface utilisateur peu(ven)t donc se baser sur la simple documentation du code mtier pour travailler sur la
couche de prsentation en crant les vues, les JSP donc, et ce sans avoir crire ni lire de Java, langage qu'ils ne maitrisent pas
aussi bien, voire pas.

retenir
Si vous ne deviez retenir qu'une phrase de tout cela, c'est que bafouer MVC en crivant du code Java directement dans une JSP
rend la maintenance d'une application extrmement complique, et par consquent rduit fortement son volutivit. Libre vous
par consquent de dcider de l'avenir que vous souhaitez donner votre projet, en suivant ou non les recommandations.
Dernire couche : on crit du code Java directement dans une JSP uniquement lorsqu'il nous est impossible de faire
autrement, ou lorsque l'on dsire vrifier un fonctionnement via une simple feuille de tests, et enfin pourquoi pas
lorsque l'on souhaite rapidement crire un prototype temporaire afin de se donner une ide du fonctionnement d'une
application de trs faible envergure. Voil, j'espre que maintenant vous l'avez bien assimil, ce n'est pas faute de vous
l'avoir rpt...

Plusieurs versions
La JSTL a fait l'objet de plusieurs versions :
JSTL 1.0 pour la plate-forme J2EE 3, et un conteneur JSP 1.2 (ex: Tomcat 4) ;
JSTL 1.1 pour la plate-forme J2EE 4, et un conteneur JSP 2.0 (ex: Tomcat 5.5) ;
JSTL 1.2, qui est partie intgrante de le plateforme Java EE 6, avec un conteneur JSP 2.1 ou 3.0 (ex: Tomcat 6 et 7).
Les diffrences entre ces versions se traduisent principalement par le conteneur JSP ncessaire. Le changement majeur retenir
dans le passage de la premire version la seconde version de ce conteneur, c'est la gestion des EL. Le conteneur JSP 1.2 sur
lequel est base la JSTL 1.0 ne grait pas les EL, cette dernire proposait donc deux implmentations pour pallier ce manque : une
interprtant les EL et l'autre non. Ceci se traduisait alors par l'utilisation d'adresses diffrentes lors de la dclaration des
bibliothques.
La version 1.1 est base sur le conteneur JSP 2.0, qui intgre nativement un interprteur d'EL, et ne propose par consquent plus
qu'une seule implmentation.
Ce tutoriel se base quant lui sur la version actuelle, savoir la JSTL 1.2, qui d'aprs le site officiel apporte des EL "unifies",
ainsi qu'une meilleure intgration dans le framework JSF. Ces changements par rapport la prcdente version n'ont aucun
impact sur ce cours : tout ce qui suit sera valable, que vous souhaitiez utiliser la version 1.1 ou 1.2 de la JSTL.

Configuration
Configuration de la JSTL
Il y a plusieurs choses que vous devez savoir ici. Plutt que de vous donner tout de suite les solutions aux problmes qui vous
attendent, fonons ttes baisses, et je vous guiderai lorsque cela s'avrera ncessaire. On apprend toujours mieux en faisant
des erreurs et en apprenant les corriger, qu'en suivant btement une srie de manipulations.

D'erreur en erreur...
Allons-y gaiement donc, et tentons navement d'insrer une balise JSTL ni vu ni connu dans notre belle et vierge page JSP :
Code : JSP - Une balise JSTL dans notre page
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
<title>Test</title>
</head>
<body>
<c:out value="test" />
</body>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

127/345

</html>

Pour le moment, cette notation vous est inconnue, nous y reviendrons en temps voulu. Vous pouvez d'ores et dj constater que
cette balise a une syntaxe trs similaire celle des actions standard JSP. Pour votre information seulement, il s'agit ici d'un tag
JSTL issu de la bibliothque Core, permettant d'afficher du texte dans une page. Relativement basique donc...
Basique, sur le principe oui. Mais Eclipse vous signale alors une premire erreur :

tag

inconnu
Il ne connait visiblement pas cette balise. Et pour cause : puisqu'il est issu d'une bibliothque (la JSTL), il est ncessaire de
prciser Eclipse o ce tag est rellement dfini ! Et si vous avez suivi la partie prcdente de ce cours, vous devez vous
souvenir d'une certaine directive JSP, destine inclure des bibliothques... Cela vous revient ? Tout juste, c'est la directive
taglib que nous allons utiliser ici. Voici donc notre code modifi pour inclure la bibliothque Core :
Code : JSP - Ajout de la directive taglib
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
<title>Test</title>
</head>
<body>
<c:out value="test" />
</body>
</html>

tudions cette directive :


dans le paramtre uri se trouve le lien vers la dfinition de la bibliothque. Remarquez bien ici l'arborescence de ce lien :
/jsp/jstl/core. Si vous travailliez sur des codes qui ne sont pas de vous, vous serez ventuellement amens rencontrer
dans cette balise un lien de la forme /jstl/core : sachez que ce type de lien est celui de la version antrieure 1.0 de la JSTL.
En effet, le dossier jsp a t rajout afin d'viter toute ambigut avec les prcdentes versions, qui comme je vous l'ai
prcis en premire partie ne graient pas les EL. Faites bien attention utiliser le bon lien selon la version de la JSTL que
vous souhaitez utiliser, sous peine de vous retrouver avec des erreurs peu comprhensibles...
dans le paramtre prefix se trouve l'alias qui sera utilis dans notre page JSP pour faire appel aux balises de la
bibliothque en question. Concrtement, cela signifie que si je souhaite appeler le tag if de la bibliothque Core, je dois
crire <c:if>. Si j'avais entr "core" dans le champ prefix de la directive au lieu de "c", je devrais alors crire
<core:if>.
L, je suppose que vous vous apprtez me jeter des bches. En effet, s'il est vrai qu'Eclipse vous signalait une alerte
auparavant, vous vous retrouvez maintenant avec une nouvelle erreur en plus de la prcdente !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

128/345

bibliotheque introuvable
Effectivement, nouvelle erreur. Pourquoi ?

Eh bien cette fois, c'est Tomcat qui est en cause ! Lorsque je vous avais prsent Tomcat, je vous avais bien prcis qu'il n'tait
pas un serveur d'applications Java EE au sens complet du terme. Nous voil devant une premire illustration de cet tat de fait :
alors que la JSTL fait partie intgrante de la plate-forme Java EE 6, Tomcat 7 n'est par dfaut pas livr avec la JSTL. Si vous
utilisez par exemple le serveur Glassfish d'Oracle, qui quant lui respecte bien les spcifications Java EE, vous ne rencontrerez
pas de problme : la JSTL y est bien incluse.
La lumire tant faite sur l'origine de cette erreur, il est temps de la corriger. Maintenant que nous avons prcis la dfinition de
notre bibliothque, il faut dfinir quelque part o se situe physiquement cette bibliothque, et donc configurer notre projet afin
qu'il puisse accder ses fichiers sources. Si vous tes un peu curieux et que vous vous souvenez de ce que nous avons d
faire pour utiliser l'API JodaTime dans la partie prcdente, vous avez probablement dj remarqu que dans le dossier /WEBINF de votre projet, il y a un dossier nomm... lib !
Le chemin semble donc tout trac, nous devons aller chercher notre bibliothque. O la trouver ? J'y reviendrai dans le chapitre
suivant, la JSTL contient nativement plusieurs bibliothques, et Core est l'une d'entre elles. Par consquent, c'est l'archive jar de
la JSTL tout entire que nous allons devoir ajouter notre projet. Vous pouvez tlcharger le jar jstl-1.2.jar en cliquant sur ce
lien de tlchargement direct. Vous voil donc en possession du fichier que vous allez devoir copier dans votre rpertoire lib :

Ajout du jar JSTL notre projet Eclipse

a commence bien faire, nous tournons en rond ! Nous avons inclus notre bibliothque, mais nous avons toujours
nos deux erreurs !
Que s'est-il pass ?
Pas d'inquitude, nous apercevons le bout du tunnel... Effectivement, Eclipse vous crie toujours dessus. Mais ce n'est cette fois
que pure illusion !
Note : la raison pour laquelle Eclipse ne met pas directement ses avertissements jour, je n'en suis pas vraiment certain.
J'imagine que l'environnement a besoin d'une modification postrieure la mise en place des bibliothques pour prendre en
compte compltement la modification. Bref, modifiez simplement votre page JSP, en y ajoutant un simple espace ou ce que vous
voulez, et sauvez. Comme par magie, Eclipse cesse alors de vous crier dessus !
Il ne vous reste plus qu' dmarrer votre Tomcat si ce n'est pas dj fait, et vrifier que tout se passe bien, en accdant votre
JSP depuis votre navigateur : http://localhost:8080/TestJSTL/test.jsp. Le mot "test" devrait alors s'afficher :
flicitations, vous venez de mettre en place et utiliser avec succs votre premier tag JSTL !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

129/345

Si vous ne parvenez toujours pas faire fonctionner votre page, reprenez attentivement et dans l'ordre chaque tape
prsente ci-dessus, et si malgr cette relecture vous restez sur un chec, dirigez-vous vers le forum Java du site pour y
exposer votre problme en dtail.
Dans le prochain chapitre, nous allons aborder la bibliothque principale de la JSTL, trs justement nomme Core.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

130/345

La bibliothque Core
Nous voici prts tudier la bibliothque Core, offrant des balises pour les principales actions ncessaires dans la couche
prsentation d'une application web. Ce chapitre va en quelque sorte faire office de documentation : je vais vous y prsenter les
principales balises de la bibliothque, et expliciter leur rle et comportement via des exemples simples.
Lorsque ces bases seront poses, nous appliquerons ce que nous aurons dcouvert ici dans un TP. S'il est vrai que l'on ne peut
se passer de la thorie, pratiquer est galement indispensable si vous souhaitez assimiler et progresser.

Les variables et expressions


Pour commencer, nous allons apprendre comment afficher le contenu d'une variable ou d'une expression, et comment grer une
variable et sa porte. Avant cela, je vous donne ici la directive JSP ncessaire pour permettre l'utilisation des balises de la
bibliothque Core dans vos pages :
Code : JSP
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

Cette directive devra tre prsente sur chacune des pages de votre projet utilisant les balises JSTL que je vous prsente dans ce
chapitre. Dans un prochain chapitre, nous verrons comment il est possible de ne plus avoir se soucier de cette commande. En
attendant, ne l'oubliez pas !

Affichage d'une expression


La balise utilise pour l'affichage est <c:out value="" />. Le seul attribut obligatoirement requis pour ce tag est value.
Cet attribut peut contenir une chane de caractres simple, ou une expression EL. Voici quelques exemples :
Code : JSP
<c:out value="test" /> <%-- Affiche test --%>
<c:out value="${ 'a' < 'b' }" /> <%-- Affiche true --%>

A celui-ci s'ajoutent deux attributs optionnels :


default : permet de dfinir une valeur affiche par dfaut si le contenu de l'expression value est vide.
escapeXml : permet de remplacer les caractres de scripts < , > , " , ' et & par leurs quivalents en code html &lt;, &gt;,
&#034;, &#039;, &amp;. Cette option est active par dfaut, et vous devez expliciter <c:out ...
escapeXml="false" /> pour la dsactiver.
Pourquoi utiliser une balise pour afficher simplement du texte ou une expression ?

C'est une question lgitime. Aprs tout c'est vrai, pourquoi ne pas directement crire le texte ou l'expression dans notre page JSP
? Pourquoi s'embter inclure le texte ou l'expression dans cette balise ? Eh bien la rponse se trouve dans l'explication de
l'attribut optionnel escapeXml : celui-ci est activ par dfaut ! Cela signifie que l'utilisation de la balise <c:out /> permet
d'chapper automatiquement les caractres spciaux de nos textes et rendus d'expressions, et c'est l une excellente raison
d'utilisation (voir ci-dessous l'avertissement concernant les failles XSS).
Voici des exemples d'utilisation de l'attribut default :
Code : JSP
<%-- Cette balise affichera le mot 'test' si le bean n'existe pas :
--%>
<c:out value="${bean}">
test
</c:out>
<%-- Elle peut galement s'crire sous cette forme : --%>
<c:out value="${bean}" default="test" />

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

131/345

<%-- Et il est interdit d'crire : --%>


<c:out value="${bean}" default="test">
une autre chaine
</c:out>

Pour le dernier cas, l'explication est simple : l'attribut default jouant dj le rle de valeur par dfaut, le corps du tag ne peut
exister que lorsqu'aucune valeur par dfaut n'est dfinie. Pour information, Eclipse vous signalera une erreur si vous tentez
d'crire la balise sous cette forme.
Pour en finir avec cette balise, voici un exemple d'utilisation de l'attribut escapeXml :
Code : JSP
<%-- Sans prciser d'attribut escapeXml : --%>
<c:out value="<p>Je suis un 'paragraphe'.</p>" />
<%-- La balise affichera : --%>
&lt;p&gt;Je suis un &#039;paragraphe&#039;.&lt;/p&gt;
<%-- Et en prcisant l'attribut false :--%>
<c:out value="<p>Je suis un 'paragraphe'.</p>" escapeXml="false" />
<%-- La balise affichera : --%>
<p>Je suis un 'paragraphe'.</p>

Vous pouvez constater dans cet exemple l'importance de l'activation par dfaut de l'option escapeXml : elle empche
l'interprtation de ce qui est affich par le navigateur, en modifiant les lments de code HTML prsents dans le contenu trait
(en l'occurrence les caractres <, > et ').
Vous devez prendre l'habitude d'utiliser ce tag JSTL lorsque vous affichez des variables, notamment lorsqu'elles sont rcupres
depuis le navigateur, c'est--dire lorsqu'elle sont saisies par l'utilisateur. Prenons l'exemple d'un formulaire :
Code : JSP
<%-- Mauvais exemple --%>
<input type="text" name="donnee"
value="${donneeSaisieParUnUtilisateur}" />
<%-- Bon exemple --%>
<input type="text" name="donnee" value="<c:out
value="${donneeSaisieParUnUtilisateur}"/>" />

Les donnes rcupres depuis un formulaire sont potentiellement dangereuses, puisqu'elles permettent des attaques de type
XSS ou d'injection de code. L'utilisation du tag <c:out/> permet d'chapper les caractres spciaux responsables de cette
faille, et ainsi de prvenir tout risque ce niveau. Nous reviendrons en dtails sur cette faille dans le chapitre sur les formulaires.

Gestion d'une variable


Avant de parler variable, revenons sur leur porte ! La porte (ou visibilit) d'une variable correspond concrtement l'endroit
dans lequel elle est stocke, et par corolaire aux endroits depuis lesquels elle est accessible. Selon la porte affecte votre
variable, elle sera par exemple accessible depuis toute votre application, ou seulement depuis une page particulire, etc. Il y a
quatre portes diffrentes (ou scopes en anglais), que vous connaissez dj et redcouvrirez au fur et mesure des exemples de
ce chapitre :
la page : les objets crs avec la porte page ne sont accessibles que depuis cette mme page, et une fois la rponse
retourne au navigateur ces donnes ne sont plus accessibles.
la requte : les objets crs avec la porte request ne sont accessibles que depuis les pages qui traitent cette mme
requte. Si la requte est transmise une autre page, les donnes sont conserves, mais sont perdues en cas de
redirection.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

132/345

la session : les objets crs avec la porte session ne sont accessibles que depuis les pages traitant les requtes cres
dans cette mme session. Concrtement, une session correspond la dure pendant laquelle un visiteur va utiliser
l'application, cette dure se terminant lorsque l'utilisateur ferme son navigateur ou encore lorsque l'application le dcide
(le dveloppeur, pour tre exact), par exemple via un lien de dconnexion ou encore un temps maximum de validit impos
aprs lequel la session sera automatiquement dtruite. Les donnes ainsi cres ne sont plus accessibles une fois que le
visiteur quitte le site.
l'application : les objets crs avec la porte application sont accessibles depuis toutes les pages JSP de l'application
web ! C'est en quelque sorte une variable globale, accessible partout.

Cration
La balise utilise pour la cration d'une variable est <c:set />. Abordons pour commencer la mise en place d'un attribut dans
la requte. En JSP/servlets, vous savez tous faire a, mais qu'en est-il avec la JSTL ? Il suffit d'utiliser les trois attributs suivants :
var, value et scope.
Code : JSP
<%-- Cette balise met l'expression "Salut les zros !" dans
l'attribut "welcomeMessage" de la requte : --%>
<c:set var="welcomeMessage" value="Salut les zros !"
scope="request" />
<%-- Et est l'quivalent du scriplet Java suivant : --%>
<% request.setAttribute( "welcomeMessage", "Salut les zros !" ); %>

L'attribut var contient le nom de la variable que l'on veut stocker, value sa valeur, et scope la porte de cette variable. Simple,
rapide et efficace ! Voyons maintenant comment rcuprer cette valeur pour l'afficher l'utilisateur, par exemple :
Code : JSP
<%-- Affiche l'expression contenue dans la variable "welcomeMessage"
de la requte --%>
<c:out value="${requestScope.welcomeMessage}" />

Vous remarquerez que nous utilisons ici dans l'EL l'objet implicite requestScope, qui permet de rechercher un objet dans
la porte requte uniquement. Les plus avertis d'entre vous ont peut-tre tent d'accder la valeur frachement cre
via un simple <c:out value="${ welcomeMessage }"/>. Et effectivement, dans ce cas cela fonctionne
galement. Pourquoi ?
Nous retrouvons ici une illustration du mcanisme dont je vous ai parl lorsque nous avons appliqu les EL dans notre code
d'exemple : par dfaut, si le terme de l'expression n'est ni un type primitif (int, char, boolean, etc.) ni un objet implicite de la
technologie EL, l'expression va d'elle-mme chercher un attribut correspondant ce terme dans les diffrentes portes de votre
application : page, puis request, puis session et enfin application.
Souvenez-vous, je vous avais expliqu que c'est grce l'objet implicite pageContext que le mcanisme parcourt toutes les
portes, et qu'il renvoie alors automatiquement le premier objet trouv lors de son parcours. Voil donc pourquoi cela fonctionne
avec la seconde criture : puisque nous ne prcisons pas de porte, l'expression EL les parcourt automatiquement une par une
jusqu' ce qu'elle trouve un objet nomm welcomeMessage, et nous le renvoie !
N'oubliez pas : la bonne pratique veut que vous ne donniez pas le mme nom deux variables diffrentes, prsentes
dans des portes diffrentes. Toutefois, afin d'viter toute confusion si jamais des variables aux noms identiques
venaient coexister, il est galement conseill de n'utiliser la seconde criture que lorsque que vous souhaitez faire
rfrence des attributs de porte page, et d'utiliser la premire criture que je vous ai prsente pour le reste (session,
request et application).

Modification
La modification d'une variable s'effectue de la mme manire que sa cration. Ainsi, le code suivant crera une variable nomme

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

133/345

"maVariable" si elle n'existe pas dj, et initialisera son contenu "12" :


Code : JSP
<%-- L'attribut scope n'est pas obligatoire. Rappelez-vous, le scope
par dfaut est dans ce cas la page,
puisque c'est le premier dans la liste des scopes parcourus --%>
<c:set var="maVariable" value="12" />

Pour information, il est galement possible d'initialiser une variable en utilisant le corps de la balise, plutt qu'en utilisant
l'attribut value :
Code : JSP
<c:set var="maVariable"> 12 </c:set>

ce sujet, sachez d'ailleurs qu'il est possible d'imbriquer d'autres balises dans le corps de cette balise, et pas seulement d'utiliser
de simples chanes de caractres ou expressions. Voici par exemple comment vous pourriez initialiser la valeur d'une variable de
session depuis une valeur lue dans un paramtre de l'URL :
Code : JSP
<c:set var="locale" scope="session">
<c:out value="${param.lang}" default="FR"/>
</c:set>

Plusieurs points importants ici :


vous constatez bien ici l'utilisation de la balise <c:out/> l'intrieur du corps de la balise <c:set/>.
vous pouvez remarquer l'utilisation de l'objet implicite param, pour rcuprer la valeur du paramtre de la requte nomm
lang ;
si le paramtre lang n'existe pas ou s'il est vide, c'est la valeur par dfaut "FR" spcifie dans notre balise <c:out/> qui
sera utilise pour initialiser notre variable en session.

Modification des proprits d'un objet


Certains d'entre vous se demandent probablement comment il est possible de dfinir ou modifier une valeur particulire lorsqu'on
travaille sur certains types d'objets... Et ils ont bien raison ! En effet, avec ce que je vous ai prsent pour le moment, vous tes
capables de dfinir une variable de n'importe quel type, type qui est dfini par l'expression que vous crivez dans l'attribut value
du tag <c:set/> :
Code : JSP
<%-- Cre un objet de type String --%>
<c:set scope="session" var="description" value="Je suis une loutre."
/>
<%-- Cre un objet du type du bean ici spcifi dans l'attribut
'value'--%>
<c:set scope="session" var="tonBean" value="${monBean}" />

Et c'est ici que vous devez vous poser la question suivante : comment modifier les proprits du bean cr dans cet exemple ? En
effet, il vous manque deux attributs pour y parvenir ! Regardons donc de plus prs quels sont ces attributs, et comment ils
fonctionnent :
target : contient le nom de l'objet dont la proprit sera modifie ;

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

134/345

property : contient le nom de la proprit qui sera modifie.


Code : JSP
<!-- Dfinir ou modifier la proprit 'prenom' du bean 'coyote' -->
<c:set target="${coyote}" property="prenom" value="Wile E."/>
<!-- Dfinir ou modifier la proprit 'prenom' du bean 'coyote' via
le corps de la balise -->
<c:set target="${coyote}" property="prenom">
Wile E.
</c:set>
<!-- Passer null la valeur de la proprit 'prenom' du bean
'coyote' -->
<c:set target="${coyote}" property="prenom" value="${null}" />

Remarquez dans le dernier exemple qu'il suffit d'utiliser une EL avec pour mot-cl null dans l'attribut value pour faire passer la
valeur d'une proprit null. Pour information, lorsque l'objet trait n'est pas un bean mais une simple Map, cette action a pour
effet de directement supprimer l'entre de la Map concerne : le comportement est alors identique avec la balise prsente dans le
paragraphe suivant.

Suppression
Dernire tape : supprimer une variable. Une balise est ddie cette tche, avec pour seul attribut requis var. Par dfaut
toujours, c'est le scope page qui sera parcouru si l'attribut scope n'est pas explicit :
Code : JSP
<%-- Supprime la variable "maVariable" de la session --%>
<c:remove var="maVariable" scope="session" />

Voil dj un bon morceau de fait ! Ne soyez pas abattus si vous n'avez pas tout compris lorsque nous avons utilise des objets
implicites. Nous y reviendrons de toute manire au fur et mesure que nous en aurons besoin dans nos exemples, et vous
comprendrez alors avec la pratique.

Les conditions
Une condition simple
La JSTL fournit deux moyens d'effectuer des tests conditionnels. Le premier, simple et direct, permet de tester une seule
expression, et correspond au bloc if() du langage Java. Le seul attribut obligatoire est test.
Code : JSP
<c:if test="${ 12 > 7 }" var="maVariable" scope="session">
Ce test est vrai.
</c:if>

Ici, le corps de la balise est une simple chane de caractres. Elle ne sera affiche dans la page finale que si la condition est vraie,
savoir si l'expression contenue dans l'attribut test renvoie true. Ici, c'est bien entendu le cas, 12 est bien suprieur 7.
Les attributs optionnels var et scope ont ici sensiblement le mme rle que dans la balise <c:set/>. Le rsultat du test
conditionnel sera stock dans la variable et dans le scope dfini, et sinon dans le scope page par dfaut. L'intrt de cette
utilisation rside principalement dans le stockage des rsultats de tests coteux, un peu la manire d'un cache, afin de pouvoir
les rutiliser en accdant simplement des variables de scope.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

135/345

Des conditions multiples


La seconde mthode fournie par la JSTL est utile pour traiter les conditions mutuellement exclusives, quivalentes en Java une
suite de if() / else if() ou au bloc switch(). Elle est en ralit constitue de plusieurs balises :
Code : JSP
<c:choose>
<c:when test="${expression}">Action ou texte.</c:when>
...
<c:otherwise>Autre action ou texte.</c:otherwise>
</c:choose>

La balise <c:choose/> ne peut contenir aucun attribut, et son corps ne peut contenir qu'une ou plusieurs balise(s)
<c:when/> et une ou zro balise <c:otherwise/>.
La balise <c:when/> ne peut exister qu' l'intrieur d'une balise <c:choose/>. Elle est l'quivalent du mot-cl case en Java,
dans un bloc switch(). Tout comme la balise <c:if/>, elle doit obligatoirement se voir dfinir un attribut test contenant la
condition. l'intrieur d'un mme bloc <c:choose/>, un seul <c:when/> verra son corps valu, les conditions tant
mutuellement exclusives.
La balise <c:otherwise/> ne peut galement exister qu' l'intrieur d'une balise <c:choose/>, et aprs la dernire balise
<c:when/>. Elle est l'quivalent du mot-cl default en Java, dans un bloc switch(). Elle ne peut contenir aucun attribut, et
son corps ne sera valu que si aucune des conditions la prcdant dans le bloc n'est vrifie.
Voil pour les conditions avec la JSTL. Je ne pense pas qu'il soit ncessaire de prendre plus de temps ici, la principale diffrence
avec les conditions en Java tant la syntaxe utilise.

Les boucles
Abordons prsent la question des boucles. Dans la plupart des langages, les boucles ont une syntaxe similaire : for, while,
do/while... Avec la JSTL, deux choix vous sont offerts, en fonction du type d'lment que vous souhaitez parcourir avec votre
boucle : <c:forEach/> pour parcourir une collection, et <c:forTokens/> pour parcourir une chane de caractres.

Boucle "classique"
Prenons pour commencer une simple boucle for en scriptlet Java, affichant un rsultat format dans un tableau HTML par
exemple :
Code : JSP - Une boucle sans la JSTL
<%-- Boucle calculant le cube des entiers de 0 7 et les affichant
dans un tableau HTML --%>
<table>
<tr>
<th>Valeur</th>
<th>Cube</th>
</tr>
<%
int[] cube= new int[8];
/* Boucle calculant et affichant le cube des entiers de 0 7 */
for(int i = 0 ; i < 8 ; i++)
{
cube[i] = i * i * i;
out.println("<tr><td>" + i + "</td> <td>" + cube[i] +
"</td></tr>");
}
%>
</table>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

136/345

Avec la JSTL, si l'on souhaite raliser quelque chose d'quivalent, il faudrait utiliser la syntaxe suivante :
Code : JSP - Une boucle avec la JSTL
<%-- Boucle calculant le cube des entiers de 0 7 et les affichant
dans un tableau HTML --%>
<table>
<tr>
<th>Valeur</th>
<th>Cube</th>
</tr>
<c:forEach var="i" begin="0" end="7" step="1">
<tr>
<td><c:out value="${i}"/></td>
<td><c:out value="${i * i * i}"/></td>
</tr>
</c:forEach>
</table>

Avant tout, on peut dj remarquer la clart du second code en comparaison avec le premier : les balises JSTL s'intgrent trs
bien au formatage HTML englobant les rsultats. On devine rapidement ce que produira cette boucle, ce qui tait bien moins
vident avec le code en Java, pourtant tout aussi basique. tudions donc les attributs de cette fameuse boucle :
begin : la valeur de dbut de notre compteur (la valeur de i dans la boucle en Java, initialis zro en l'occurrence).
end : la valeur de fin de notre compteur. Vous remarquez ici que la valeur de fin est 7 et non pas 8, comme c'est le cas dans
la boucle Java. La raison est simple : dans la boucle Java en exemple j'ai utilis une comparaison stricte (i strictement
infrieur 8), alors que la boucle JSTL ne procde pas par comparaison stricte (i infrieur ou gal 7). J'aurais certes pu
crire i <= 7 dans ma boucle Java, mais je n'ai par contre pas le choix dans ma boucle JSTL, c'est uniquement ainsi.
Pensez-y, c'est une erreur bte mais facile commettre si l'on oublie ce comportement.
step : c'est le pas d'incrmentation de la boucle. Concrtement, si vous changez cette valeur de 1 3 par exemple, alors le
compteur de la boucle ira de 3 en 3 et non plus de 1 en 1. Par dfaut, si vous ne spcifiez pas l'attribut step, la valeur 1
sera utilise.
var : cette attribut est, contrairement ce qu'on pourrait croire a priori, non obligatoire. Si vous ne le spcifiez pas, vous
ne pourrez simplement pas accder la valeur du compteur en cours (via la variable i dans notre exemple). Vous pouvez
choisir de ne pas prciser cet attribut si vous n'avez pas besoin de la valeur du compteur l'intrieur de votre boucle. Par
ailleurs, tout comme en Java lorsqu'on utilise une syntaxe quivalente l'exemple prcdent (dclaration de l'entier i
l'intrieur du for), la variable n'est accessible qu' l'intrieur de la boucle, autrement dit dans le corps de la balise
<c:forEach/>.
Vous remarquerez bien videmment que l'utilisation de tags JSTL dans le corps de la balise est autoris : nous utilisons ici dans
cet exemple l'affichage via des balises <c:out/>.
Voici, mais cela doit vous paratre vident, le code HTML produit par cette page JSP :
Code : HTML
<table>
<tr>
<th>Valeur</th>
<th>Cube</th>
</tr>
<tr>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>8</td>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

137/345

</tr>
<tr>
<td>3</td>
<td>27</td>
</tr>
<tr>
<td>4</td>
<td>64</td>
</tr>
<tr>
<td>5</td>
<td>125</td>
</tr>
<tr>
<td>6</td>
<td>216</td>
</tr>
<tr>
<td>7</td>
<td>343</td>
</tr>
</table>

Itration sur une collection


Passons maintenant quelque chose de plus intressant et utilis dans la cration de pages web : les itrations sur les
collections. Si ce terme ne vous parle pas, c'est que vous avez besoin d'un bonne piqre de rappel en Java ! Et ce n'est pas moi
qui vous la donnerai, si vous en sentez le besoin, allez faire un tour sur ce chapitre du tuto de Java.
La syntaxe utilise pour parcourir une collection est similaire celle d'une boucle simple, sauf que cette fois, un attribut items est
requis. Et pour cause, c'est lui qui indiquera la collection parcourir. Imaginons ici que nous souhaitions raliser l'affichage de
news sur une page web. Imaginons pour cela que nous ayons disposition un ArrayList ici nomm maListe, contenant
simplement des HashMap. Chaque HashMap ici contiendra le titre d'une news et son contenu. Nous souhaitons alors parcourir
cette liste afin d'afficher ces informations dans une page web :
Code : JSP
<%@ page import="java.util.*" %>
<%
/* Cration de la liste et des donnes */
List<HashMap<String, String>> maListe = new
ArrayList<HashMap<String, String>>();
HashMap<String, String> news = new HashMap<String, String>();
news.put("titre", "Titre de ma premire news");
news.put("contenu", "corps de ma premire news");
maListe.add(news);
news = new HashMap<String, String>();
news.put("titre", "Titre de ma seconde news");
news.put("contenu", "corps de ma seconde news");
maListe.add(news);
pageContext.setAttribute("maListe", maListe);
%>
<c:forEach items="${maListe}" var="news">
<div class="news">
<div class="titreNews">
<c:out value="${news['titre']}" />
</div>
<div class="corpsNews">
<c:out value="${news['contenu']}" />
</div>
</div>
</c:forEach>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

138/345

Je sens que certains vont m'attendre au tournant... Eh oui, j'ai ici utilis du code Java ! Et du code sale en plus ! Mais attention
ne pas vous y mprendre : je n'ai recours du code Java ici que pour l'exemple, afin de vous procurer un moyen simple et rapide
pour initialiser des donnes de test, et afin de vrifier le bon fonctionnement de notre boucle.
Il va de soi que dans une vraie application web, ces donnes seront initialises correctement, et non pas salement
comme je l'ai fait ici. Qu'elles soient rcupres depuis une base de donnes, depuis un fichier, voire codes en dur
dans la couche mtier de votre application, ces donnes ne doivent jamais et en aucun cas, je rpte elles ne doivent
jamais et en aucun cas, tre initialises directement depuis vos JSP. Le rle d'une page JSP, je le rappelle, c'est de
prsenter l'information, un point c'est tout. Ce n'est pas pour rien que la couche dans laquelle se trouve les JSP
sappelle la couche de prsentation.

Revenons notre boucle : je n'ai ici pas encombr la syntaxe, en utilisant les seuls attributs items et var. Le premier indique la
collection sur laquelle la boucle porte, en l'occurrence notre List nomm maListe, et le second indique quant lui le nom de la
variable qui sera lie llment courant de la collection parcourue par la boucle, que j'ai ici de manire trs originale nomme
"news", nos HashMap contenant... des news. Ainsi, pour accder respectivement aux titre et contenu de nos news, il suffit via
des crochets de prciser les lments viss dans notre map : ${news['titre']} et ${news['contenu']}. Les lignes
contenant des lments importants sont les lignes 16, 19 et 22 dans le code prcdent.
Voici le rendu HTML de cet exemple :
Code : HTML
<div class="news">
<div class="titreNews">
Titre de ma premire news
</div>
<div class="corpsNews">
corps de ma premire news
</div>
</div>
<div class="news">
<div class="titreNews">
Titre de ma seconde news
</div>
<div class="corpsNews">
corps de ma seconde news
</div>
</div>

Les attributs prsents prcdemment lors de l'tude d'une boucle simple sont l aussi valables : si vous souhaitez par exemple
n'afficher que les dix premires news sur votre page, vous pouvez limiter le parcours de votre liste aux dix premiers lments ainsi
:
Code : JSP
<c:forEach items="${maListe}" var="news" begin="0" end="9">
...
</c:forEach>

Si les attributs begin et end spcifis dpassent le contenu rel de la collection, par exemple si vous voulez afficher les
dix premiers lments d'une liste mais qu'elle n'en contient que trois, la boucle s'arrtera automatiquement lorsque le
parcours de la liste sera termin, peu importe l'indice end spcifi.

Simple, n'est-ce pas ?


titre d'information, voici enfin les diffrentes collections sur lesquelles il est possible d'itrer avec la boucle <c:forEach/>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

139/345

de la bibliothque Core :
java.util.Collection ;
java.util.Map ;
java.util.Iterator ;
java.util.Enumeration ;
Array d'objets ou de types primitifs ;
(Chanes de caractres spares par des sparateurs dfinis.)
Si j'ai mis entre parenthses le dernier lment, c'est parce qu'il est dconseill d'utiliser cette boucle pour parcourir une chane de
caractres dont les lments sont spars par des caractres sparateurs dfinis. Voyez le paragraphe suivant pour en savoir
plus ce sujet.
Enfin, sachez qu'il est galement possible d'itrer directement sur le rsultat d'une requte SQL. Je n'aborderai cependant
volontairement pas ce cas, pour deux raisons :
je ne vous ai pas encore prsent la bibliothque sql de la JSTL, permettant d'effectuer des requtes SQL depuis vos JSP
;
je vous prsenterai pas la bibliothque sql de la JSTL, ne souhaitant pas vous voir effectuer des requtes SQL depuis
vos JSP !

L'attribut varStatus
Il reste un attribut que je n'ai pas encore voqu, et qui est comme les autres utilisables pour tout type d'itrations, que ce soit
sur des entiers ou sur des collections : l'attribut varStatus. Tout comme l'attribut var, il est utilis pour crer une variable de
scope, mais prsente une diffrence majeure : alors que var permet de stocker la valeur de l'index courant ou l'lment courant de
la collection parcourue, le varStatus permet de stocker un objet LoopTagStatus, qui dfinit un ensemble de proprits
dfinissant l'tat courant d'une itration :
Proprit

Description

begin

La valeur de l'attribut begin.

end

La valeur de l'attribut end.

step

La valeur de l'attribut step.

first

Boolen prcisant si l'itration courante est la premire.

last

Boolen prcisant si l'itration courante est la dernire.

count

Compteur d'itrations (commence 1).

index

Index d'itrations (commence 0).

current

lment courant de la collection parcourue.

Reprenons l'exemple utilis prcdemment, mais cette fois-ci mettant en jeu lattribut varStatus :
Code : JSP
<c:forEach items="${maListe}" var="news" varStatus="status">
<div class="news">
News n <c:out value="${status.count}"/> :
<div class="titreNews">
<c:out value="${news['titre']}" />
</div>
<div class="corpsNews">
<c:out value="${news['contenu']}" />
</div>
</div>
</c:forEach>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

140/345

J'ai ici utilis la proprit count de l'attribut varStatus, et l'affiche ici simplement en tant que numro de news. Cet exemple est
simple, mais suffit vous faire comprendre comment utiliser cet attribut : il suffit d'appeler directement une proprit de l'objet
varStatus, que j'ai ici de manire trs originale nomm... status.
Pour terminer, sachez enfin que l'objet cr par cet attribut varStatus n'est visible que dans le corps de la boucle, tout comme
l'attribut var.

Itration sur une chane de caractres


Une variante de la boucle <c:forEach/> existe, spcialement ddie aux chanes de caractres. La syntaxe est presque
identique :
Code : JSP
<p>
<%-- Affiche les diffrentes sous-chanes spares par une virgule
ou un point-virgule --%>
<c:forTokens var="sousChaine" items="salut; je suis un,gros;zro+!"
delims=";,+">
${sousChaine}<br/>
</c:forTokens>
</p>

Un seul attribut apparat : delims. C'est ici que l'on doit spcifier quels sont les caractres qui serviront de sparateurs dans la
chane que la boucle parcourra. Il suffit de les spcifier les uns la suite des autres, comme c'est le cas ici dans notre exemple.
Tous les autres attributs vus prcdemment peuvent galement s'appliquer ici (begin, end, step...).
Le rendu HTML de ce dernier exemple est donc :
Code : HTML
<p>
salut<br/>
je suis un<br/>
gros<br/>
zero<br/>
!<br/>
</p>

Ce que la JSTL ne permet pas (encore) de faire


Il est possible en Java d'utiliser les commandes break et continue pour sortir d'une boucle en cours de parcours. Eh bien
sachez que ces fonctionnalits ne sont pas implmentes dans la JSTL. Il est par consquent la plupart du temps impossible de
sortir d'une boucle en cours d'itration.
Il existe dans certains cas des moyens plus ou moins efficaces de sortir d'une boucle, via l'utilisation de conditions <c:if />
notamment. Quant aux cas d'itrations sur des collections, la meilleure solution si le besoin de sortir en cours de boucle se fait
ressentir est de dporter le travail de la boucle dans une classe Java. Pour rsumer, ce genre de situations se rsout au cas par
cas, selon vos besoins. Mais n'oubliez pas, votre vue doit se consacrer l'affichage uniquement : si vous sentez que vous avez
besoin de fonctionnalits qui n'existent pas dans la JSTL, il y a de grandes chances pour que vous soyez en train de trop en
demander votre vue, et ventuellement de bafouer MVC !

Les liens
Liens
La balise <c:url/> a pour objectif de gnrer des URL. En lisant ceci, j'imagine que vous vous demandez ce qu'il peut bien y
avoir de particulier grer dans la cration d'une URL ! Dans une page HTML simple, lorsque l'on cre un lien on se contente en

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

141/345

effet d'crire directement l'adresse au sein de la balise <a> :


Code : HTML
<a href="url">lien</a>

Dans ce cas, qu'est-ce qui peut motiver le dveloppeur utiliser la balise <c:url/> ?

Eh bien vous devez savoir qu'en ralit, un adresse n'est pas qu'une simple chane de caractres, elle est soumise plusieurs
contraintes.
Voici les trois fonctionnalits associes la balise :
ajouter le nom du contexte aux URL absolues ;
rcrire l'adresse pour la gestion des sessions (si les cookies sont dsactivs ou absents, par exemple) ;
encoder les noms et contenus des paramtres de l'URL.
L'attribut value contient logiquement l'adresse, et l'attribut var permet comme pour les tags vus auparavant de stocker le rsultat
dans une variable. Voici un premier jeu d'exemples :
Code : JSP
<%-- Gnre une url simple, positionne dans un lien HTML --%>
<a href="<c:url value="test.jsp" />">lien</a>
<%-- Gnre une url et la stocke dans la variable lien --%>
<c:url value="test.jsp" var="lien" />

Reprenons maintenant les trois proprits en dtail, et analysons leur fonctionnement.

1. Ajout du contexte
Lorsqu'une URL est absolue, c'est--dire lorsqu'elle fait rfrence la racine de l'application et commence par le caractre / , le
contexte de l'application sera par dfaut ajout en dbut d'adresse. Ceci est principalement d au fait que lors du dveloppement
d'une application, le nom du contexte importe peu et on y crit souvent un nom par dfaut, faute de mieux. Il n'est gnralement
choisi dfinitivement que lors du dploiement de l'application, qui intervient en fin de cycle.
Lors de l'utilisation d'adresses relatives, pas de soucis puisqu'elles ne font pas rfrence au contexte, et pointeront quoi qu'il
arrive vers le rpertoire courant. Mais pour les adresses absolues, pointant la racine, sans cette fonctionnalit il serait
ncessaire d'crire en dur le contexte de l'application dans les URL lors du dveloppement, et de toutes les modifier si le contexte
est chang par la suite lors du dploiement. Vous comprenez donc mieux l'intrt d'un tel systme.
Code : JSP
<%-- L'url absolue ainsi gnre --%>
<c:url value="/test.jsp" />
<%-- Sera rendue ainsi dans la page web finale si le contextPath est
"Test" --%>
/Test/test.jsp
<%-- Et une url relative ainsi gnre --%>
<c:url value="test.jsp" />
<%-- Ne sera pas modifie lors du rendu --%>
test.jsp

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

142/345

2. Gestion des sessions


Si le conteneur JSP dtecte un cookie stockant l'identifiant de session dans le navigateur de l'utilisateur, alors aucune
modification ne sera apporte l'URL. Par contre, si ce cookie est absent, les URL gnres via la balise <c:url/> seront
rcrites pour intgrer l'identifiant de session en question. Regardez ces exemples, afin de bien visualiser la forme de ce
paramtre :
Code : JSP
<%-- L'url ainsi gnre --%>
<c:url value="test.jsp" />
<%-- Sera rendue ainsi dans la page web finale,
si le cookie est prsent --%>
test.jsp
<%-- Et sera rendue sous cette forme si le cookie est absent --%>
test.jsp;jsessionid=A6B57CE08012FB431D

Ainsi, via ce systme une application Java EE ne dpendra pas de l'activation des cookies du ct utilisateur. Ne vous inquitez
pas si vous ne saisissez pas le principe ici, nous reviendrons sur cette histoire de cookies et de sessions plus tard. Pour le
moment, essayez simplement de retenir que la balise <c:url/> est quipe pour leur gestion automatique !

3. Encodage
En utilisant la balise <c:url/>, les paramtres que vous souhaitez passer cette URL seront encods : les caractres spciaux
qu'ils contiennent ventuellement vont tre transforms en leurs codes HTML respectifs. Toutefois, il ne faut pas faire de
confusion ici : ce sont seulement les paramtres (leur nom et contenu) qui seront encods, le reste de l'URL ne sera pas modifi
. La raison de ce comportement est de pouvoir assurer la compatibilit avec l'action standard d'inclusion <jsp:include/>,
qui ne sait pas grer une URL encode.
D'accord, mais comment faire pour passer des paramtres ?

Pour transmettre proprement des paramtres une URL, une balise particulire existe : <c:param/>. Elle ne peut exister que
dans le corps des balises <c:url/>, <c:import/> ou <c:redirect/>. Elle se prsente sous cette forme, et est assez
intuitive :
Code : JSP
<c:url value="/monSiteWeb/countZeros.jsp">
<c:param name="nbZeros" value="${countZerosBean.nbZeros}"/>
<c:param name="date" value="22/06/2010"/>
</c:url>

L'attribut name contient donc le nom du paramtre, et value son contenu. C'est en ralit cette balise ici fille de la balise
<c:url/> qui se charge de l'encodage des paramtres, et non directement la balise <c:url/>. Retenez enfin qu'une telle
balise ne peut exister qu'entre deux balises d'URL, de redirection ou d'import, et qu'il est possible d'en utiliser autant que
ncessaire.
Code : JSP
<%-- Une URL gnre de cette manire --%>
<a href="<c:url value="/monSiteWeb/test.jsp">
<c:param name="date" value="22/06/2010"/>
<c:param name="donnees" value="des donnes contenant des c@r#ct%res bi&a**es..."
</c:url>">Lien HTML</a>

<%-- Sera rendue ainsi dans la page web finale --%>


<a href="/test/monSiteWeb/test.jsp?
date=22%2f06%2f2010&donnees=des+donn%e9es+contenant+des+c%40r%23ct%25res+bi%26a**es..."

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

143/345

HTML</a>

Vous voyez bien dans cet exemple que :


les caractres spciaux contenus dans les paramtres de l'URL ont t transforms : / est devenu % 2f , est devenu
% e9, etc.
les caractres & sparant les diffrents paramtres, qui font quant eux partie intgrante de l'URL, n'ont pas t modifis
en leur code HTML &amp; .
Si vous travaillez sur une page XML ou une page XHTML stricte, alors vous devez savoir qu'afin de respecter les
normes qui rgissent ces technologies, il est impratif d'encoder proprement l'URL. Cela dit, je viens de vous expliquer
que la balise <c:url/> n'effectue pas cette opration, elle ne s'occupe que des paramtres... Par consquent, vous
devrez transformer vous-mmes les caractres spciaux, comme le & sparant les paramtres d'une URL, en leur code
HTML quivalent (en l'occurrence, & doit devenir &amp; pour que la syntaxe soit valide). Si vous avez bien suivi,
vous savez qu'il est possible d'effectuer ces transformations l'aide de la balise <c:out/> !

Pour rsumer
Rcapitulons tout cela avec un exemple assez complet :
Code : JSP
<%-- L'url avec paramtres ainsi gnre --%>
<c:url value="/monSiteWeb/countZeros.jsp">
<c:param name="nbZeros" value="123"/>
<c:param name="date" value="22/06/2010"/>
</c:url>
<%-- Sera rendue ainsi dans la page web finale,
si le cookie est prsent et le contexte est Test --%>
/Test/monSiteWeb/countZeros.jsp?nbZeros=123&date=22%2f06%2f2010
<%-- Et sera rendue sous cette forme si le cookie est absent --%>
/Test/monSiteWeb/countZeros.jsp;jsessionid=A6B57CE08012FB431D?
nbZeros=123&date=22%2f06%2f2010

Vous pouvez ici observer :


la mise en place de paramtres via <c:param/> ;
l'ajout automatique du contexte en dbut de l'URL absolue ;
l'encodage automatique des paramtres (ici les caractres / dans la date sont transforms en %2f) ;
le non-encodage de l'URL (le caractre & sparant les paramtres n'est pas transform) ;
l'ajout automatique de l'identifiant de session. Remarquez d'ailleurs ici sa prsence avant les paramtres de la requte, et
non aprs.

Redirection
La balise <c:redirect/> est utilise pour envoyer un message de redirection HTTP au navigateur de l'utilisateur. Si elle
ressemble l'action <jsp:forward/>, il existe toutefois une grosse diffrence, qui rside dans le fait qu'elle va entraner un
changement de l'URL dans le navigateur de l'utilisateur final, contrairement <jsp:forward/> qui est quant elle
transparente du point de vue de l'utilisateur (l'URL dans la barre de navigation du navigateur n'est pas modifie).
La raison de cette diffrence de comportement est simple : le forwarding se fait ct serveur, contrairement la redirection qui
elle est effectue par le navigateur. Cela limite par consquent la porte de l'action de forwarding , qui puisqu'excute ct
serveur est limite aux pages prsentes dans le contexte de la servlet utilise. La redirection tant elle excute ct client, rien ne
vous empche de rediriger l'utilisateur vers n'importe quelle page web.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

144/345

Au final, le forwarding est plus performant, ne ncessitant pas d'aller/retour passant par le navigateur de l'utilisateur final, mais il
est moins flexible que la redirection. De plus, utiliser le forwarding impose certaines contraintes : concrtement, l'utilisateur
final n'est pas au courant que sa requte a t redirige vers une ou plusieurs servlets ou JSP diffrentes, puisque l'URL qui
est affiche dans son navigateur ne change pas. En d'autres termes, cela veut dire que l'utilisateur ne sait pas si le contenu qu'il
visualise dans son navigateur a t produit par la page qu'il a appel via l'URL d'origine, ou par une autre page vers laquelle la
premire servlet ou JSP appele a effectu un forwarding ! Ceci peut donc poser problme si l'utilisateur rafrachit la page par
exemple, puisque cela appellera nouveau la servlet ou JSP d'origine... Sachez enfin que lorsque vous utilisez le forwarding , le
code prsent aprs cette instruction dans la page n'est pas excut.
Bref, je vous conseille pour dbuter d'utiliser la redirection via la balise <c:redirect/> plutt que l'action standard JSP, cela
vous vitera bien des ennuis. Voyons pour terminer quelques exemples d'utilisation :
Code : JSP
<%-- Forwarding avec l'action standard JSP --%>
<jsp:forward url="/monSiteWeb/erreur.jsp">
<%-- Redirection avec la balise redirect --%>
<c:redirect url="http://www.siteduzero.com"/>
<%-- Les attributs valables pour <c:url/> le sont aussi pour la
redirection.
Ici par exemple, l'utilisation de paramtres --%>
<c:redirect url="http://www.siteduzero.com">
<c:param name="mascotte" value="zozor"/>
<c:param name="langue" value="fr"/>
</c:redirect>
<%-- Redirigera vers --%>
http://www.siteduzero.com?mascotte=zozor&langue=fr

Imports
La balise <c:import/> est en quelque sorte un quivalent <jsp:include/>, mais qui propose plus d'options, et pallie
ainsi les manques de l'inclusion standard.
L'attribut url est le seul paramtre obligatoire lors de l'utilisation de cette balise, et il dsigne logiquement le fichier importer :
Code : JSP
<%-- Copie le contenu du fichier cibl dans la page actuelle --%>
<c:import url="exemple.html"/>

Un des avantages majeurs de la fonction d'import est qu'elle permet d'utiliser une variable pour stocker le flux rcupr, et ne
propose pas simplement de l'inclure dans votre JSP comme c'est le cas avec <jsp:include/>. Cette fonctionnalit est
importante, puisqu'elle permet d'effectuer des traitements sur les pages importes. L'attribut utilis pour ce faire est nomm
varReader. Nous reverrons cela en dtails lorsque nous dcouvrirons la bibliothque xml de la JSTL, o ce systme prend toute
son importance lorsqu'il s'agit de lire et de parser des fichiers XML :
Code : JSP
<%-- Copie le contenu d'un fichier xml dans une variable
(fileReader),
puis parse le flux rcupr dans une autre variable (doc). --%>
<c:import url="test.xml" varReader="fileReader">
<x:parse var="doc" doc="${fileReader}" />
</c:import>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

145/345

Ne vous inquitez pas si la ligne <x:parse var="doc" doc="${fileReader}" /> vous est inconnue, c'est une
balise de la bibliothque xml de la JSTL, que je vous prsenterai dans le chapitre suivant. Vous pouvez cependant retenir
l'utilisation du <c:import/> pour rcuprer un flux xml.
Note : le contenu du varReader utilis, autrement dit la variable dans laquelle est stocke le contenu de votre fichier,
n'est accessible qu' l'intrieur du corps de la balise d'import, entre les tags <c:import> et </c:import>. Il n'est
par consquent pas possible de s'en servir en dehors. Dans le chapitre portant sur la bibliothque xml, nous
dcouvrirons un autre moyen, permettant de pouvoir travailler sur le contenu du fichier en dehors de l'import, au
travers d'une variable de scope.

De la mme manire que la redirection en comparaison avec le forwarding , <c:import/> permet d'inclure des pages
extrieures au contexte de votre servlet ou votre serveur, contrairement l'action standard JSP. Voyons une nouvelle fois
quelques exemples d'utilisation :
Code : JSP
<%-- Inclusion d'une page avec l'action standard JSP. --%>
<jsp:include page="index.html" />
<%-- Importer une page distante dans une variable
Le scope par dfaut est ici page si non prcis. --%>
<c:import url="http://www.siteduzero.com/zozor/biographie.html"
var="bio" scope="page"/>
<%-- Les attributs valables pour <c:url/> le sont aussi pour la
redirection.
Ici par exemple, l'utilisation de paramtres --%>
<c:import url="footer.jsp">
<c:param name="design" value="bleu"/>
</c:import>

Au terme de ce chapitre, vous devez tre capable de transformer des scriptlets Java contenant variables, boucles et conditions
en une jolie page JSP base sur des tags JSTL.
Testez maintenant vos connaissances dans le TP qui suit ce chapitre !
Sachez avant de continuer que d'autres bibliothques de base existent, la JSTL ne contenant en ralit pas une bibliothque mais
cinq ! Voici une brve description des quatre autres :
fmt : destine au formatage et au parsage des donnes. Permet notamment la localisation de l'affichage.
fn : destine au traitement de chanes de caractres.
sql : destine l'interaction avec une base de donnes. Celle-ci ne trouve pour moi son sens que dans une petite
application standalone, ou une feuille de tests. En effet, le code ayant trait au stockage des donnes dans une
application web Java EE suivant le modle MVC doit tre masqu de la vue, et tre encapsul dans le modle,
ventuellement dans une couche ddie (voir le modle de conception DAO pour plus d'information ce sujet). Bref, je
vous laisse parcourir par vous-mmes les liens de documentation si vous souhaitez en faire usage dans vos projets. En
ce qui nous concerne, nous suivons MVC la lettre et je ne souhaite clairement pas vous voir toucher aux donnes de la
base directement depuis vos pages JSP... Une fois n'est pas coutume, le premier que je vois coder ainsi, je le pends un
arbre !
xml : destine au traitement de fichiers et donnes XML. l'instar de la bibliothque sql, celle-ci trouve difficilement sa
place dans une application MVC, ces traitements ayant bien souvent leur place dans des objets du modle, et pas dans la
vue. Cela dit, dans certains cas elle peut s'avrer trs utile, ce format tant trs rpandu dans les applications et
communications web : c'est pour cela que j'ai dcid d'en faire l'objet du prochain chapitre !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

146/345

JSTL core : exercice d'application


La bibliothque Core n'a maintenant plus de secrets pour vous. Mais si vous souhaitez vous familiariser avec toutes ces
nouvelles balises et tre l'aise lors du dveloppement de pages JSP, vous devez vous entrainer !
Je vous propose ici un petit exercice d'application qui met en jeu des concepts ralisables l'aide des balises que vous venez de
dcouvrir. Suivez le guide...

Les bases de l'exercice


Pour mener bien ce petit exercice, commencez par crer un nouveau projet web nomm jstl_exo1. Rfrez-vous au premier
chapitre de cette partie si vous avez encore des hsitations sur la dmarche ncessaire. Configurez bien entendu ce projet en y
intgrant la JSTL, afin de pouvoir utiliser nos chres balises dans nos pages JSP !
Une fois ceci fait, crez une premire page JSP la racine de votre application, sous le rpertoire WebContent. Je vous en donne
ici le contenu complet :
Code : JSP - initForm.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>
Initialisation des donnes
</title>
</head>
<body>
<form method="post" action="initProcess.jsp">
<p>
<label for="nom">Entrez ici votre nom de famille
:</label><br />
<input type="text" name="nom" id="nom" tabindex="10" />
</p>
<p>
<label for="prenom">Entrez ici votre prnom :</label><br />
<input type="text" name="prenom" id="prenom" tabindex="20"
/>
</p>
<p>
<label for="pays">Dans quel(s) pays avez-vous dj voyag
?</label><br />
<select name="pays" id="pays" multiple="multiple"
tabindex="30">
<option value="France">France</option>
<option value="Espagne">Espagne</option>
<option value="Italie">Italie</option>
<option value="Royaume-uni">Royaume-Uni</option>
<option value="Canada">Canada</option>
<option value="Etats-unis">Etats-Unis</option>
<option value="Chine">Chine</option>
<option value="Japon">Japon</option>
</select>
</p>
<p>
<label for="autre">Entrez ici les autres pays que vous avez
visits, spars par une virgule :</label><br />
<textarea id="autre" name="autre" rows="2" cols="40"
tabindex="40" placeholder="Ex: Norvge, Chili, NouvelleZlande"></textarea>
</p>
<p>
<input type="submit" value="Valider" /> <input type="reset"
value="Remettre zro" />
</p>
</form>
</body>
</html>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

147/345

Rcapitulons rapidement la fonction de cette page :


permettre l'utilisateur de saisir son nom ;
permettre l'utilisateur de saisir son prnom ;
permettre l'utilisateur de choisir les pays qu'il a visits parmi une liste de choix par dfaut ;
permettre l'utilisateur de saisir d'autres pays qu'il a visit, en les sparant par une virgule.
Voici le rendu, rempli avec des donnes de test :

Formulaire du TP Core.

Votre mission maintenant, c'est d'crire la page initProcess.jsp qui va se charger de traiter les donnes saisies dans la page
contenant le formulaire.
Nous n'avons pas encore tudi le traitement des formulaires en Java EE, mais ne paniquez pas. Ce que je vous demande de crer
ici a pour unique objectif de vous faire manipuler la JSTL. En effet, vous savez que les donnes envoyes par le client sont
accessibles travers les paramtres de requtes, avec la JSTL et les EL vous avez tout en main pour mettre en place ce petit
exercice !
Ne vous inquitez pas, nous apprendrons dans la partie suivante de ce cours comment grer proprement les formulaires
dans une application Java EE.
Le sujet est ici volontairement simple, et son utilit nulle. L'objectif est purement didactique ici, l'intrt est de vous familiariser
avec le dveloppement de pages et la manipulations de donnes en utilisant la JSTL. Ne vous intressez par consquent pas aux
dtails de cette premire page initForm.jsp, elle n'est l que pour servir de base notre exercice.
Pour en revenir l'exercice, je ne vous demande ici rien de bien compliqu. La page devra simplement afficher :
1. une liste rcapitulant le nom de chaque champ du formulaire et les informations qui y ont t saisies ;
2. les nom et prnom saisis par l'utilisateur ;
3. une liste des pays visits par l'utilisateur.

Il y a plusieurs manires de raliser ces tches basiques, choisissez celle qui vous semble la plus simple et logique.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

148/345

Prenez le temps de chercher et de rflchir, et on se retrouve ensuite pour la correction !

Correction
Ne vous jetez pas sur la correction sans chercher par vous-mmes : cet exercice n'aurait alors plus aucun intrt. Pour ceux
d'entre vous qui peinent voir par o partir, ou comment agencer tout cela, voil en exemple le squelette de la page que j'ai
ralise, contenant seulement les commentaires expliquant les traitements effectuer :
Secret (cliquez pour afficher)
Code : JSP
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Traitement des donnes</title>
</head>
<body>
<p>
<b>Vous avez renseign les informations suivantes :</b>
</p>
<%-- Parcourt chaque paramtre de la requte --%>
<%-- Affiche le nom de chaque paramtre. --%>
<%-- Parcourt la liste des valeurs de chaque
paramtre. --%>
<%-- Affiche chacune des valeurs --%>
<p>
<b>Vous vous nommez :</b>
</p>
<p>
<%-- Affiche les valeurs des paramtres nom et prenom --%>
</p>
<p>
<b>Vous avez visit les pays suivants :</b>
</p>
<p>
<%-- Teste l'existence du parametre pays. S'il existe on le
traite,
si non on affiche un message par dfaut.--%>
<%-- Teste l'existence du parametre autre. Si des donnes
existent on les traite,
si non on affiche un message par dfaut.--%>
</p>
</body>
</html>

Si vous tiez perdus, avec cette bauche vous devriez avoir une meilleure ide de ce que j'attends de vous. Prenez votre temps,
et n'hsitez pas relire les chapitres prcdents pour vrifier les points qui vous semblent flous !
Voici finalement la page que j'ai crite. Comme je vous l'ai signal plus tt, ce n'est pas LA solution, c'est simplement une des
manires de raliser ce simple traitement :
Secret (cliquez pour afficher)
Code : JSP - initProcess.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

149/345

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Traitement des donnes</title>
</head>
<body>
<p>
<b>Vous avez renseign les informations suivantes :</b>
</p>
<%-- Parcourt l'objet implicite paramValues, qui
souvenez-vous est une Map,
pour traiter chaque paramtre de la requte --%>
<c:forEach var="parametre" items="${ paramValues }">
<ul>
<%-- Affiche la cl de la Map paramValues,
qui correspond concrtement au nom du paramtre. --%>
<li><b><c:out value="${ parametre.key }"/></b> :</li>
traite,

--%>

<%-- Parcourt le tableau de String[] associ la cl


qui correspond la liste de ses valeurs. --%>
<c:forEach var="value" items="${ parametre.value }">
<%-- Affiche chacune des valeurs pour la cl donne

<c:out value="${ value }"/>


</c:forEach>
</ul>
</c:forEach>

<p>
<b>Vous vous nommez :</b>
</p>
<p>
<%-- Affiche les valeurs des paramtres nom et prenom en
y accdant directement via l'objet implicite (une Map) param.
On sait en effet qu'il n'y a qu'une valeur associe chacun de
ces 2 paramtres,
pas besoin d'utiliser paramValues ! --%>
<c:out value="${ param.nom }"/> <c:out value="${
param.prenom }"/>
</p>
<p>
<b>Vous avez visit les pays suivants :</b>
</p>
<p>
<%-- Teste l'existence du parametre pays. S'il existe on le
traite,
si non on affiche un message par dfaut.--%>
<c:choose>
<c:when test="${ !empty paramValues.pays }">
<%-- Parcourt le tableau de valeurs associes au paramtre pays
de la requte,
en utilisant l'objet implicite paramValues. En effet, c'est
ncessaire ici puisque
le select permet de renvoyer plusieurs valeurs pour le seul
paramtre nomm pays. --%>
<c:forEach var="pays" items="${ paramValues.pays }">
<c:out value="${ pays }"/><br/>
</c:forEach>
</c:when>
<c:otherwise>
Vous n' avez pas visit de pays parmi la liste propose.<br/>
</c:otherwise>
</c:choose>
<%-- Teste l'existence du parametre autre. Si des donnes
existent on les traite,
si non on affiche un message par dfaut.--%>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

150/345

<c:choose>
<c:when test="${ !empty param.autre }">
<%-- Parcourt les valeurs associes au paramtre autre de la
requte,
en utilisant l'objet implicite param. En effet, toutes les
valeurs sont ici concatnes
et transmises dans une seule chane de caractres, qu'on
parcourt via la boucle forTokens ! --%>
<c:forTokens var="pays" items="${ param.autre }" delims=",">
<c:out value="${ pays }"/><br/>
</c:forTokens>
</c:when>
<c:otherwise>
Vous n' avez pas visit d'autre pays.<br/>
</c:otherwise>
</c:choose>
</p>
</body>
</html>

Et voici le rendu avec les donnes de test :

Rendu du formulaire du TP Core.

J'ai utilis ici des tests conditionnels et diffrentes boucles afin de vous faire pratiquer, et mis en jeu diffrents objets implicites.
J'aurais par exemple trs bien pu mettre en jeu des variables de scope pour stocker les informations rcupres depuis la requte.
Si vous n'tes pas parvenus raliser ce simple traitement de formulaire, vous devez identifier les points qui vous ont pos
problme et revoir le cours plus attentivement !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

151/345

Je n'irai pour le moment pas plus loin dans la pratique. De nombreuses balises ne sont pas intervenues dans cet exercice : ne
vous inquitez pas, vous aurez bien assez tt l'occasion d'appliquer de manire plus exhaustive ce que vous avez dcouvert,
dans les prochaines parties du cours. Soyez patients !
En attendant, n'hsitez pas travailler davantage, tenter de dvelopper d'autres fonctionnalits de votre choix. Vous serez alors
prts pour tudier la bibliothque xml de la JSTL, que je vous prsente dans le chapitre suivant !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

152/345

La bibliothque xml
Nous allons ici parcourir les fonctions principales de la bibliothque xml. Les flux ou fichiers XML sont trs souvent utiliss
dans les applications web, et la JSTL offrant ici un outil trs simple d'utilisation pour effectuer quelques actions de base sur ce
type de format, il serait bte de s'en priver. Toutefois, n'oubliez pas mon avertissement dans la conclusion du chapitre sur la
bibliothque Core : seuls certains cas particuliers justifient l'utilisation de la bibliothque xml, dans la plupart des applications
MVC ces actions ont leur place dans le modle, et pas dans la vue !
Petite remarque avant de commencer : le fonctionnement de certaines balises tant trs similaire celui de balises que nous
avons dj abordes dans le chapitre prcdent sur la bibliothque Core, ce chapitre sera par moment un peu plus expditif.

La syntaxe XPath
Pour vous permettre de comprendre simplement les notations que j'utiliserai dans les exemples de ce chapitre, je dois d'abord
vous prsenter le langage XML Path Language, ou XPath. Autant vous prvenir tout de suite, de la mme manire que pour les
EL lors du chapitre prsentant la syntaxe JSP, je ne vous prsenterai ici que succinctement les bases dont j'ai besoin. Un tuto
part entire serait ncessaire afin de faire le tour complet des possibilits offertes par ce langage, et ce n'est pas notre objectif ici.
Encore une fois, si vous tes curieux, les documentations et ressources ne manquent pas sur le web ce sujet !

Le langage XPath
Le langage XPath permet d'identifier les nuds dans un document XML. Il fournit une syntaxe permettant de cibler directement
un fragment du document trait, comme un ensemble de nuds ou encore un attribut d'un nud en particulier, de manire
relativement simple. Comme son nom le suggre, "path" signifiant chemin en anglais, la syntaxe de ce langage ressemble aux
chemins d'accs aux fichiers dans un systme : les lments d'une expression XPath sont en effet spars par des slashes '/'.
Je n'introduis ici que les notions qui me seront ncessaires dans la suite de ce cours. Pour des notions exhaustives,
dirigez-vous vers la page du w3c, ou vers un tuto ddi ce sujet.

Structure XML
Voici la structure de notre fichier XML de test, que j'utiliserai dans les quelques exemples illustrant ce paragraphe :
Code : XML - monDocument.xml
<news>
<article id="1">
<auteur>Pierre</auteur>
<titre>Foo...</titre>
<contenu>...bar !</contenu>
</article>
<article id="27">
<auteur>Paul</auteur>
<titre>Bientt un LdZ J2EE !</titre>
<contenu>Woot ?</contenu>
</article>
<article id="102">
<auteur>Jacques</auteur>
<titre>Coyote court toujours</titre>
<contenu>Bip bip !</contenu>
</article>
</news>

Plutt que de paraphraser, voyons directement comment slectionner diverses portions de ce document via des exemples
comments :
Code : XML
<!-- Slection du nud racine -->
/
<!-- Slection des nuds 'article' enfants des nuds 'news' -->

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

153/345

<!-- Slection des nuds 'article' enfants des nuds 'news' -->
/news/article
<!-- Slection de tous les nuds inclus dans les nuds 'article'
enfants des nuds 'news' -->
/news/article/*
<!-- Slection de tous les nuds 'auteur' qui ont deux parents
quelconques -->
/*/*/auteur
<!-- Slection de tous les nuds 'auteur' du document via
l'oprateur '//' -->
//auteur
<!-- Slection de tous les nuds 'article' ayant au moins un parent
-->
/*//article
<!-- Slection de l'attribut 'id' des nuds 'article' enfants de
'news' -->
/news/article/@id
<!-- Slection des nuds 'article' enfants de 'news' dont la valeur
du nud 'auteur 'est 'Paul' -->
/news/article[auteur='Paul']
<!-- Slection des nuds 'article' enfants de 'news' dont l'attribut
id vaut '12' -->
/news/article[@id='12']

Je m'arrterai l pour les prsentations. Sachez qu'il existe des commandes plus pousses que ces quelques lments, et je vous
laisse le loisir de vous plonger dans les ressources que je vous ai communiques pour plus d'information. Mon objectif ici est
simplement de vous donner un premier aperu de ce qu'est la syntaxe XPath, afin que vous compreniez sa logique et ne soyez
pas perturbs lorsque vous me verrez utiliser cette syntaxe dans les attributs de certaines balises de la bibliothque xml.
J'imagine que cela reste assez flou dans votre esprit, et que vous vous demandez probablement comment diable ces
expressions vont-elles bien pouvoir nous servir, et surtout o nous allons pouvoir les utiliser. Pas d'inquitude, les
explications vous seront fournies au fur et mesure que vous dcouvrirez les balises mettant en jeu ce type
d'expressions.

Pour ceux d'entre vous qui veulent tester les expressions XPath prcdentes, ou qui veulent pratiquer en manipulant d'autres
fichiers XML et/ou en mettant en jeu d'autres expressions XPath, voici un site web qui vous permettra de tester en direct le
rsultat de vos expressions sur le document XML de votre choix : XPath Expression Testbed. Amusez-vous et vrifiez ainsi votre
bonne comprhension du langage !

Les actions de base


Avant de vous prsenter les diffrentes balises disponibles, je vous donne ici la directive JSP ncessaire pour permettre
l'utilisation des balises de la bibliothque xml dans vos pages :
Code : JSP
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>

Retenez bien que cette directive devra tre prsente sur chacune des pages de votre projet utilisant les balises JSTL que je vous
prsente dans ce chapitre. Dans un prochain chapitre concernant la cration d'une bibliothque personnalise, nous verrons
comment il est possible de ne plus avoir se soucier de cette commande. En attendant, ne l'oubliez pas !

Rcuprer et analyser un document


Je vais dans ce paragraphe vous montrer comment procder pour rcuprer et analyser simplement un fichier XML depuis votre
page JSP. Je reprends le fichier XML que j'ai utilis prcdemment lorsque je vous ai prsent la syntaxe du langage XPath, et je

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

154/345

le nomme monDocument.xml.
Commenons par aborder la rcupration du fichier XML. Cette tape correspond simplement un import, ralis avec ce tag de
la bibliothque Core que vous devez dj connatre :
Code : JSP
<c:import url="monDocument.xml" varReader="monReader">
...
</c:import>

Remarquez l'utilisation de l'attribut varReader. C'est en quelque sorte un buffer, une variable qui sera utilise pour une utilisation
postrieure du contenu du fichier import. Notez que lorsque vous utiliserez cet attribut, il vous sera impossible d'utiliser
conjointement l'attribut var.
Rappelez-vous, lorsque l'on utilise cet attribut varReader, le contenu du fichier import n'est pas inclus littralement
dans votre page JSP comme c'est le cas lors d'un import simple : il est copi dans la variable nomme dans l'attribut
varReader.

Le document XML tant rcupr et stock dans la variable monReader, nous souhaitons maintenant l'analyser. Nous allons
pour cela faire intervenir une nouvelle balise, issue de la librairie xml cette fois :
Code : JSP
<c:import url="monDocument.xml" varReader="monReader">
<%-- Parse le contenu du fichier XML monDocument.xml dans une
variable nomme 'doc' --%>
<x:parse var="doc" doc="${monReader}" />
...
</c:import>

Deux attributs sont ici utiliss :


var : contient le nom de la variable de scope qui contiendra les donnes qui reprsentent notre document XML pars.
Comme d'habitude, si l'attribut scope n'est pas explicit, la porte par dfaut de cette variable sera la page.
doc : permet de prciser que l'on souhaite parser le contenu de notre varReader dfini prcdemment lors de l'import.
Souvenez-vous, le varReader ici nomm monReader est une variable, il nous faut donc utiliser une EL pour y faire
rfrence, en l'occurrence ${monReader} !
Dans certains codes vieillissant, vous trouverez parfois dans l'utilisation de la balise <x:parse/> un attribut nomm
xml. Sachez qu'il joue le mme rle que l'attribut doc, et qu'il est dprci : concrtement, il a t remplac par doc, et il ne
faut donc plus l'utiliser.

Note : l'import qui stocke le fichier dans le varReader doit rester ouvert pour pouvoir appliquer un <x:parse/> sur le contenu
de ce varReader ! La porte du varReader dfini est en effet uniquement l'intrieur du corps du <c:import/>. Afin de pouvoir
accder ce varReader, il ne faut donc pas fermer directement la balise d'import comme c'est le cas ci-dessous :
Code : JSP
<%-- Mauvaise utilisation du varReader --%>
<c:import url="monDocument.xml" varReader="monReader" />

Toutefois, il est possible de ne pas utiliser le varReader, et de simplement utiliser une variable de scope. Vous pourrez ainsi faire
votre import, puis traiter le contenu du fichier par la suite, sans devoir travailler dans le corps de la balise d'import :
Code : JSP

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

155/345

<c:import url="monDocument.xml" var="monReader" />

Cela dit, je vous conseille de travailler avec le varReader, puisque c'est l'objectif premier de cet attribut.
Plusieurs remarques sont d'ores et dj ncessaires :
Comprenez bien ici la diffrence entre le varReader de la balise <c:import/> et le var de la balise <x:parse/>: le
premier contient le contenu brut du fichier XML, alors que le second contient le rsultat du parsing du fichier XML. Pour
faire simple, la JSTL utilise une structure de donnes qui reprsente notre document XML pars, et c'est cette structure
qui est stocke dans la variable dfinie par var.
Le type de la variable dfinie via cet attribut var dpendra de l'implmentation choisie par le dveloppeur. Pour
information, il est ici possible de remplacer l'attribut var par l'attribut nomm varDom, qui permet de fixer l'implmentation
utilise : la variable ainsi dfinie sera de type org.w3c.dom.Document. De mme, scope sera remplac par
scopeDom. Ceci impose donc que votre fichier XML respecte l'interface Document cite prcdemment. Tout cela tant
vraiment spcifique, je ne m'talerai pas davantage sur le sujet et je vous renvoie la documentation pour plus d'infos.
Importer un fichier n'est pas ncessaire. Il est en effet possible de traiter directement un flux XML depuis la page JSP, en
le plaant dans le corps de la balise <x:parse/> :
Code : JSP
<%-- Parse le flux XML contenu dans le corps de la balise --%>
<x:parse var="doc">
<news>
<article id="1">
<auteur>Pierre</auteur>
<titre>Foo...</titre>
<contenu>...bar !</contenu>
</article>
<article id="27">
<auteur>Paul</auteur>
<titre>Bientt un LdZ J2EE !</titre>
<contenu>Woot ?</contenu>
</article>
<article id="102">
<auteur>Jacques</auteur>
<titre>Coyote court toujours</titre>
<contenu>Bip bip !</contenu>
</article>
</news>
</x:parse>

Il reste seulement deux attributs que je n'ai pas encore abords :


filter : permet de limiter le contenu trait par l'action de parsing <x:parse/> une portion d'un flux XML seulement.
Cet attribut peut s'avrer utile lors de l'analyse de documents XML lourds, afin de ne pas dtriorer les performances
l'excution de votre page. Pour plus d'information sur ces filtres de type XMLFilter, essayez la documentation.
systemId : cet attribut ne vous sera utile que si votre fichier XML contient des rfrences vers des entits externes. Vous
devez y saisir l'adresse URI qui permettra de rsoudre les liens relatifs contenus dans votre fichier XML. Bref rappel :
une rfrence une entit externe dans un fichier XML est utilise pour y inclure un fichier externe, principalement
lorsque des donnes ou textes sont trop longs et qu'il est plus simple de les garder dans un fichier part. Le processus
accdera ces fichiers externes lors du parsage du document XML spcifi.

Je n'ai pour ces derniers pas d'exemple trivial vous proposer. Je fais donc volontairement l'impasse ici, je pense que ceux parmi
vous qui connaissent et ont dj manipul les filtres XML et les entits externes comprendront aisment de quoi il retourne.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

156/345

Afficher une expression


Les noms des balises que nous allons maintenant aborder devraient vous tre familiers : ils trouvent leur quivalent dans la
bibliothque Core que vous avez dcouverte dans le chapitre prcdent. Alors que ces dernires accdaient des donnes de
l'application en utilisant des EL, les balises de la bibliothque xml vont quant elles accder des donnes issues de documents
XML, via des expressions XPath.
Pour afficher un lment, nous allons utiliser la balise <x:out/>, pour laquelle seul l'attribut select est ncessaire :
Code : JSP
<c:import url="monDocument.xml" varReader="monReader">
<%-- Parse le contenu du fichier XML monDocument.xml dans une
variable nomme 'doc' --%>
<x:parse var="doc" doc="${monReader}" />
<x:out select="$doc/news/article/auteur" />
</c:import>

Le rendu HTML du code ci-dessus est alors le suivant :


Code : HTML
Pierre

En suivant le paragraphe introduisant XPath, j'avais compris qu'une telle expression renvoyait tous les nuds "auteur"
du document !
O sont passs Paul et Jacques ? O est l'erreur ?
Hh... Eh bien, vrai dire il n'y a aucune erreur ! En effet, l'expression XPath renvoie bel et bien un ensemble de nuds, en
l'occurrence les nuds "auteur" ; cet ensemble de noeuds est stock dans une structure de type NodeSet, un type propre
XPath qui implmente le type Java standard NodeList.
Le comportement ici observ provient du fait que la balise d'affichage <x:out/> ne gre pas rellement un ensemble de nuds,
et n'affiche que le premier nud contenu dans cet ensemble de type NodeSet. Toutefois, le contenu de l'attribut select peut
trs bien contenir un NodeSet ou une opration sur un NodeSet. Vrifions par exemple que NodeSet contient bien 3 nuds,
puisque nous avons 3 auteurs dans notre document XML :
Code : JSP
<c:import url="monDocument.xml" varReader="monReader">
<%-- Parse le contenu du fichier XML monDocument.xml dans une
variable nomme 'doc' --%>
<x:parse var="doc" doc="${monReader}" />
<x:out select="count($doc/news/article/auteur)" />
</c:import>

J'utilise ici la fonction count(), qui renvoie le nombre d'lments que l'expression XPath a slectionns et stocks dans le
NodeSet. Et le rendu HTML de cet exemple est bien "3" ; notre ensemble de nuds contient donc bien trois auteurs, Paul et
Jacques ne sont pas perdus en cours de route.

L'attribut select de la balise <x:out/> est l'quivalent de l'attribut value de la balise <c:out/>, sauf qu'il attend ici une
expression XPath et non plus une EL ! Rappelez-vous que le rle des expressions XPath est de slectionner des portions de
document XML. Expliquons rapidement l'expression <x:out select="$doc/news/article/auteur" /> : elle va
slectionner tous les nuds "auteur" qui sont enfants d'un nud "article" lui-mme enfant du nud racine "news" prsent dans
le document $doc. En l'occurrence, $doc se rfre ici au conteu pars de notre variable varReader.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

157/345

Dans une expression XPath, pour faire rfrence une variable nomme nomVar on n'utilise pas ${nomVar} comme
c'est le cas dans une EL, mais $nomVar. Essayez de retenir cette syntaxe, cela vous vitera bien des erreurs ou
comportements inattendus !

ce sujet, sachez enfin qu'outre une variable simple, il est possible de faire intervenir les objets implicites dans une expression
XPath, de cette manire :
Code : JSP
<%-- Rcupre le document nomm 'doc' enregistr auparavant en
session, via l'objet implicite sessionScope --%>
<x:out select="$sessionScope:doc/news/article" />
<%-- Slectionne le nud 'article' dont l'attribut 'id' a pour
valeur le contenu de la variable
nomme 'idArticle' qui a t passe en paramtre de la requte, via
l'objet implicite param --%>
<x:out select="$doc/news/article[@id=$param:idArticle]"/>

Ce qu'on peut retenir de cette balise d'affichage, c'est qu'elle fournit, grce un fonctionnement bas sur des expressions XPath,
une alternative aux feuilles de style XSL pour la transformation de contenus XML, en particulier lorsque le format d'affichage
final est une page web html.

Crer une variable


Nous passerons trs rapidement sur cette balise. Sa syntaxe est <x:set/>, et comme vous vous en doutez elle est l'quivalent
de la balise <c:set/> de la bibliothque Core, avec de petites diffrences :
l'attribut select remplace l'attribut value, ce qui a la mme consquence que pour la balise d'affichage : une expression
XPath est attendue, et non pas une EL ;
l'attribut var est obligatoire, ce qui n'tait pas le cas pour la balise <c:set/>.
Ci-dessous un bref exemple de son utilisation :
Code : JSP
<%-- Enregistre le rsultat de l'expression XPath, spcifie dans
l'attribut select,
dans une variable de session nomme 'auteur' --%>
<x:set var="auteur" scope="session" select="$doc//auteur" />
<%-- Affiche le contenu de la variable nomme 'auteur' enregistre
en session --%>
<x:out select="$sessionScope:auteur" />

Le rle de la balise est donc sensiblement le mme que son homologue de la bibliothque Core : enregistrer le rsultat
d'une expression dans une variable de scope. La seule diffrence rside dans la nature de l'expression value, qui est
ici une expression XPath et non plus une EL.

Les conditions
Les conditions
Les balises permettant la mise en place de conditions sont l aussi sensiblement identiques leurs homologues de la
bibliothque Core : la seule et unique diffrence rside dans le changement de l'attribut test pour l'attribut select. Par
consquent, comme vous le savez maintenant c'est ici une expression XPath qui est attendue, et non plus une EL !
Plutt que de paraphraser le prcdent chapitre, je ne vous donne ici que de simples exemples comments, qui vous permettront
de reprer les quelques diffrences de syntaxe.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

158/345

Une condition simple


Code : JSP
<%-- Afficher le titre de la news poste par 'Paul' --%>
<x:if select="$doc/news/article[auteur='Paul']">
Paul a dj post une news dont voici le titre :
<x:out select="$doc/news/article[auteur='Paul']/titre" />
</x:if>

Le rendu HTML correspondant :


Code : JSP
Paul a dj post une news dont voici le titre : Bientt un LdZ J2EE
!

De mme que pour la balise <c:if/>, il est possible de stocker le rsultat du test conditionnel en spcifiant un attribut var.

Des conditions multiples


Code : JSP
<%-- Affiche le titre de la news poste par 'Nicolas' si elle
existe, et un simple message sinon --%>
<x:choose>
<x:when select="$doc/news/article[auteur='Nicolas']">
Nicolas a dj post une news dont voici le titre :
<x:out select="$doc/news/article[auteur='Nicolas']/titre" />
</x:when>
<x:otherwise>
Nicolas n'a pas post de news.
</x:otherwise>
</x:choose>

Le rendu HTML correspondant :


Code : JSP
Nicolas n'a pas post de news.

Les contraintes d'utilisation de ces balises sont les mmes que celles de la bibliothques Core. Je vous renvoie au chapitre
prcdent si vous ne vous en souvenez plus.
Voil tout pour les tests conditionnels de la bibliothque xml : leur utilisation est semblable celle des conditions de la
bibliothque Core, seule la cible change : on traite ici un flux XML, via des expressions XPath.

Les boucles
Les boucles
Il n'existe qu'un seul type de boucle dans la bibliothque xml de la JSTL, la balise <x:forEach/> :
Code : JSP
<!-- Affiche les auteurs et titres de tous les articles -->
<p>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

159/345

<x:forEach var="element" select="$doc/news/article">


<strong><x:out select="$element/auteur" /></strong> :
<x:out select="$element/titre" />.<br/>
</x:forEach>
</p>

Le rendu HTML correspondant :


Code : JSP
<p>

<strong>Pierre</strong> : Foo....<br/>
<strong>Paul</strong> : Bientt un LdZ J2EE !.<br/>
<strong>Jacques</strong> : Coyote court toujours.<br/>
</p>

De mme que pour la balise <c:forEach/>, il est possible de faire intervenir un pas de parcours via l'attribut step, de dfinir
les index de dbut et de fin via les attributs begin et end, ou encore d'utiliser l'attribut varStatus pour accder l'tat de chaque
itration.

Les tranformations
Transformations
Le bibliothque xml de la JSTL permet d'appliquer des transformations un flux XML via une feuille de style XSL. Je ne
reviendrai pas ici sur le langage et les mthodes employer, si vous n'tes pas familiers avec ce concept, je vous conseille de lire
cette introduction la mise en forme de documents XML avec XSLT.
La balise ddie cette tche est <x:tranform/>. Commenons par un petit exemple, afin de comprendre comment elle
fonctionne. J'utiliserai ici le mme fichier XML que pour les exemples prcdents, ainsi que la feuille de style XSL suivante :
Code : XML - test.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8" />
<title>Mise en forme avec XSLT</title>
</head>
<body>
<table width="1000" border="1" cellspacing="0"
cellpadding="0">
<tr>
<th scope="col">Id</th>
<th scope="col">Auteur</th>
<th scope="col">Titre</th>
<th scope="col">Contenu</th>
</tr>
<xsl:for-each select="/news/article">
<tr>
<td>
<xsl:value-of select="@id" />
</td>
<td>
<xsl:value-of select="auteur" />
</td>
<td>
<xsl:value-of select="titre" />
</td>
<td>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

160/345

<xsl:value-of select="contenu" />


</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Cette feuille affiche simplement les diffrents lments de notre fichier XML dans un tableau HTML.
Et voici comment appliquer la transformation base sur cette feuille de style notre document XML :
Code : JSP - testTransformXsl.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<c:import varReader="xslFile" url="test.xsl">
<c:import varReader="xmlFile" url="monDocument.xml">
<x:transform doc="${xmlFile}" xslt="${xslFile}"/>
</c:import>
</c:import>

On importe ici simplement nos deux fichiers, puis on appelle la balise <x:transform/>. Deux attributs sont ici utiliss :
doc : contient la rfrence au document XML sur lequel la transformation doit tre applique. Attention, ici on parle bien
du document XML d'origine, et pas d'un document analys via <x:parse/>. On travaille bien directement sur le
contenu XML. Il est d'ailleurs possible ici de ne pas utiliser d'import, en dfinissant directement le flux XML traiter dans
une variable de scope, voire directement dans le corps de la balise comme dans l'exemple suivant :
Code : JSP
<x:transform xslt="${xslFile}">
<news>
<article id="1">
<auteur>Pierre</auteur>
<titre>Foo...</titre>
<contenu>...bar !</contenu>
</article>
<article id="27">
<auteur>Paul</auteur>
<titre>Bientt un LdZ J2EE !</titre>
<contenu>Woot ?</contenu>
</article>
<article id="102">
<auteur>Jacques</auteur>
<titre>Coyote court toujours</titre>
<contenu>Bip bip !</contenu>
</article>
</news>
</x:transform>

xslt : contient logiquement la feuille de style XSL. Il est galement possible de ne pas utiliser d'import ici, et de
simplement dfinir une feuille de style dans une variable de scope.

En l'absence d'attribut var, le contenu transform sera automatiquement gnr dans la page HTML finale. Et lorsque vous
accdez cette page JSP depuis votre navigateur, vous apercevez un tableau contenant les donnes de votre fichier XML : la
transformation a bien t applique ! Ceci est particulirement intressant lorsque vous souhaitez formater un contenu XML en
HTML, par exemple lors de la lecture de flux RSS. En images :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

161/345

Arborescence sous Eclipse avec XSLT.

Rendu transformation XSLT.

Si par contre vous prcisez un attribut var, le rsultat de cette transformation sera alors stock dans la variable de scope ainsi
cre, de type Document. Sachez qu'il existe galement un attribut result qui, en l'absence des attributs var et scope, stocke
l'objet cr par la transformation.
Pour terminer, il est possible de passer des paramtres une transformation XSLT, en utilisant la balise <x:param/>. Cette
dernire ne peut exister que dans le corps d'une balise <x:transform/>, et s'emploie de la mme manire que son homologue
de la bibliothque Core :
Code : JSP - testTransformXsl.jsp
<c:import var="xslFile" url="test.xsl"/>
<c:import var="xmlFile" url="monDocument.xml"/>
<x:transform doc="${xmlFile}" xslt="${xslFile}">
<x:param name="couleur" value="orange" />
</x:transform>

Le comportement et l'utilisation sont identiques ceux de <c:param/> : deux attributs name et value contiennent simplement
le nom et la valeur du paramtre transmettre. Ici dans cet exemple, ma feuille de style ne traite pas de paramtre, et donc ne fait
rien de ce paramtre nomm couleur que je lui passe. Si vous souhaitez en savoir plus sur l'utilisation de paramtres dans une
feuille XSL, vous savez o chercher !
Il reste deux attributs que je n'ai pas explicits : docSystemId and xsltSystemId. Ils ont tous deux la mme utilit que l'attribut
systemId de la balise <x:parse/>, et s'utilisent de la mme faon : il suffit d'y renseigner l'URI destine rsoudre les liens
relatifs contenus respectivement dans le document XML et dans la feuille de style XSL.
Je n'ai pour le moment pas prvu de vous prsenter les autres bibliothques de la JSTL : je pense que vous tes maintenant
assez familiers avec la comprhension du fonctionnement des tags JSTL pour voler de vos propres ailes.
Mais ne partez pas si vite, prenez le temps de faire tous les tests que vous jugez ncessaires. Il n'y a que comme a que a
rentrera, et que vous prendrez suffisamment de recul pour comprendre parfaitement ce que vous faites. Dans le chapitre suivant
je vous propose un exercice d'application de ce que vous venez de dcouvrir, et ensuite on reprendra le code d'exemple de la
partie prcdente en y intgrant la JSTL !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

162/345

JSTL xml : exercice d'application


La bibliothque xml n'a maintenant plus de secrets pour vous. Mais si vous souhaitez vous familiariser avec toutes ces nouvelles
balises et tre l'aise lors du dveloppement de pages JSP, vous devez vous entrainer !
Je vous propose ici un petit exercice d'application qui met en jeu des concepts ralisables l'aide des balises que vous venez de
dcouvrir. Suivez le guide...

Les bases de l'exercice


On prend les mmes et on recommence...
Pour mener bien ce petit exercice, commencez par crer un nouveau projet nomm jstl_exo2. Configurez bien entendu ce projet
en y intgrant la JSTL, afin de pouvoir utiliser nos chres balises dans nos pages JSP !
Une fois ceci fait, crez pour commencer un document XML. Je vous en donne ici le contenu complet :
Code : XML - inventaire.xml
<?xml version="1.0" encoding="utf-8"?>
<inventaire>
<livre>
<auteur>Pierre</auteur>
<titre>D&#233;veloppez vos applications web avec JRuby !</titre>
<date>Janvier 2012</date>
<prix>22</prix>
<stock>127</stock>
<minimum>10</minimum>
</livre>
<livre>
<auteur>Paul</auteur>
<titre>D&#233;couvrez la puissance du langage Perl</titre>
<date>Avril 2017</date>
<prix>26</prix>
<stock>74</stock>
<minimum>10</minimum>
</livre>
<livre>
<auteur>Matthieu</auteur>
<titre>Apprenez &#224; programmer en C</titre>
<date>Novembre 2009</date>
<prix>25</prix>
<stock>19</stock>
<minimum>20</minimum>
</livre>
<livre>
<auteur>Matthieu</auteur>
<titre>Concevez votre site web avec PHP et MySQL</titre>
<date>Mars 2010</date>
<prix>30</prix>
<stock>7</stock>
<minimum>20</minimum>
</livre>
<livre>
<auteur>Cysboy</auteur>
<titre>La programmation en Java</titre>
<date>Septembre 2010</date>
<prix>29</prix>
<stock>2000</stock>
<minimum>20</minimum>
</livre>
</inventaire>

Ne prtez pas grande attention aux donnes modlises par ce document. Nous avons simplement besoin d'une base simple,
contenant de quoi nous amuser un peu avec les balises que nous venons de dcouvrir !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

163/345

Note : toute ressemblance avec des personnages existant ou ayant exist serait fortuite et indpendante de la volont de
l'auteur...
Votre mission maintenant, c'est d'crire la page rapportInventaire.jsp se chargeant d'analyser ce document XML, et de gnrer un
rapport qui :
listera chacun des livres prsents ;
affichera un message d'alerte pour chaque livre dont le stock est en dessous de la quantit minimum spcifie ;
listera enfin chacun des livres prsents, regroups par stocks tris du plus grand au plus faible.

Il y a plusieurs manires de raliser ces tches basiques, choisissez celle qui vous semble la plus simple et logique.
Prenez le temps de chercher et de rflchir, et on se retrouve ensuite pour la correction !

Correction
Ne vous jetez pas sur la correction sans chercher par vous-mmes : cet exercice n'aurait alors plus aucun intrt. Je ne vous
donne ici pas d'aide supplmentaire, si vous avez suivi le cours jusqu'ici vous devez tre capables de comprendre comment faire,
les balises ncessaires pour cet exercice ressemblant fortement celles utilises dans celui concernant la bibliothque Core !
Voici donc une correction possible :
Secret (cliquez pour afficher)
Code : JSP
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Rapport d'inventaire</title>
</head>
<body>
<%-- Rcupration du document XML. --%>
<c:import url="inventaire.xml" var="documentXML" />
<%-- Analyse du document XML rcupr. --%>
<x:parse var="doc" doc="${documentXML}" />
<p><b>Liste de tous les livres :</b></p>
<div>
<ul>
<%-- Parcours du document pars pour y rcuprer chaque noeud
"livre". --%>
<x:forEach var="livre" select="$doc/inventaire/livre">
<%-- Affichage du titre du livre rcupr. --%>
<li><x:out select="$livre/titre" /></li>
</x:forEach>
</ul>
</div>
<p><b>Liste des livres qu'il faut rapprovisionner :</b></p>
<div>
<ul>
<%-- Parcours du document pars pour y rcuprer chaque noeud
"livre"
dont le contenu du noeud "stock" est infrieur au contenu du
noeud
"minimum". --%>
<x:forEach var="livre" select="$doc/inventaire/livre[stock <
minimum]">
<%-- Affichage des titres, stocks et minimaux du livre rcupr.
--%>
<li><x:out select="$livre/titre" /> : <x:out
select="$livre/stock" /> livres en stock (limite avant alerte :
<x:out select="$livre/minimum" />)</li>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

164/345

</x:forEach>
</ul>
</div>
<p><b>Liste des livres classs par stock :</b></p>
<%-- Il faut rflchir... un peu ! --%>
<pre>
Le tri d'une liste, d'un tableau, d'une collection... bref de
manire gnrale le tri de donnes,
ne doit pas se faire depuis votre page JSP ! Que ce soit en
utilisant les API relatives aux collections,
ou via un bean de votre couche mtier, ou que sais-je encore, il
est toujours prfrable que votre tri
soit effectu avant d'arriver votre JSP. La JSP ne doit en
principe que rcuprer cette collection dj trie,
formater les donnes pour une mise en page particulire si
ncessaire, et seulement les afficher.
C'tait un simple pige ici, j'espre que vous avez rflchi avant
de tenter d'implmenter un tri avec
la JSTL, et que vous comprenez pourquoi cela ne doit pas
intervenir ce niveau ;)
</pre>
</body>
</html>

Je n'ai fait intervenir ici que des traitements faciles, n'utilisant que des boucles et des expressions XPath. J'aurais pu vous
imposer l'utilisation de tests conditionnels, ou encore de variables de scope, mais l'objectif est ici uniquement de vous permettre
d'tre l'aise avec l'analyse de document XML. Si vous n'tes pas parvenus raliser ce simple traitement de document, vous
devez identifier les points qui vous ont pos problme et revoir le cours plus attentivement !
N'hsitez pas travailler davantage, tenter de dvelopper d'autres fonctionnalits de votre choix. Vous pouvez par exemple faire
intervenir des transformations XSL sur le document XML.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

165/345

Faisons le point !
Il est temps de mettre en pratique ce que nous avons appris. Nous avons en effet abord toutes les balises et tous les concepts
ncessaires et sommes maintenant capables de rcrire proprement nos premiers exemples en utilisant des tags JSTL ! Je vous
propose ensuite, pour vous dtendre un peu, quelques conseils autour de l'criture de code Java en gnral.

Reprenons notre exemple


Dans la partie prcdente, la mise en place de boucles et conditions tait un obstacle que nous tions incapables de franchir
sans crire de code Java. Maintenant que nous avons dcouvert les balises de la bibliothque Core de la JSTL, nous avons tout
ce qu'il nous faut pour russir.
Pour rappel, voici o nous en tions :
Code : JSP - tat final de notre vue d'exemple en fin de partie prcdente
<%@ page import="java.util.List" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
${test}
${auteur}
</p>
<p>
Rcupration du bean :
${coyote.prenom}
${coyote.nom}
</p>
<p>
Rcupration de la liste :
<%
List<Integer> liste = (List<Integer>)
request.getAttribute( "liste" );
for( Integer i : liste ){
out.println(i + " : ");
}
%>
</p>
<p>
Rcupration du jour du mois :
<%
Integer jourDuMois = (Integer) request.getAttribute(
"jour" );
if ( jourDuMois % 2 == 0 ){
out.println("Jour pair : " + jourDuMois);
} else {
out.println("Jour impair : " + jourDuMois);
}
%>
</p>
</body>
</html>

Et voici les nouvelles balises qui vont nous permettre de faire disparatre le code Java de notre JSP d'exemple :
<c:choose> pour la mise en place de conditions ;
<c:foreach> pour la mise en place de boucles.

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

166/345

Reprise de la boucle
En utilisant la syntaxe JSTL, notre boucle devient simplement :
Code : JSP
<p>

</p>

Rcupration de la liste :
<%-- Boucle sur l'attribut de la requte nomm 'liste' --%>
<c:forEach items="${liste}" var="element">
<c:out value="${element}" /> :
</c:forEach>

Comme prvu, plus besoin de rcuprer explicitement la variable contenant la liste depuis la requte, et plus besoin d'crire du
code Java en dur pour mettre en place la boucle sur la liste.

Reprise de la condition
En utilisant la syntaxe JSTL, notre condition devient simplement :
Code : JSP
<p>

Rcupration du jour du mois :


<c:choose>
<%-- Test de parit sur l'attribut de la requte nomm
'jour' --%>
<c:when test="${ jour % 2 == 0 }">Jour pair :
${jour}</c:when>
<c:otherwise>Jour impair : ${jour}</c:otherwise>
</c:choose>
</p>

Comme prvu, plus besoin de rcuprer explicitement la variable contenant le jour du mois depuis la requte, et plus besoin
d'crire du code Java en dur pour mettre en place le test de parit.
Ainsi, notre page finale est bien plus claire et comprhensible :
Code : JSP - Page d'exemple sans code Java
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Titre</title>
</head>
<body>
<p>Ceci est une page gnre depuis une JSP.</p>
<p>
${test}
${auteur}
</p>
<p>
Rcupration du bean :
${coyote.prenom}
${coyote.nom}
</p>
<p>
Rcupration de la liste :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

167/345

<c:forEach items="${liste}" var="element">


${element} :
</c:forEach>
</p>
<p>
Rcupration du jour du mois :
<c:choose>
<c:when test="${ jour % 2 == 0 }">Jour pair : ${jour}</c:when>
<c:otherwise>Jour impair : ${jour}</c:otherwise>
</c:choose>
</p>
</body>
</html>

Quelques conseils
Avant d'attaquer la suite du cours, dtendez-vous un instant et dcouvrez ces quelques astuces pour mieux organiser votre code
et le rendre plus lisible.

Utilisation de constantes
Afin de faciliter la lecture et la modification du code d'une classe, il est recommand de ne pas crire le contenu des attributs de
types primitifs en dur au sein de votre code, et de le regrouper sous forme de constantes en dbut de classe afin d'y centraliser
les donnes.
Reprenons par exemple notre servlet d'exemple, o vous pouvez voir aux lignes 42-45 et 48 des String initialiss directement
dans le code :
Code : Java - com.sdzee.servlets.Test
package com.sdzee.servlets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import org.joda.time.DateTime;
import com.sdzee.beans.CoyoteBean;
public class Test extends HttpServlet {
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/** Cration et initialisation du message. */
String message = "Message transmis de la servlet la JSP.";
/** Cration du bean et initialisation de ses proprits */
CoyoteBean premierBean = new CoyoteBean();
premierBean.setNom( "Coyote" );
premierBean.setPrenom( "Wile E." );
/** Cration de la liste et insertion de quatre lments */
List<Integer> premiereListe = new ArrayList<Integer>();
premiereListe.add( 27 );
premiereListe.add( 12 );
premiereListe.add( 138 );
premiereListe.add( 6 );
/** On utilise ici la libraire Joda pour manipuler les dates,
pour deux raisons :
* - c'est tellement plus simple et limpide que de travailler avec
les objets Date ou Calendar !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

168/345

* - c'est (probablement) un futur standard de l'API Java.


*/
DateTime dt = new DateTime();
Integer jourDuMois = dt.getDayOfMonth();
/** Stockage du message, du bean et de la liste dans l'objet
request */
request.setAttribute( "test", message );
request.setAttribute( "coyote", premierBean );
request.setAttribute( "liste", premiereListe );
request.setAttribute( "jour", jourDuMois );
/** Transmission de la paire d'objets request/response notre
JSP */
this.getServletContext().getRequestDispatcher( "/WEB-INF/test.jsp"
).forward( request, response );
}
}

Les lignes 20, 24 25 et 29 32, bien qu'elles contiennent des String et int en dur, correspondent simplement l'initialisation
des donnes d'exemple que nous transmettons notre JSP : ce sont des donnes "externes". Dans le cas d'une relle application,
ces donnes seront issues de la base de donnes, du modle ou encore d'une saisie utilisateur, mais bien videmment jamais
directement issues de la servlet comme c'est le cas ici dans l'exemple.
En ce qui concerne les String initialises en dur, vous devez remarquer qu'elles ne contiennent que des donnes "internes" : en
l'occurrence, un nom de page JSP et quatre noms d'attributs. Il s'agit bien ici de donnes propres au fonctionnement de
l'application et non pas de donnes destines tre transmises la vue pour affichage.
Eh bien comme je vous l'ai annonc, une bonne pratique est de remplacer ces initialisations directes par des constantes,
regroupes en tte de classe. Voici donc le code de notre servlet aprs modification :
Code : Java - com.sdzee.servlets.Test
package com.sdzee.servlets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import org.joda.time.DateTime;
import com.sdzee.beans.CoyoteBean;
public class Test extends HttpServlet {
public static final String ATT_MESSAGE = "test";
public static final String ATT_BEAN = "coyote";
public static final String ATT_LISTE = "liste";
public static final String ATT_JOUR = "jour";
public static final String VUE = "/WEB-INF/test.jsp";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/** Cration et initialisation du message. */
String message = "Message transmis de la servlet la JSP.";
/** Cration du bean et initialisation de ses proprits */
CoyoteBean premierBean = new CoyoteBean();
premierBean.setNom( "Coyote" );
premierBean.setPrenom( "Wile E." );
/** Cration de la liste et insertion de quatre lments */

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

169/345

List<Integer> premiereListe = new ArrayList<Integer>();


premiereListe.add( 27 );
premiereListe.add( 12 );
premiereListe.add( 138 );
premiereListe.add( 6 );
/** On utilise ici la libraire Joda pour manipuler les dates,
pour deux raisons :
* - c'est tellement plus simple et limpide que de travailler avec
les objets Date ou Calendar !
* - c'est (probablement) un futur standard de l'API Java.
*/
DateTime dt = new DateTime();
Integer jourDuMois = dt.getDayOfMonth();
/** Stockage du message, du bean et de la liste dans l'objet
request */
request.setAttribute( ATT_MESSAGE, message );
request.setAttribute( ATT_BEAN, premierBean );
request.setAttribute( ATT_LISTE, premiereListe );
request.setAttribute( ATT_JOUR, jourDuMois );
/** Transmission de la paire d'objets request/response notre
JSP */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
}

Vous visualisez bien ici l'intrt d'une telle pratique : en dbut de code sont accessibles en un coup dil toutes les donnes
utilises en dur au sein de la classe. Si vous nommez intelligemment vos constantes, vous pouvez alors sans avoir parcourir le
code savoir quelle constantes correspond quelle donne. Ici par exemple, j'ai prfix les noms des attributs de requte par
"ATT_" et nomm "VUE" la constante contenant le chemin vers notre page JSP. Ainsi, si vous procdez plus tard une
modification sur une de ces donnes, il vous suffira de modifier la valeur de la constante correspondante et vous n'aurez pas
besoin de parcourir votre code. C'est d'autant plus utile que votre classe est volumineuse : plus long est votre code, plus pnible
il sera d'y chercher les donnes initialises en dur.
Dornavant, dans tous les exemples de code venir dans la suite du cours, je mettrai en place de telles constantes.

Inclure automatiquement la JSTL Core toutes vos JSP


Vous le savez, pour pouvoir utiliser les balises de la bibliothqe Core dans vos pages JSP, il est ncessaire de faire intervenir la
directive include en tte de page :
Code : JSP
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

Admettons-le : dans une application, rares seront les vues qui ne ncessiteront pas l'utilisation de balises issues de la JSTL. Afin
d'viter d'avoir dupliquer cette ligne dans l'intgralit de vos vues, il existe un moyen de rendre cette inclusion automatique !
C'est dans le fichier web.xml que vous avez la possibilit de spcifier une telle section :
Code : XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<include-prelude>/WEB-INF/taglibs.jsp</include-prelude>
</jsp-property-group>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

170/345

</jsp-config>
...

Le fonctionnement est trs simple, la balise <jsp-property-group> ne contenant dans notre cas que deux balises :
<url-pattern>, qui permet comme vous vous en doutez de spcifier quels fichiers appliquer l'inclusion
automatique. Ici, j'ai choisi de l'appliquer tous les fichiers JSP de l'application !
<include-prelude>, qui permet de prciser l'emplacement du fichier inclure en tte de chacune des pages
couvertes par le pattern prcdemment dfini. Ici, J'ai nomm ce fichier taglibs.jsp .
Il ne nous reste donc plus qu' crer un fichier taglibs.jsp sous le rpertoire /WEB-INF de notre application, et y placer la
directive taglib que nous souhaitons voir apparatre sur chacune de nos pages JSP :
Code : JSP - Contenu du fichier taglibs.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

Redmarrez Tomcat pour que les modifications apportes au fichier web.xml soient prises en compte, et vous n'aurez dornavant
plus besoin de prciser la directive en haut de vos pages JSP : cela se fera de manire transparente !
Sachez par ailleurs que ce systme est quivalent une inclusion statique, en d'autres termes une directive include <%@
include file="/WEB-INF/taglibs.jsp" %> place en tte de chaque JSP.
Nous n'en avons pas l'utilit ici, mais sachez qu'il est possible avec ce mme systme d'inclure automatiquement un
fichier en fin de page : il faut pour cela prciser le fichier inclure au sein d'une balise <include-coda>, et non plus
<include-prelude> comme nous l'avons fait dans notre exemple. Le principe de fonctionnement reste identique,
seul le nom de la balise diffre.

Formater proprement et automatiquement votre code avec Eclipse


Produire un code propre et lisible est trs important lorsque vous travaillez sur un projet, et c'est d'autant plus vrai dans le cas
d'un projet professionnel et en quipe. Toutefois, harmoniser son style d'criture sur l'ensemble des classes que l'on rdige n'est
pas toujours vident, il est difficile de faire preuve d'une telle rigueur. Pour nous faciliter la tche, Eclipse propose un systme de
formatage automatique du code !

Crer un style de formatage


Sous Eclipse, rendez-vous dans le menu Window > Preferences > Java > Code Style > Formatter, comme indiqu sur la capture
d'cran suivante :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

171/345

Eclipse

format tool.
Le volet de droite de cette fentre est compos de plusieurs blocs :
un lien intitul "Configure Project Specific Settings...", qui vous redirige vers la fentre de configuration pour un projet
en particulier uniquement ;
un formulaire d'dition des profils de formatage existant ;
un cadre d'aperu qui vous montre l'apparence de votre code lorsque le profil actuellement en place est utilis.
Pour modifier le style de formatage par dfaut, il suffit de cliquer sur le bouton Edit.... Vous accdez alors une vaste interface
vous permettant de personnaliser un grand nombre d'options :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

172/345

Options de formatage du code.


Je laisse aux plus motivs d'entre vous le loisir de parcourir les diffrents onglets et de modifier eux-mmes le style de formatage.
Vous devrez pour que vos modifications soient prises en compte changer le nom du profil actuel, dans l'encadr en haut de la
fentre, puis valider les changements en cliquant sur le bouton Apply en bas de fentre.
Pour tous les autres, j'ai cr un modle de formatage prt l'emploi, que je vous propose de mettre en place et d'utiliser pour
formater vos fichiers sources :
=> Tlcharger le fichier format_sdzee.xml (clic droit, puis "Enregistrer sous...")
Une fois le fichier tlcharg, il vous suffit de l'importer dans votre Eclipse en cliquant sur le bouton Import... dans le formulaire
de la premire fentre :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

173/345

Import du

modle de formatage.
Le nom du profil change alors pour format_sdzee, et il vous reste enfin appliquer les changements en cliquant sur le bouton
Apply en bas de fentre.

Utiliser un style de formatage


Maintenant que le profil est en place, vous pouvez formater automatiquement votre code source Java. Pour cela, ouvrez un
fichier Java quelconque de votre projet, et rendez-vous dans le menu Source > Format, ou tapez tout simplement le raccourci
clavier Ctrl + Maj + F. Prenons pour exemple le code de notre servlet Test :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

174/345

Rendu du formatage de la source.


gauche la version non formate, et droite la version aprs formatage. La diffrence n'est pas norme sur un code aussi court,
d'autant plus que le code d'origine tait dj relativement bien organis et indent. Vous pouvez toutefois remarquer quelques
changements arant le code et facilitant sa lecture :
l'alignement des valeurs des constantes en tte de classe ;
l'ajout d'espaces aprs l'ouverture et avant la fermeture de parenthses.

Automatiser le formatage chaque sauvegarde


Nous voil mieux quips, mais il reste un dtail pnible : il nous faut encore taper Ctrl + Maj + F chaque fois que nous
effectuons des modifications dans le code source, afin de conserver un formatage parfait. Comme nous sommes fnants, nous
allons demander Eclipse d'y penser pour nous ! Rendez-vous dans le menu Window > Preferences > Java > Editor > Save
Actions :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

175/345

Formatage automatique.
Comme indiqu dans l'encadr, cochez les cases "Perform the selected actions on save" et "Format source code". Validez les
changements, et c'est termin : votre code source Java sera format automatiquement selon les rgles dfinies dans votre profil,
chaque fois que vous enregistrerez des modifications effectues sur un fichier.
Vous n'avez dornavant plus aucune excuse : votre code doit tre correctement format, organis et indent !

Documentation
Les tutoriaux d'auteurs diffrents vous feront profiter de nouveaux points de vue et angles d'attaque, et les documentations
officielles vous permettront un accs des informations justes et maintenues jour (en principe).

Liens utiles
JSTL 1.1 Tag Reference (un Javadoc-like bien pratique), sur oracle.com
JSP Standard Tag Library, sur java.sun.com

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

176/345

propos de la JSTL, sur stackoverflow.com


Une introduction la JSTL, sur developer.com
Tutoriel sur la JSTL, sur developpez.com
Tutoriel sur les TagLib, sur developpez.com
FAQ propos des TagLib, sur developpez.com
Tutoriel complet sur l'utilisation de la JSTL, sur ibm.com

Vous l'aurez compris, cette liste ne se veut pas exhaustive, et je vous recommande d'aller chercher par vous mme l'information
sur les forums et sites du web. En outre, faites bien attention aux dates de cration des documents que vous lisez : les
ressources primes font lgion sur le web, notamment au sujet de la plate-forme Java EE, en constante volution. N'hsitez
pas demander la communaut sur le forum Java du Site du Zro, si vous ne parvenez pas trouver l'information que vous
cherchez.
Finie la dtente, une partie extrmement importante nous attend : la gestion des formulaires. Accrochez-vous, le rythme va
s'acclrer !

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

177/345

TP Fil rouge - tape 2


Dans ce second opus de notre fil rouge, vous allez appliquer ce que vous avez dcouvert propos de la JSTL Core et des
bonnes pratiques de dveloppement.

Objectifs
Les prcdents chapitres concernant uniquement la vue, vous allez ici principalement vous consacrer la reprise des pages JSP
que vous aviez cres lors du premier TP.
Je vous conseille de repartir sur la base de la correction que je vous ai donne pour la premire tape, cela facilitera
votre comprhension des tapes et corrections venir.

Utilisation de la JSTL
L'objectif est modeste et le programme lger, mais l'important est que vous compreniez ce que vous faites et que vous preniez de
l'aise avec le systme des balises de la JSTL. Je vous demande de :
scuriser contre les failles XSS l'affichage des donnes saisies par l'utilisateur dans vos pages afficherClient.jsp et
afficherCommande.jsp ;
grer dynamiquement les diffrents liens et URL qui interviennent dans le code de vos pages JSP ;
crer un menu, qui ne contiendra pour le moment que deux liens respectivement vers creerClient.jsp et
creerCommande.jsp, et l'intgrer toutes vos pages existantes ;
mettre en place une condition l'affichage du rsultat de la validation : si les donnes ont t correctement saisies, alors
afficher le message de succs et la fiche rcapitulative, sinon afficher uniquement le message d'erreur.

Application des bonnes pratiques


Je vous demande dans le code de vos servlets de mettre en place des constantes, pour remplacer les chanes de caractres
initialises directement au sein du code des mthodes doGet().

Exemples de rendus
Cration de client avec erreurs :

Cration de client sans erreur :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

178/345

Cration de commande avec erreurs :

Cration de commande sans erreur :

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

179/345

Conseils
Utilisation de la JSTL
Je vous donne tout de mme quelques pistes pour vous guider, mais vous devriez tre capables de vous en sortir mme sans lire
ce paragraphe :
pour scuriser l'affichage des donnes saisies, pensez la balise <c:out/> ;
pour la gestion des liens, pensez la balise <c:url/> ;
pour le menu, vous pouvez crer une page menu.jsp que vous placerez dans le rpertoire /inc et que vous inclurez dans
toutes les autres pages grce la balise <c:import/> ;
pour la condition, vous pouvez modifier vos servlets pour qu'elles transmettent vos JSP une information
supplmentaire - pourquoi pas un boolen - afin que celles-ci puissent dterminer si la validation a t effectue avec
succs ou non grce la balise <c:choose/> ou <c:if/>.

Bien videmment, vous n'oublierez pas d'inclure le jar de la JSTL au rpertoire lib de votre projet, afin de rendre les balises
oprationnelles. Voici l'allure de l'arborescence que vous devriez obtenir une fois le TP termin :

Vous pouvez remarquer en encadr les deux nouveaux fichiers intervenant dans votre projet : le fichier jar de la JSTL et la page
menu.jsp.

Application des bonnes pratiques


Il vous suffit ici de remplacer toutes les chanes de caractres utilises directement dans le code de vos servlets par des
constantes dfinies en dehors des mthodes doGet(), comme je vous l'ai montr dans l'avant-dernier chapitre.
C'est tout ce dont vous avez besoin. Au travail !

Correction
www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

180/345

Faible dose de travail cette fois, j'espre que vous avez bien pris le temps de relire les explications concernant les diffrentes
balises mettre en jeu. Encore une fois, ce n'est pas la seule manire de faire, ne vous inquitez pas si vous avez procd
diffremment, le principal est que vous ayez couvert tout ce qu'il fallait couvrir ! Pour que vous puissiez reprer rapidement ce
qui a chang, j'ai surlign les modifications apportes aux codes existants.
Prenez le temps de rflchir, de chercher et coder par vous-mmes. Si besoin, n'hsitez pas relire le sujet ou retourner
lire certains chapitres. La pratique est trs importante, ne vous ruez pas sur la solution !

Code des servlets


Secret (cliquez pour afficher)
Servlet grant le formulaire de cration de client :
Code : Java - com.sdzee.tp.servlets.CreationClient
package com.sdzee.tp.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import com.sdzee.tp.beans.Client;
public class CreationClient extends HttpServlet {
/* Constantes */
public static final String CHAMP_NOM
= "nomClient";
public static final String CHAMP_PRENOM
= "prenomClient";
public static final String CHAMP_ADRESSE
= "adresseClient";
public static final String CHAMP_TELEPHONE =
"telephoneClient";
public static final String CHAMP_EMAIL
= "emailClient";
public static final String ATT_CLIENT
public static final String ATT_MESSAGE
public static final String ATT_ERREUR
public static final String VUE
"/afficherClient.jsp";

= "client";
= "message";
= "erreur";
=

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/*
* Rcupration des donnes saisies, envoyes en tant que
paramtres de
* la requte GET gnre la validation du formulaire
*/
String nom = request.getParameter( CHAMP_NOM );
String prenom = request.getParameter( CHAMP_PRENOM );
String adresse = request.getParameter( CHAMP_ADRESSE );
String telephone = request.getParameter( CHAMP_TELEPHONE
);
String email = request.getParameter( CHAMP_EMAIL );
String message;
boolean erreur;
/*
* Initialisation du message afficher : si un des champs
obligatoires
* du formulaire n'est pas renseign, alors on affiche un message
* d'erreur, sinon on affiche un message de succs

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

181/345

*/

if ( nom.trim().isEmpty() || adresse.trim().isEmpty() ||
telephone.trim().isEmpty() ) {
message = "Erreur - Vous n'avez pas rempli tous les
champs obligatoires. <br> <a href=\"creerClient.jsp\">Cliquez
ici</a> pour accder au formulaire de cration d'un client.";
erreur = true;
} else {
message = "Client cr avec succs !";
erreur = false;
}
/*
* Cration du bean Client et initialisation avec les donnes
rcupres
*/
Client client = new Client();
client.setNom( nom );
client.setPrenom( prenom );
client.setAdresse( adresse );
client.setTelephone( telephone );
client.setEmail( email );
/* Ajout du bean et du message l'objet requte */
request.setAttribute( ATT_CLIENT, client );
request.setAttribute( ATT_MESSAGE, message );
request.setAttribute( ATT_ERREUR, erreur );
/* Transmission la page JSP en charge de l'affichage
des donnes */
this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
}

Servlet grant le formulaire de cration de commande :


Code : Java - com.sdzee.tp.servlets.CreationCommande
package com.sdzee.tp.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.sdzee.tp.beans.Client;
import com.sdzee.tp.beans.Commande;
public class CreationCommande extends HttpServlet {
/* Constantes */
public static final String CHAMP_NOM
"nomClient";
public static final String CHAMP_PRENOM
"prenomClient";
public static final String CHAMP_ADRESSE
"adresseClient";
public static final String CHAMP_TELEPHONE
"telephoneClient";
public static final String CHAMP_EMAIL
"emailClient";

www.siteduzero.com

=
=
=
=
=

Partie 3 : Une bonne vue grce la JSTL

182/345

public static final String


"dateCommande";
public static final String
"montantCommande";
public static final String
"modePaiementCommande";
public static final String
"statutPaiementCommande";
public static final String
"modeLivraisonCommande";
public static final String
"statutLivraisonCommande";

CHAMP_DATE

CHAMP_MONTANT

CHAMP_MODE_PAIEMENT

CHAMP_STATUT_PAIEMENT

CHAMP_MODE_LIVRAISON

CHAMP_STATUT_LIVRAISON =

public static final String ATT_COMMANDE


"commande";
public static final String ATT_MESSAGE
public static final String ATT_ERREUR

public static final String FORMAT_DATE


"dd/MM/yyyy HH:mm:ss";

public static final String VUE


"/afficherCommande.jsp";

= "message";
= "erreur";

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/*
* Rcupration des donnes saisies, envoyes en tant que
paramtres de
* la requte GET gnre la validation du formulaire
*/
String nom = request.getParameter( CHAMP_NOM );
String prenom = request.getParameter( CHAMP_PRENOM );
String adresse = request.getParameter( CHAMP_ADRESSE );
String telephone = request.getParameter( CHAMP_TELEPHONE
);
String email = request.getParameter( CHAMP_EMAIL );
/* Rcupration de la date courante */
DateTime dt = new DateTime();
/* Conversion de la date en String selon le format
choisi */
DateTimeFormatter formatter = DateTimeFormat.forPattern(
FORMAT_DATE );
String date = dt.toString( formatter );
double montant;
try {
/* Rcupration du montant */
montant = Double.parseDouble( request.getParameter(
CHAMP_MONTANT ) );
} catch ( NumberFormatException e ) {
/* Initialisation -1 si le montant n'est pas un
nombre correct */
montant = -1;
}
String modePaiement = request.getParameter(
CHAMP_MODE_PAIEMENT );
String statutPaiement = request.getParameter(
CHAMP_STATUT_PAIEMENT );
String modeLivraison = request.getParameter(
CHAMP_MODE_LIVRAISON );
String statutLivraison = request.getParameter(
CHAMP_STATUT_LIVRAISON );
String message;
boolean erreur;
/*
* Initialisation du message afficher : si un des champs

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

183/345

obligatoires
* du formulaire n'est pas renseign, alors on affiche un message
* d'erreur, sinon on affiche un message de succs
*/
if ( nom.trim().isEmpty() || adresse.trim().isEmpty() ||
telephone.trim().isEmpty() || montant == -1
|| modePaiement.isEmpty() ||
modeLivraison.isEmpty() ) {
message = "Erreur - Vous n'avez pas rempli tous les
champs obligatoires. <br> <a href=\"creerCommande.jsp\">Cliquez
ici</a> pour accder au formulaire de cration d'une commande.";
erreur = true;
} else {
message = "Commande cre avec succs !";
erreur = false;
}
/*
* Cration des beans Client et Commande et initialisation avec
les
* donnes rcupres
*/
Client client = new Client();
client.setNom( nom );
client.setPrenom( prenom );
client.setAdresse( adresse );
client.setTelephone( telephone );
client.setEmail( email );
Commande commande = new Commande();
commande.setClient( client );
commande.setDate( date );
commande.setMontant( montant );
commande.setModePaiement( modePaiement );
commande.setStatutPaiement( statutPaiement );
commande.setModeLivraison( modeLivraison );
commande.setStatutLivraison( statutLivraison );
/* Ajout du bean et du message l'objet requte */
request.setAttribute( ATT_COMMANDE, commande );
request.setAttribute( ATT_MESSAGE, message );
request.setAttribute( ATT_ERREUR, erreur );
/* Transmission la page JSP en charge de l'affichage
des donnes */
this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
}

Code des JSP


Secret (cliquez pour afficher)
Page de cration d'un client :
Code : JSP - /creerClient.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

184/345

<title>Cration d'un client</title>


<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div>
<form method="get" action="<c:url
value="/creationClient"/>">
<fieldset>
<legend>Informations client</legend>
<label for="nomClient">Nom <span
class="requis">*</span></label>
<input type="text" id="nomClient"
name="nomClient" value="" size="30" maxlength="30" />
<br />
<label for="prenomClient">Prenom </label>
<input type="text" id="prenomClient"
name="prenomClient" value="" size="30" maxlength="30" />
<br />
<label for="adresseClient">Adresse de
livraison <span class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="" size="30" maxlength="60" />
<br />
<label for="telephoneClient">Numro de
tlphone <span class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="" size="30" maxlength="30" />
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient"
name="emailClient" value="" size="30" maxlength="60" />
<br />
</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br
/>
</form>
</div>
</body>
</html>

Page de cration d'une commande :


Code : JSP - /creerCommande.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cration d'une commande</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div>
<form method="get" action="<c:url
value="/creationCommande"/>">

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

185/345

<fieldset>
<legend>Informations client</legend>
<label for="nomClient">Nom <span
class="requis">*</span></label>
<input type="text" id="nomClient"
name="nomClient" value="" size="30" maxlength="30" />
<br />
<label for="prenomClient">Prenom </label>
<input type="text" id="prenomClient"
name="prenomClient" value="" size="30" maxlength="30" />
<br />
<label for="adresseClient">Adresse de
livraison <span class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="" size="30" maxlength="60" />
<br />
<label for="telephoneClient">Numro de
tlphone <span class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="" size="30" maxlength="30" />
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient"
name="emailClient" value="" size="30" maxlength="60" />
<br />
</fieldset>
<fieldset>
<legend>Informations commande</legend>
<label for="dateCommande">Date <span
class="requis">*</span></label>
<input type="text" id="dateCommande"
name="dateCommande" value="" size="30" maxlength="30" disabled />
<br />
<label for="montantCommande">Montant <span
class="requis">*</span></label>
<input type="text" id="montantCommande"
name="montantCommande" value="" size="30" maxlength="30" />
<br />
<label for="modePaiementCommande">Mode de
paiement <span class="requis">*</span></label>
<input type="text" id="modePaiementCommande"
name="modePaiementCommande" value="" size="30" maxlength="30" />
<br />
paiement</label>

<label for="statutPaiementCommande">Statut du

<input type="text" id="statutPaiementCommande"


name="statutPaiementCommande" value="" size="30" maxlength="30" />
<br />
<label for="modeLivraisonCommande">Mode de
livraison <span class="requis">*</span></label>
<input type="text" id="modeLivraisonCommande"
name="modeLivraisonCommande" value="" size="30" maxlength="30" />
<br />
la livraison</label>

<label for="statutLivraisonCommande">Statut de

<input type="text"
id="statutLivraisonCommande" name="statutLivraisonCommande"
value="" size="30" maxlength="30" />
<br />

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

/>

186/345

</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br

</form>
</div>
</body>
</html>

Page d'affichage d'un client :


Code : JSP - /afficherClient.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Affichage d'un client</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div id="corps">
<p class="info">${ message }</p>
<c:if test="${ !erreur }">
<p>Nom : <c:out value="${ client.nom }"/></p>
<p>Prenom : <c:out value="${ client.prenom
}"/></p>
<p>Adresse : <c:out value="${ client.adresse
}"/></p>
<p>Numro de tlphone : <c:out value="${
client.telephone }"/></p>
<p>Email : <c:out value="${ client.email }"/></p>
</c:if>
</div>
</body>
</html>

Page d'affichage d'une commande :


Code : JSP - /afficherCommande.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Affichage d'une commande</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div id="corps">
<p class="info">${ message }</p>
<c:if test="${ !erreur }">
<p>Client</p>
<p>Nom : <c:out value="${ commande.client.nom
}"/></p>
<p>Prenom : <c:out value="${
commande.client.prenom }"/></p>

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

187/345

<p>Adresse : <c:out value="${


commande.client.adresse }"/></p>
<p>Numro de tlphone : <c:out value="${
commande.client.telephone }"/></p>
<p>Email : <c:out value="${ commande.client.email
}"/></p>
<p>Commande</p>
<p>Date : <c:out value="${ commande.date }"/></p>
<p>Montant : <c:out value="${ commande.montant
}"/></p>
<p>Mode de paiement : <c:out value="${
commande.modePaiement }"/></p>
<p>Statut du paiement : <c:out value="${
commande.statutPaiement }"/></p>
<p>Mode de livraison : <c:out value="${
commande.modeLivraison }"/></p>
<p>Statut de la livraison : <c:out value="${
commande.statutLivraison }"/></p>
</c:if>
</div>
</body>
</html>

Page contenant le nouveau menu :


Code : JSP - /inc/menu.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<div id="menu">
<p><a href="<c:url value="/creerClient.jsp"/>">Crer un
nouveau client</a></p>
<p><a href="<c:url value="/creerCommande.jsp"/>">Crer une
nouvelle commande</a></p>
</div>

Ajout de styles pour la mise en page du menu :


Code : CSS - /inc/style.css
/* Gnral ------------------------------------------------------------------------------------ */
body, p, legend, label, input {
font: normal 8pt verdana, helvetica, sans-serif;
}
/* Forms -------------------------------------------------------------------------------------- */
fieldset {
padding: 10px;
border: 1px #0568CD solid;
margin: 10px;
}
legend {
font-weight: bold;
color: #0568CD;
}
form label {
float: left;
width: 200px;
margin: 3px 0px 0px 0px;

www.siteduzero.com

Partie 3 : Une bonne vue grce la JSTL

188/345

}
form input {
margin: 3px 3px 0px 0px;
border: 1px #999 solid;
}
form input.sansLabel {
margin-left: 200px;
}
/* Styles et couleurs ------------------------------------------------------------------------- */
.requis {
color: #c00;
}
.erreur {
color: #900;
}
.succes {
color: #090;
}
.info {
font-style: italic;
color: #E8A22B;
}
/* Blocs constituants ------------------------------------------------------------------------- */
div#menu{
border: 1px solid #0568CD;
padding: 10px;
margin: 10px;
}
div#corps{
margin: 10px;
}

Nous y voil enfin : nous sommes capables de crer des vues qui suivent le modle MVC .
Seulement maintenant que nous sommes au point, nous aimerions bien interagir avec notre client : comment rcuprer et grer
les donnes qu'il va nous envoyer ?
Rendez-vous dans la partie suivante, nous avons du pain sur la planche !

www.siteduzero.com

Partie 4 : Une application interactive !

189/345

Partie 4 : Une application interactive !


Il est temps de rellement faire entrer en jeu nos servlets, de donner un sens leur existence : nous allons ici apprendre grer
les informations envoyes par les clients notre application. Et dans une application web, vous le savez dj, qui dit interaction
dit formulaire : cette partie aurait presque pu s'intituler "Le formulaire dans tous ses tats", car nous allons l'examiner sous toutes
les coutures !
Au passage, nous en profiterons pour dcouvrir au travers d'applications pratiques l'utilisation des sessions, des cookies et d'un
nouveau composant cousin de la servlet : le filtre.

Formulaires : le b.a.-ba
Dans cette partie, nous allons littralement faire table rase. Laissons tomber nos prcdents exemples, et attaquons l'tude des
formulaires par quelque chose de plus concret : un formulaire d'inscription. Cration, mise en place, rcupration des donnes,
affichage et vrifications nous attendent !
Bien entendu, nous n'allons pas pouvoir raliser un vrai systme d'inscription de A Z : il nous manque encore pour cela la
gestion des donnes, que nous n'allons dcouvrir que dans la prochaine partie de ce cours. Toutefois, nous pouvons d'ores et
dj raliser proprement tout ce qui concerne les aspects vue, contrle et traitement d'un tel systme. Allons-y !

Mise en place
Je vous propose de mettre en place une base srieuse qui nous servira d'exemple tout au long de cette partie du cours, ainsi que
dans la partie suivante. Plutt que de travailler une nime fois sur un embryon de page sans intrt, je vais tenter ici de vous
placer dans un contexte plus proche du monde professionnel : nous allons travailler de manire propre et organise, et la fin de
ce cours nous aurons produit un exemple utilisable dans une relle application.
Pour commencer, je vous demande de crer un nouveau projet dynamique sous Eclipse. Laissez tomber le bac sable que nous
avions nomm test, et repartez de zro : cela aura le double avantage de vous permettre de construire quelque chose de propre,
et de vous faire pratiquer l'tape de mise en place d'un projet (cration, build-path, bibliothques, etc.). Je vous propose de
nommer ce nouveau projet pro. Si vous ne vous souvenez pas de toutes les tapes suivre, voici un aperu des principaux
crans intervenant dans le processus de mise en place d'un projet :

www.siteduzero.com

Partie 4 : Une application interactive !

190/345

Cration du projet dynamique -

tape 1

www.siteduzero.com

Partie 4 : Une application interactive !

191/345

Cration du projet dynamique -

tape 2

www.siteduzero.com

Partie 4 : Une application interactive !

192/345

Cration du projet dynamique -

tape 3

www.siteduzero.com

Partie 4 : Une application interactive !

193/345

Modification du build-path

www.siteduzero.com

Partie 4 : Une application interactive !

194/345

Modification du serveur de

dploiement - tape 1

www.siteduzero.com

Partie 4 : Une application interactive !

195/345

Modification du serveur de

dploiement - tape 2

www.siteduzero.com

Partie 4 : Une application interactive !

196/345

Arborescence finale du nouveau projet

N'oubliez pas les changements effectuer sur le build-path et le serveur de dploiement, et remarquez bien sur le dernier cran
l'ajout du .jar de la JSTL notre projet, ainsi que la cration des deux packages vides qui accueilleront par la suite nos servlets et
beans.
Revenons maintenant notre base. En apparence, elle consistera en une simple page web contenant un formulaire destin
l'inscription du visiteur sur le site. Ce formulaire proposera :
un champ texte recueillant l'adresse mail de l'utilisateur;
un champ texte recueillant son mot de passe ;
un champ texte recueillant la confirmation de son mot de passe ;
un champ texte recueillant son nom d'utilisateur (optionnel).
Voici un aperu du design que je vous propose de mettre en place :

Formulaire d'inscription

Si vous avez t assidu lors de vos premiers pas, vous devez vous souvenir que nous placerons dornavant toujours nos pages
JSP sous le rpertoire /WEB-INF de l'application, et qu' chaque JSP cre nous associerons une servlet. Je vous ai ainsi prpar
une page JSP charge de l'affichage du formulaire d'inscription, une feuille CSS pour sa mise en forme et une servlet pour
l'accompagner.

JSP & CSS


Voici le code HTML de base du formulaire d'inscription que nous allons utiliser tout au long de cette partie :
Code : JSP - /WEB-INF/inscription.jsp

www.siteduzero.com

Partie 4 : Une application interactive !

197/345

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Inscription</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="inscription">
<fieldset>
<legend>Inscription</legend>
<p>Vous pouvez vous inscrire via ce formulaire.</p>
<label for="email">Adresse email <span
class="requis">*</span></label>
<input type="text" id="email" name="email" value=""
size="20" maxlength="60" />
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<br />
<label for="confirmation">Confirmation du mot de
passe <span class="requis">*</span></label>
<input type="password" id="confirmation"
name="confirmation" value="" size="20" maxlength="20" />
<br />
<label for="nom">Nom d'utilisateur</label>
<input type="text" id="nom" name="nom" value=""
size="20" maxlength="20" />
<br />
<input type="submit" value="Inscription"
class="sansLabel" />
<br />
</fieldset>
</form>
</body>
</html>

Et voici le code de la feuille de style CSS accompagnant ce formulaire :


Code : CSS - /form.css
/* Gnral ------------------------------------------------------------------------------------ */
body, p, legend, label, input {
font: normal 8pt verdana, helvetica, sans-serif;
}
fieldset {
padding: 10px;
border: 1px #0568CD solid;
}
legend {
font-weight: bold;
color: #0568CD;
}
/* Forms -------------------------------------------------------------------------------------- */

www.siteduzero.com

Partie 4 : Une application interactive !

198/345

form label {
float: left;
width: 200px;
margin: 3px 0px 0px 0px;
}
form input {
margin: 3px 3px 0px 0px;
border: 1px #999 solid;
}
form input.sansLabel {
margin-left: 200px;
}
form .requis {
color: #c00;
}

Contrairement la page JSP, la feuille de style ne doit pas tre place sous le rpertoire /WEB-INF ! Eh oui, vous devez vous
souvenir que ce rpertoire a la particularit de cacher ce qu'il contient l'extrieur :
dans le cas d'une page JSP c'est pratique, cela rend les pages inaccessibles directement depuis leur URL et nous permet
de forcer le passage par une servlet.
dans le cas de notre feuille CSS par contre, c'est une autre histoire ! Car ce que vous ne savez peut-tre pas encore, c'est
qu'en ralit lorsque vous accdez une page web sur laquelle est attache une feuille de style, votre navigateur va dans
les coulisses envoyer une requte GET au serveur pour rcuprer silencieusement cette feuille, en se basant sur l'URL
prcise dans la balise <link href="..." />. Et donc fatalement, si vous placez le fichier sous /WEB-INF la
requte va chouer, puisque le fichier sera cach du public et ne sera pas accessible par une URL.
De toute manire, dans la trs grande majorit des cas le contenu d'une feuille CSS est fixe, il ne dpend pas de codes
dynamiques et ne ncessite pas de pr-traitements depuis une servlet comme nous le faisons jusqu' prsent pour nos pages
JSP. Nous pouvons donc rendre nos fichiers CSS accessibles directement aux navigateurs en les plaant dans un rpertoire
public de l'application.
En l'occurrence, ici je l'ai place directement la racine de notre application, dsigne par le rpertoire WebContent dans Eclipse.
Retenez donc bien que tous les lments fixes utiliss par vos pages JSP, comme les feuilles de style CSS, les feuilles de
scripts Javascript ou encore les images, doivent tre placs dans un rpertoire public, et donc pas sous /WEB-INF.
Avant de mettre en place la servlet, penchons-nous un instant sur les deux attributs de la balise <form>.

La mthode
Il est possible d'envoyer les donnes d'un formulaire par deux mthodes diffrentes :
get : les donnes transiteront par l'URL via des paramtres dans une requte HTTP GET. Je vous l'ai dj expliqu, en
raison des limitations de la taille d'une URL cette mthode est peu utilise pour l'envoi de donnes.
post : les donnes ne transiteront cette fois pas par l'URL mais dans le corps d'une requte HTTP POST, l'utilisateur ne les
verra donc pas dans la barre d'adresse de son navigateur.
Malgr leur invisibilit apparente, les donnes envoyes via la mthode POST restent aisment accessibles, et ne sont
donc pas plus scurises qu'avec la mthode GET : nous devrons donc toujours vrifier la prsence et la validit des
paramtres avant de les utiliser. La rgle d'or suivre lorsqu'on dveloppe une application web, c'est de ne jamais
faire confiance l'utilisateur.
Voil donc pourquoi nous utiliserons la plupart du temps la mthode POST pour envoyer les donnes de nos formulaires. En
l'occurrence, nous avons bien prcis <form method="post" ... > dans le code de notre formulaire.

La cible

www.siteduzero.com

Partie 4 : Une application interactive !

199/345

L'attribut action de la balise <form> permet de dfinir la page laquelle seront envoyes les donnes du formulaire. Puisque
nous suivons le modle MVC, vous devez savoir que l'tape suivant l'envoi de donnes par l'utilisateur est le contrle.
Autrement dit, direction la servlet ! C'est donc l'URL permettant de joindre cette servlet, c'est--dire l'URL que vous allez spcifier
dans sa dclaration dans le fichier web.xml, qui doit tre prcise dans le champ action du formulaire. En l'occurrence, nous
avons prcis <form ... action="inscription"> dans le code de notre formulaire, nous devrons donc associer
l'URL /inscription notre servlet dans le mapping du fichier web.xml.
Lanons-nous maintenant, et crons une servlet qui s'occupera de rcuprer les donnes envoyes et de les valider.

La servlet
Voici le code de la servlet accompagnant la JSP qui affiche le formulaire :
Code : Java - com.sdzee.servlets.Inscription
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class Inscription extends HttpServlet {


public static final String VUE = "/WEB-INF/inscription.jsp";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Affichage de la page d'inscription */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
}

Pour le moment, elle se contente d'afficher notre page JSP l'utilisateur lorsqu'elle reoit une requte GET de sa part. Bientt, elle
sera galement capable de grer la rception d'une requte POST, lorsque l'utilisateur enverra les donnes de son formulaire !
Avant d'attaquer le traitement des donnes, voici enfin la configuration de notre servlet dans le fichier web.xml :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>Inscription</servlet-name>
<servlet-class>com.sdzee.servlets.Inscription</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Inscription</servlet-name>
<url-pattern>/inscription</url-pattern>
</servlet-mapping>
</web-app>

Souvenez-vous, l'adresse contenue dans le champ <url-pattern> est relative au contexte de l'application. Puisque nous
avons nomm le contexte de notre projet pro, pour accder la JSP affichant le formulaire d'inscription il faut appeler l'URL
suivante :
Code : URL
http://localhost:8080/pro/inscription

www.siteduzero.com

Partie 4 : Une application interactive !

200/345

Vous devez si tout se passe bien visualiser le formulaire ci-dessous dans votre navigateur :

Formulaire d'inscription

Et voici sous forme d'un schma ce que nous venons de raliser :

L'envoi des donnes


Maintenant que nous avons accs notre page d'inscription, nous pouvons saisir des donnes dans le formulaire et les envoyer
au serveur. Remplissez les champs du formulaire avec un nom d'utilisateur, un mot de passe et une adresse mail de votre choix, et
cliquez sur le bouton d'inscription. Voici la page que vous obtenez alors :

Code d'erreur HTTP 405


Eh oui, nous avons demand un envoi des donnes du formulaire par la mthode POST, mais nous n'avons pas surcharg la
mthode doPost() dans notre servlet, nous avons uniquement crit une mthode doGet(). Par consquent, notre servlet
n'est pas encore capable de traiter une requte POST !
Nous savons donc ce qu'il nous reste faire : il faut implmenter la mthode doPost(). Voici le code de notre servlet modifi :
Code : Java - com.sdzee.servlets.Inscription

www.siteduzero.com

Partie 4 : Une application interactive !

201/345

package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class Inscription extends HttpServlet {


public static final String VUE = "/WEB-INF/inscription.jsp";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Affichage de la page d'inscription */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Traitement des donnes du formulaire */
}
}

Maintenant que nous avons ajout une mthode doPost(), nous pouvons dornavant envoyer les donnes de notre
formulaire, il n'y aura plus d'erreur HTTP !
Par contre, notre mthode doPost() tant vide, nous obtenons bien videmment une simple page blanche en retour...

Contrle : ct servlet

Maintenant que notre formulaire est accessible l'utilisateur et que la servlet en charge de son contrle est en place, nous
pouvons nous attaquer la vrification des donnes envoyes par le client.
Que souhaitons-nous vrifier ?

Nous travaillons sur un formulaire d'inscription qui contient quatre champs de type <input>, cela ne va pas tre bien
compliqu. Voici ce que je vous propose de vrifier :
que le champ obligatoire email n'est pas vide et qu'il contient une adresse mail valide ;
que les champs obligatoires mot de passe et confirmation ne sont pas vides, qu'ils contiennent au moins 3 caractres, et
qu'ils sont gaux ;
que le champ facultatif nom, s'il est rempli, contienne au moins 3 caractres.
Nous allons confier ces tches trois mthodes distinctes :
une mthode validationEmail(), charge de valider l'adresse mail saisie ;
une mthode validationMotsDePasse(), charge de valider les mots de passe saisis ;
une mthode validationNom(), charge de valider le nom d'utilisateur saisi.
Voici donc le code modifi de notre servlet, impliquant la mthode doPost(), des nouvelles constantes et les mthodes de
validation cres pour l'occasion, en charge de rcuprer le contenu des champs du formulaire et de les faire valider :
Code : Java - com.sdzee.servlets.Inscription
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

www.siteduzero.com

Partie 4 : Une application interactive !

202/345

public class Inscription extends HttpServlet {


public static final String VUE = "/WEB-INF/inscription.jsp";
public static final String CHAMP_EMAIL = "email";
public static final String CHAMP_PASS = "motdepasse";
public static final String CHAMP_CONF = "confirmation";
public static final String CHAMP_NOM = "nom";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Affichage de la page d'inscription */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Rcupration des champs du formulaire. */
String email = request.getParameter( CHAMP_EMAIL );
String motDePasse = request.getParameter( CHAMP_PASS );
String confirmation = request.getParameter( CHAMP_CONF );
String nom = request.getParameter( CHAMP_NOM );

try {
validationEmail( email );
validationMotsDePasse( motDePasse, confirmation );
validationNom( nom );
} catch (Exception e) {
/* Grer les erreur de validation ici. */
}

private void validationEmail( String email ) throws Exception{}


private void validationMotsDePasse( String motDePasse, String
confirmation ) throws Exception{}
private void validationNom( String nom ) throws Exception{}
}

J'ai surlign dans le code la partie en charge de la rcupration des champs du formulaire : il s'agit tout simplement d'appels la
mthode request.getParameter(). Il nous reste maintenant implmenter nos trois dernires mthodes de validation,
qui sont vides pour le moment. Voil un premier jet de ce que cela pourrait donner :
Code : Java - com.sdzee.servlets.Inscription
...
/**
* Valide l'adresse mail saisie.
*/
private void validationEmail( String email ) throws Exception {
if ( email != null && email.trim().length() != 0 ) {
if ( !email.matches(
"([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)" ) ) {
throw new Exception( "Merci de saisir une adresse mail
valide." );
}
} else {
throw new Exception( "Merci de saisir une adresse mail." );
}
}
/**
* Valide les mots de passe saisis.
*/
private void validationMotsDePasse( String motDePasse, String
confirmation ) throws Exception{
if (motDePasse != null && motDePasse.trim().length() != 0 &&

www.siteduzero.com

Partie 4 : Une application interactive !

203/345

confirmation != null && confirmation.trim().length() != 0) {


if (!motDePasse.equals(confirmation)) {
throw new Exception("Les mots de passe entrs sont
diffrents, merci de les saisir nouveau.");
} else if (motDePasse.trim().length() < 3) {
throw new Exception("Les mots de passe doivent contenir
au moins 3 caractres.");
}
} else {
throw new Exception("Merci de saisir et confirmer votre mot
de passe.");
}
}
/**
* Valide le nom d'utilisateur saisi.
*/
private void validationNom( String nom ) throws Exception {
if ( nom != null && nom.trim().length() < 3 ) {
throw new Exception( "Le nom d'utilisateur doit contenir au
moins 3 caractres." );
}
}

Je ne dtaille pas le code de ces trois courtes mthodes. Si vous ne comprenez pas leur fonctionnement, vous devez
imprativement revenir par vous-mmes sur ces notions basiques du langage Java avant de continuer ce tutoriel.
J'ai ici fait en sorte que dans chaque mthode, lorsqu'une erreur de validation se produit, le code envoie une exception contenant
un message explicitant l'erreur. Ce n'est pas la seule solution envisageable, mais c'est une solution qui a le mrite de tirer parti de
la gestion des exceptions en Java. ce niveau, un peu de rflexion sur la conception de notre systme de validation s'impose ici
:
Que faire de ces exceptions envoyes ?

Ou en d'autres termes, quelles informations souhaitons-nous renvoyer l'utilisateur en cas d'erreur ? Pour un formulaire
d'inscription, a priori nous aimerions bien que l'utilisateur soit au courant du succs ou de l'chec de l'inscription, et en cas
d'chec qu'il soit inform des erreurs commises sur les champs posant problme.
Comment procder ? L encore, il y a bien des manires de faire. Je vous propose ici le mode de fonctionnement suivant :
une chane resultat contenant le statut final de la validation des champs ;
une map erreurs contenant les ventuels messages d'erreur renvoys par nos diffrentes mthodes se chargeant de la
validation des champs. Une HashMap convient trs bien dans ce cas d'utilisation : en l'occurrence, la cl sera le nom du
champ et la valeur sera le message d'erreur correspondant.
Mettons tout cela en musique, toujours dans la mthode doPost() de notre servlet :
Code : Java - com.sdzee.servlets.Inscription
package com.sdzee.servlets;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class Inscription extends HttpServlet {


public static final String VUE = "/WEB-INF/inscription.jsp";
public static final String CHAMP_EMAIL = "email";

www.siteduzero.com

Partie 4 : Une application interactive !

204/345

public static final String CHAMP_PASS = "motdepasse";


public static final String CHAMP_CONF = "confirmation";
public static final String CHAMP_NOM = "nom";
public static final String ATT_ERREURS = "erreurs";
public static final String ATT_RESULTAT = "resultat";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Affichage de la page d'inscription */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
String resultat;
Map<String, String> erreurs = new HashMap<String, String>();
/* Rcupration des champs du formulaire. */
String email = request.getParameter( CHAMP_EMAIL );
String motDePasse = request.getParameter( CHAMP_PASS );
String confirmation = request.getParameter( CHAMP_CONF );
String nom = request.getParameter( CHAMP_NOM );
/* Validation du champ email. */
try {
validationEmail( email );
} catch (Exception e) {
erreurs.put( CHAMP_EMAIL, e.getMessage() );
}
/* Validation des champs mot de passe et confirmation. */
try {
validationMotsDePasse( motDePasse, confirmation );
} catch (Exception e) {
erreurs.put( CHAMP_PASS, e.getMessage() );
}
/* Validation du champ nom. */
try {
validationNom( nom );
} catch (Exception e) {
erreurs.put( CHAMP_NOM, e.getMessage() );
}
/* Initialisation du rsultat global de la validation. */
if( erreurs.isEmpty() ){
resultat = "Succs de l'inscription.";
} else {
resultat = "chec de l'inscription.";
}
/* Stockage du rsultat et des messages d'erreur dans l'objet
request */
request.setAttribute( ATT_ERREURS, erreurs );
request.setAttribute( ATT_RESULTAT, resultat );
*/

/* Transmission de la paire d'objets request/response notre JSP

this.getServletContext().getRequestDispatcher( VUE ).forward(


request, response );
}
}

...

J'ai surlign les modifications importantes du code pour que vous visualisiez bien ce qui intervient dans ce processus de gestion
des exceptions :

www.siteduzero.com

Partie 4 : Une application interactive !

205/345

chaque appel une mthode de validation d'un champ est entoure d'un bloc try/catch ;
chaque entre dans un catch, c'est--dire ds lors qu'une mthode de validation envoie une exception, on ajoute la
map erreurs le message de description inclus dans l'exception courante, avec pour cl l'intitul du champ du formulaire
concern ;
le message resultat contenant le rsultat global de la validation est initialis selon que la map erreurs contient des
messages d'erreurs ou non ;
les deux objets erreurs et resultat sont enfin inclus en tant qu'attributs la requte avant l'appel final la vue.
Le contrle des donnes dans notre servlet est maintenant fonctionnel : avec les donnes que nous transmettons notre JSP,
nous pouvons y dterminer si des erreurs de validation ont eu lieu et sur quels champs.

Affichage : ct JSP
Ce qu'il nous reste maintenant raliser, c'est l'affichage de nos diffrents messages au sein de la page JSP, aprs que l'utilisateur
a saisi et envoy ses donnes. Voici ce que je vous propose :
1. En cas d'erreur, affichage du message d'erreur ct de chacun des champs concerns.
2. R-affichage dans les champs <input> des donnes auparavant saisies par l'utilisateur.
3. Affichage du rsultat de l'inscription en bas du formulaire.

1. Afficher les messages d'erreurs


L'attribut erreurs que nous recevons de la servlet ne contient des messages concernant les diffrents champs de notre
formulaire que si des erreurs ont t rencontres lors de la validation de leur contenu, c'est--dire uniquement si des exceptions
ont t envoyes. Ainsi, il nous suffit d'afficher les entres de la map correspondant chacun des champs email, motdepasse,
confirmation et nom :
Code : JSP - /WEB-INF/inscription.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Inscription</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="inscription">
<fieldset>
<legend>Inscription</legend>
<p>Vous pouvez vous inscrire via ce formulaire.</p>
<label for="email">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email" value=""
size="20" maxlength="60" />
<span class="erreur">${erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span class="erreur">${erreurs['motdepasse']}</span>
<br />
<label for="confirmation">Confirmation du mot de
passe <span class="requis">*</span></label>
<input type="password" id="confirmation"
name="confirmation" value="" size="20" maxlength="20" />
<span class="erreur">${erreurs['confirmation']}</span>
<br />
<label for="nom">Nom d'utilisateur</label>
<input type="text" id="nom" name="nom" value=""
size="20" maxlength="20" />

www.siteduzero.com

Partie 4 : Une application interactive !

206/345

<span class="erreur">${erreurs['nom']}</span>
<br />
<input type="submit" value="Inscription"
class="sansLabel" />
<br />
</fieldset>
</form>
</body>
</html>

Vous retrouvez ici l'utilisation des crochets pour accder aux entres de la Map, comme nous l'avions dj fait lors de notre
apprentissage de la JSTL. De cette manire, si aucun message ne correspond dans la map un champ du formulaire donn, c'est
qu'il n'y a pas eu d'erreur lors de sa validation ct serveur et dans ce cas la balise <span> sera vide et aucun message ne sera
affich l'utilisateur. Comme vous pouvez le voir, j'en ai profit pour ajouter un style notre feuille form.css, afin de mettre en
avant les erreurs :
Code : CSS
form .erreur {
color: #900;
}

Vous pouvez dornavant faire le test : remplissez votre formulaire avec des donnes errones (une adresse mail invalide, un nom
d'utilisateur trop court ou des mots de passe diffrents, par exemple) et contemplez le rsultat ! Ci-dessous, le rendu attendu
lorsque vous entrez un nom d'utilisateur trop court :

Erreur de validation du formulaire

2. R-afficher les donnes saisies par l'utilisateur


Comme vous le constatez sur cette dernire image, les donnes saisies par l'utilisateur avant validation du formulaire
disparaissent des champs aprs validation. En ce qui concerne les champs mot de passe et confirmation, c'est trs bien ainsi :
aprs une erreur de validation, il est courant de demander l'utilisateur de saisir nouveau cette information sensible. Dans le
cas du nom et de l'adresse mail par contre, ce n'est vraiment pas ergonomique et nous allons tcher de les faire rapparatre. Pour
cette tape, nous pourrions tre tents de simplement r-afficher directement ce qu'a saisi l'utilisateur dans chacun des champs
"value" des <input> du formulaire. En effet, nous savons que ces donnes sont directement accessibles via l'objet implicite
param, qui donne accs aux paramtres de la requte HTTP. Le problme, et c'est un problme de taille, c'est qu'en procdant
ainsi nous nous exposons aux failles XSS. Souvenez-vous, je vous en ai dj parl lorsque nous avons dcouvert la balise
<c:out> de la JSTL !
Quel est le problme exactement ?

Ok... Puisque vous semblez amnsique et sceptique, faisons comme si de rien n'tait, et r-affichons le contenu des paramtres
de la requte HTTP (c'est--dire le contenu saisi par l'utilisateur dans les champs <input> du formulaire) en y accdant
directement via l'objet implicite param :

www.siteduzero.com

Partie 4 : Une application interactive !

207/345

Code : JSP - /WEB-INF/inscription.jsp


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Inscription</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="inscription">
<fieldset>
<legend>Inscription</legend>
<p>Vous pouvez vous inscrire via ce formulaire.</p>
<label for="email">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email" value="${param.email}"
size="20" maxlength="60" />
<span class="erreur">${erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span class="erreur">${erreurs['motdepasse']}</span>
<br />
<label for="confirmation">Confirmation du mot de
passe <span class="requis">*</span></label>
<input type="password" id="confirmation"
name="confirmation" value="" size="20" maxlength="20" />
<span
class="erreur">${erreurs['confirmation']}</span>
<br />
<label for="nom">Nom d'utilisateur</label>
<input type="text" id="nom" name="nom" value="${param.nom}"
size="20" maxlength="20" />
<span class="erreur">${erreurs['nom']}</span>
<br />
<input type="submit" value="Inscription"
class="sansLabel" />
<br />
</fieldset>
</form>
</body>
</html>

Faites alors nouveau le test en remplissant et validant votre formulaire. Dornavant, les donnes que vous avez entres sont
bien prsentes dans les champs du formulaire aprs validation :

www.siteduzero.com

Partie 4 : Une application interactive !

208/345

Erreur de validation du formulaire avec affichage des donnes saisies


En apparence a tient la route, mais je vous ai lourdement averti : en procdant ainsi, votre code est vulnrable aux failles XSS .
Vous voulez un exemple ? Remplissez le champ nom d'utilisateur par le contenu suivant : ">Bip bip ! . Validez ensuite votre
formulaire, et contemplez alors ce triste et dsagrable rsultat :

Erreur de validation du formulaire avec faille XSS

Que s'est-il pass ?

Une faille XSS, pardi ! Eh oui, ct serveur, le contenu que vous avez saisi dans le champ du formulaire a t copi tel quel dans
le code gnr par notre JSP. Il a ensuite t interprt par le navigateur ct client, qui a alors naturellement considr que le
guillemet ( " ) et le chevron ( > ) contenus en dbut de saisie correspondaient la fermeture de la balise <input> ! Si vous tes
encore dans le flou, voyez plutt le code HTML produit sur la ligne posant problme :
Code : HTML
<input type="text" id="nom" name="nom" value="">Bip bip !" size="20"
maxlength="20" />

Vous devez maintenant comprendre le problme : le contenu de notre champ a t copi/coll tel quel dans la source de notre
fichier HTML final, lors de l'interprtation par le serveur de l'expression EL que nous avons mise en place (c'est--dire
${param.nom}). Et logiquement, puisque le navigateur ferme la balise <input> prmaturment, notre joli formulaire s'en
retrouve dfigur. Alors certes, ici ce n'est pas bien grave, je n'ai fait que casser l'affichage de la page. Mais vous devez savoir
qu'en utilisant ce type de failles, il est possible de causer bien plus de dommages, notamment en injectant du code Javascript
dans la page l'insu du client.
Je vous le rpte : la rgle d'or, c'est de ne jamais faire confiance l'utilisateur.

Pour pallier ce problme, il suffit d'utiliser la balise <c:out> de la JSTL Core pour procder l'affichage des donnes.

www.siteduzero.com

Partie 4 : Une application interactive !

209/345

Voici ce que donne alors le code modifi de notre JSP :


Code : JSP - /WEB-INF/inscription.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Inscription</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="inscription">
<fieldset>
<legend>Inscription</legend>
<p>Vous pouvez vous inscrire via ce formulaire.</p>
<label for="email">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email" value="<c:out
value="${param.email}"/>" size="20" maxlength="60" />
<span class="erreur">${erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span class="erreur">${erreurs['motdepasse']}</span>
<br />
<label for="confirmation">Confirmation du mot de
passe <span class="requis">*</span></label>
<input type="password" id="confirmation"
name="confirmation" value="" size="20" maxlength="20" />
<span
class="erreur">${erreurs['confirmation']}</span>
<br />
<label for="nom">Nom d'utilisateur</label>
<input type="text" id="nom" name="nom" value="<c:out
value="${param.nom}"/>" size="20" maxlength="20" />
<span class="erreur">${erreurs['nom']}</span>
<br />
<input type="submit" value="Inscription"
class="sansLabel" />
<br />
</fieldset>
</form>
</body>
</html>

La balise <c:out> se chargeant par dfaut d'chapper les caractres spciaux, le problme est rgl. Notez l'ajout de la directive
taglib en haut de page, pour que notre JSP puisse utiliser les balises de la JSTL Core. Faites nouveau le test avec le nom
d'utilisateur prcdent, et vous obtiendrez bien cette fois :

www.siteduzero.com

Partie 4 : Une application interactive !

210/345

Erreur de validation du formulaire sans faille XSS


Dornavant, l'affichage n'est plus cass, et si nous regardons le code HTML gnr, nous observons bien la transformation du "
et du > en leurs codes HTML respectifs par la balise <c:out> :
Code : HTML
<input type="text" id="nom" name="nom" value="&#034;&gt;Bip bip !"
size="20" maxlength="20" />

Ainsi, le navigateur de l'utilisateur reconnat que les caractres " et > font bien partie du contenu du champ, et qu'ils ne doivent
pas tre interprts en tant qu'lments de fermeture de la balise <input> !
l'avenir, n'oubliez jamais ceci : protgez toujours les donnes que vous affichez l'utilisateur !

3. Afficher le rsultat final de l'inscription


Il ne nous reste maintenant qu' confirmer le statut de l'inscription. Pour ce faire, il suffit d'afficher l'entre resultat de la map
dans laquelle nous avons initialis le message :
Code : JSP - /WEB-INF/inscription.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Inscription</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="inscription">
<fieldset>
<legend>Inscription</legend>
<p>Vous pouvez vous inscrire via ce formulaire.</p>
<label for="email">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email"
value="<c:out value="${param.email}"/>" size="20" maxlength="60" />
<span class="erreur">${erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"

www.siteduzero.com

Partie 4 : Une application interactive !

211/345

name="motdepasse" value="" size="20" maxlength="20" />


<span class="erreur">${erreurs['motdepasse']}</span>
<br />
<label for="confirmation">Confirmation du mot de
passe <span class="requis">*</span></label>
<input type="password" id="confirmation"
name="confirmation" value="" size="20" maxlength="20" />
<span
class="erreur">${erreurs['confirmation']}</span>
<br />
<label for="nom">Nom d'utilisateur</label>
<input type="text" id="nom" name="nom" value="<c:out
value="${param.nom}"/>" size="20" maxlength="20" />
<span class="erreur">${erreurs['nom']}</span>
<br />
<input type="submit" value="Inscription"
class="sansLabel" />
<br />
<p class="${empty erreurs ? 'succes' : 'erreur'}">${resultat}</p>
</fieldset>
</form>
</body>
</html>

Vous remarquez ici l'utilisation d'un test ternaire sur notre map erreurs au sein de la premire expression EL mise en place, afin de
dterminer la classe CSS appliquer au paragraphe : si la map erreurs est vide, alors cela signifie qu'aucune erreur n'a eu lieu et
on utilise le style nomm succes, et sinon on utilise le style erreur. J'en ai en effet profit pour ajouter un dernier style notre
feuille form.css, pour mettre en avant le succs de l'inscription :
Code : CSS
form .succes {
color: #090;
}

Et sous vos yeux bahis, voici le rsultat final en cas de succs et d'erreur :

Succes de la validation du formulaire

www.siteduzero.com

Partie 4 : Une application interactive !

212/345

Erreur dans la validation du formulaire


Pour terminer, voici sous forme d'un schma ce que nous venons de raliser :

Maintenant que notre base est fonctionnelle, prenons le temps de rflchir ce que nous avons cr, et ce que MVC nous
impose de modifier !

www.siteduzero.com

Partie 4 : Une application interactive !

213/345

Formulaires : la mode MVC


Le modle MVC est trs clair sur ce point : c'est le modle qui doit s'occuper de traiter les donnes. Le contrleur doit avoir pour
unique but d'aiguiller les requtes entrantes et d'appeler les ventuels traitements correspondants. Nous devons donc nous
pencher sur la conception que nous venons de mettre en place afin d'en identifier les dfauts, et la rectifier afin de suivre les
recommandations MVC.

Analyse de notre conception


La base que nous avons ralise souffre de plusieurs maux :
la rcupration et le traitement des donnes sont effectus directement au sein de la servlet. Or nous savons que d'aprs
MVC, la servlet est un contrleur, et n'est donc pas cense intervenir directement sur les donnes, elle doit uniquement
aiguiller les requtes entrantes vers les traitements correspondants ;
aucun modle (bean ou objet mtier) n'intervient dans le systme mis en place ! Pourtant, nous savons que d'aprs MVC,
les donnes sont reprsentes dans le modle par des objets...
Pour rappel, voici le schma reprsentant ce que nous avons cr :

Et voici le schma reprsentant ce vers quoi nous souhaitons parvenir :

Nous allons donc reprendre notre systme d'inscription pour y mettre en place un modle :
1. cration d'un bean qui enregistre les donnes saisies et valides ;
2. cration d'un objet mtier comportant les mthodes de rcupration/conversion/validation des contenus des champs du
formulaire ;
3. modification de la servlet pour qu'elle n'intervienne plus directement sur les donnes de la requte, mais aiguille
simplement la requte entrante ;
4. modification de la JSP pour qu'elle s'adapte au modle frachement cr.

www.siteduzero.com

Partie 4 : Une application interactive !

214/345

Cration du modle
L'utilisateur
Pour reprsenter un utilisateur dans notre modle, nous allons naturellement crer un bean nomm Utilisateur et plac dans le
package com.sdzee.beans, contenant trois champs de type String : email, motDePasse et nom. Si vous ne vous
souvenez plus des rgles respecter lors de la cration d'un bean, n'hsitez pas relire le chapitre qui y est ddi. Voici le rsultat
attendu :
Code : Java - com.sdzee.beans.Utilisateur
package com.sdzee.beans;
public class Utilisateur {
private String email;
private String motDePasse;
private String nom;
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setMotDePasse(String motDePasse) {
this.motDePasse = motDePasse;
}
public String getMotDePasse() {
return motDePasse;
}

public void setNom(String nom) {


this.nom = nom;
}
public String getNom() {
return nom;
}

C'est tout ce dont nous avons besoin pour reprsenter les donnes d'un utilisateur dans notre application.
Dans notre formulaire, il y a un quatrime champ : la confirmation du mot de passe. Pourquoi ne stockons-nous pas
cette information dans notre bean ?
Tout simplement parce que ce bean ne reprsente pas le formulaire, il reprsente un utilisateur. Et un utilisateur final, il a un mot
de passe et point barre : la confirmation est une information temporaire propre l'tape d'inscription seulement, il n'y a par
consquent aucun intrt la stocker dans notre modle.

Le formulaire
Maintenant, il nous faut crer dans notre modle un objet "mtier", c'est--dire un objet charg de traiter les donnes envoyes
par le client via le formulaire. Cet objet va dans notre cas devoir contenir :
les constantes identifiant les champs du formulaire ;
la chane resultat et la map erreurs que nous avions mises en place dans la servlet ;
la logique de validation que nous avions utilise dans la mthode doPost() de la servlet ;
les trois mthodes de validation que nous avions cres dans la servlet.
Nous allons donc dporter la majorit du code que nous avions crit dans notre servlet dans cet objet mtier, en l'adaptant afin
de le faire interagir avec notre bean frachement cr. Nous allons nommer cet objet InscriptionForm, et le placer dans un
nouveau package com.sdzee.forms :

www.siteduzero.com

Partie 4 : Une application interactive !

215/345

Code : Java - com.sdzee.forms.InscriptionForm


package com.sdzee.forms;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public final class
private static
private static
private static
private static

InscriptionForm {
final String CHAMP_EMAIL
final String CHAMP_PASS
final String CHAMP_CONF
final String CHAMP_NOM

private String
resultat;
private Map<String, String> erreurs
String>();

=
=
=
=

"email";
"motdepasse";
"confirmation";
"nom";

= new HashMap<String,

public String getResultat() {


return resultat;
}
public Map<String, String> getErreurs() {
return erreurs;
}
public Utilisateur inscrireUtilisateur( HttpServletRequest
request ) {
String email = getValeurChamp( request, CHAMP_EMAIL );
String motDePasse = getValeurChamp( request, CHAMP_PASS );
String confirmation = getValeurChamp( request, CHAMP_CONF );
String nom = getValeurChamp( request, CHAMP_NOM );
Utilisateur utilisateur = new Utilisateur();
try {
validationEmail( email );
} catch ( Exception e ) {
setErreur( CHAMP_EMAIL, e.getMessage() );
}
utilisateur.setEmail( email );
try {
validationMotsDePasse( motDePasse, confirmation );
} catch ( Exception e ) {
setErreur( CHAMP_PASS, e.getMessage() );
setErreur( CHAMP_CONF, null );
}
utilisateur.setMotDePasse( motDePasse );
try {
validationNom( nom );
} catch ( Exception e ) {
setErreur( CHAMP_NOM, e.getMessage() );
}
utilisateur.setNom( nom );
if ( erreurs.isEmpty() ) {
resultat = "Succs de l'inscription.";
} else {
resultat = "chec de l'inscription.";
}
return utilisateur;
}
private void validationEmail( String email ) throws Exception {
if ( email != null ) {

www.siteduzero.com

Partie 4 : Une application interactive !

216/345

if ( !email.matches(
"([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)" ) ) {
throw new Exception( "Merci de saisir une adresse
mail valide." );
}
} else {
throw new Exception( "Merci de saisir une adresse mail."
);
}
}
private void validationMotsDePasse( String motDePasse, String
confirmation ) throws Exception {
if ( motDePasse != null && confirmation != null ) {
if ( !motDePasse.equals( confirmation ) ) {
throw new Exception( "Les mots de passe entrs sont
diffrents, merci de les saisir nouveau." );
} else if ( motDePasse.length() < 3 ) {
throw new Exception( "Les mots de passe doivent
contenir au moins 3 caractres." );
}
} else {
throw new Exception( "Merci de saisir et confirmer votre
mot de passe." );
}
}
private void validationNom( String nom ) throws Exception {
if ( nom != null && nom.length() < 3 ) {
throw new Exception( "Le nom d'utilisateur doit contenir
au moins 3 caractres." );
}
}
/*
* Ajoute un message correspondant au champ spcifi la map des
erreurs.
*/
private void setErreur( String champ, String message ) {
erreurs.put( champ, message );
}
/*
* Mthode utilitaire qui retourne null si un champ est vide, et son
contenu
* sinon.
*/
private static String getValeurChamp( HttpServletRequest request,
String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur.trim();
}
}
}

J'ai surlign pour vous dans le code les ajouts qui ont t effectus. Vous remarquerez qu'au final, il y a trs peu de changements
:
ajout de getters publics pour les attributs privs resultat et erreurs, afin de les rendre accessibles depuis notre JSP via
des expressions EL ;
la logique de validation a t regroupe dans une mthode inscrireUtilisateur(), qui retourne un bean
Utilisateur ;
la mthode utilitaire getValeurChamp() se charge dsormais de vrifier si le contenu d'un champ est vide ou non, ce
qui nous permet aux lignes 65, 75 et 87 de ne plus avoir effectuer la vrification sur la longueur des chanes, et de
simplement vrifier si elles sont null ;

www.siteduzero.com

Partie 4 : Une application interactive !

217/345

dans les blocs catch englobant la validation de chaque champ du formulaire, nous utilisons dsormais une mthode
setErreur() qui se charge de mettre jour la map erreurs en cas d'envoi d'une exception ;
aprs la validation de chaque champ du formulaire, nous procdons dornavant l'initialisation de la proprit
correspondante dans le bean Utilisateur, peu importe le rsultat de la validation (lignes 38, 46 et 53).
Voil tout ce qu'il est ncessaire de mettre en place dans notre modle. Prochaine tape : il nous faut nettoyer notre servlet !
Le dcoupage en mthodes via setErreur() et getValeurChamp() n'est pas une obligation, mais puisque
nous avons dplac notre code dans un objet mtier, autant en profiter pour coder un peu plus proprement.

Reprise de la servlet
Puisque nous avons dport la majorit du code prsent dans notre servlet vers le modle, nous pouvons l'purer grandement !
Il nous suffit d'instancier un objet mtier responsable du traitement du formulaire, et de lui passer la requte courante en appelant
sa mthode inscrireUtilisateur() :
Code : Java - com.sdzee.servlets.Inscription
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import com.sdzee.beans.Utilisateur;
import com.sdzee.forms.InscriptionForm;
public class Inscription extends HttpServlet {
public static final String ATT_USER = "utilisateur";
public static final String ATT_FORM = "form";
public static final String VUE = "/WEB-INF/inscription.jsp";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Affichage de la page d'inscription */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Prparation de l'objet formulaire */
InscriptionForm form = new InscriptionForm();
/* Appel aux traitement et validation de la requte, et
rcupration du bean en rsultant */
Utilisateur utilisateur = form.inscrireUtilisateur( request );
/* Stockage du formulaire et du bean dans l'objet request */
request.setAttribute( ATT_FORM, form );
request.setAttribute( ATT_USER, utilisateur );
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
}

Aprs initialisation de notre objet mtier, la seule chose que notre servlet effectue est un appel la mthode
inscrireUtilisateur() qui lui retourne alors un bean Utilisateur. Elle stocke finalement ces deux objets dans l'objet
requte afin de rendre accessibles la JSP les donnes valides et les messages d'erreur retourns.
Dornavant, notre servlet joue bien uniquement le rle d'aiguilleur : elle contrle les donnes, en se contentant

www.siteduzero.com

Partie 4 : Une application interactive !

218/345

d'appeler les traitements prsents dans le modle. Elle ne fait que transmettre la requte un objet mtier, aucun
moment elle n'agit directement sur ses donnes.

doGet() n'est pas doPost(), et vice-versa !


Avant de passer la suite, je tiens vous signaler une mauvaise pratique, tristement trs couramment rencontre sur le web.
Dans normment d'exemples de servlets, vous pourrez trouver ce genre de codes :
Code : Java - Exemple de mauvaise pratique dans une servlet
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class ExempleServlet extends HttpServlet {


public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException {
/* Ne fait rien d'autre qu'appeler une JSP */
this.getServletContext().getRequestDispatcher( "/page.jsp"
).forward( request, response );
}
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException {
/**
* Ici ventuellement des traitements divers, puis au lieu
* d'appeler tout simplement un forwarding...
*/
doGet(request, response);
}
}

Vous comprenez ce qui a t ralis dans cet exemple ? Puisque la mthode doGet() ne fait rien d'autre qu'appeler la vue, le
dveloppeur n'a rien trouv de mieux que d'appeler doGet() depuis la mthode doPost() pour raliser le forwarding vers la
vue... Eh bien cette manire de faire, dans une application qui respecte MVC, est totalement dnue de sens ! Si vous souhaitez
que votre servlet ralise la mme chose quelque soit le type de la requte HTTP reue, alors :
soit vous surchargez directement la mthode service() de la classe mre HttpServlet, afin qu'elle ne redirige plus
les requtes entrantes vers les diffrentes mthodes doXXX() de votre servlet. Vous n'aurez ainsi plus implmenter
doPost() et doGet() dans votre servlet, et pourrez directement implmenter un traitement unique dans la mthode
service().
soit vous faites en sorte que vos mthodes doGet() et doPost() appellent une troisime et mme mthode, qui
effectuera un traitement commun toutes les requtes entrantes.
Quel que soit votre choix parmi ces solutions, cela sera toujours mieux que d'crire que doGet() appelle doPost(), ou viceversa !
Pour rsumer, retenez bien que croiser ainsi les appels est une mauvaise pratique, qui complique la lisibilit et la
maintenance du code de votre application !

Reprise de la JSP
La dernire tape de notre mise niveau est la modification des appels aux diffrents attributs au sein de notre page JSP. En effet,
auparavant notre servlet transmettait directement la chane resultat et la map erreurs notre page, ce qui impliquait que :
nous accdions directement ces attributs via nos expressions EL ;
nous accdions aux donnes saisies par lutilisateur via l'objet implicite param.

www.siteduzero.com

Partie 4 : Une application interactive !

219/345

Dornavant, notre servlet transmet notre bean et notre objet mtier notre page, objets qui leur tour contiennent les donnes
saisies, le rsultat et les erreurs. Ainsi, nous allons devoir modifier nos expressions EL afin qu'elles accdent aux informations
travers nos deux nouveaux objets :
Code : JSP - /WEB-INF/inscription.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Inscription</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="inscription">
<fieldset>
<legend>Inscription</legend>
<p>Vous pouvez vous inscrire via ce formulaire.</p>
<label for="email">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email" value="<c:out
value="${utilisateur.email}"/>" size="20" maxlength="60" />
<span class="erreur">${form.erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span class="erreur">${form.erreurs['motdepasse']}</span>
<br />
<label for="confirmation">Confirmation du mot de
passe <span class="requis">*</span></label>
<input type="password" id="confirmation"
name="confirmation" value="" size="20" maxlength="20" />
<span class="erreur">${form.erreurs['confirmation']}</span>
<br />
<label for="nom">Nom d'utilisateur</label>
<input type="text" id="nom" name="nom" value="<c:out
value="${utilisateur.nom}"/>" size="20" maxlength="20" />
<span class="erreur">${form.erreurs['nom']}</span>
<br />
<input type="submit" value="Inscription"
class="sansLabel" />
<br />
<p class="${empty form.erreurs ? 'succes' :
'erreur'}">${form.resultat}</p>
</fieldset>
</form>
</body>
</html>

Les modifications apportes semblent donc mineur :


l'accs aux erreurs et au rsultat se fait travers l'objet form ;
l'accs aux donnes se fait travers le bean utilisateur.
Mais en ralit, elles refltent un changement fondamental dans le principe : notre JSP lit dsormais directement les donnes
depuis le modle !

www.siteduzero.com

Partie 4 : Une application interactive !

220/345

Voici sous forme d'un schma ce que nous avons ralis :

Nous avons ainsi avec succs mis en place une architecture MVC pour le traitement de notre formulaire :
1. les donnes saisies et envoyes par le client arrivent la mthode doPost() de la servlet.
2. celle-ci ordonne alors le contrle des donnes reues en appelant la mthode inscrireUtilisateur() de l'objet
mtier InscriptionForm.
3. l'objet InscriptionForm effectue les traitements de validation de chacune des donnes reues.
4. il les enregistre par la mme occasion dans le bean Utilisateur.
5. la mthode doPost() rcupre enfin les deux objets du modle, et les transmet la JSP via la porte requte.
6. la JSP va piocher les donnes dont elle a besoin grce aux diffrentes expressions EL mises en place, qui lui donnent un
accs direct aux objets du modle transmis par la servlet.
7. pour finir, la JSP met jour l'affichage du formulaire en se basant sur les nouvelles donnes.
Ne vous fiez pas aux apparences : mme si le rendu final de notre exemple n'a pas chang d'un poil, le code a quant lui bnfici
d'une amlioration consquente ! Il respecte maintenant la lettre le modle MVC.

www.siteduzero.com

Partie 4 : Une application interactive !

221/345

TP Fil rouge - tape 3


Avant d'aller plus loin, retour sur le fil rouge travers lequel vous tenez une belle occasion de mettre en pratique tout ce que
vous venez de dcouvrir dans ces deux chapitres. Vous allez reprendre le code que vous avez dvelopp au cours des tapes
prcdentes pour y ajouter des vrifications sur le contenu des champs, et l'adapter pour qu'il respecte MVC.

Objectifs
Fonctionnalits
Pour commencer, vous allez devoir modifier vos pages et classes afin d'utiliser la mthode POST pour l'envoi des donnes depuis
vos formulaires de cration de clients et de commandes, et non plus la mthode GET.
Deuximement, je vous demande de mettre en place des vrifications sur les champs des formulaires :
chaque champ marqu d'une toile dans les formulaires devra obligatoirement tre renseign ;
les champs nom et prenom devront contenir au moins 2 caractres ;
le champ adresse devra contenir au moins 10 caractres ;
le champ telephone devra tre un nombre et contenir au moins 4 numros ;
le champ email devra contenir une adresse dont le format est valide ;
le montant devra tre un nombre positif, ventuellement dcimal ;
les champs modePaiement, statutPaiement, modeLivraison et statutLivraison devront contenir au moins 2 caractres ;
le champ date restera dsactiv.
Troisimement, je vous demande de changer le principe de votre petite application :
en cas d'erreur lors de la validation (champs manquants ou errons), vous devrez faire retourner l'utilisateur au formulaire
de saisie en lui r-affichant - sans faille XSS ! - les donnes qu'il a saisies, et en prcisant un message signalant les
erreurs sur chaque champ qui pose problme ;
en cas de succs, vous devrez envoyer l'utilisateur vers la page qui affiche la fiche rcapitulative.

Enfin bien videmment, tout cela se fera en respectant MVC !

Exemples de rendus
Cration de client avec erreurs :

Cration de client sans erreur :

www.siteduzero.com

Partie 4 : Une application interactive !

222/345

Cration de commande avec erreurs :

Cration de commande sans erreur :

www.siteduzero.com

Partie 4 : Une application interactive !

223/345

Conseils
Concernant le changement de mthode d'envoi de GET vers POST, pensez bien ce que cela va impliquer dans vos formulaires
et dans vos servlets !
Concernant les vrifications sur le contenu des champs, vous pouvez bien videmment grandement vous inspirer des mthodes
de validation que nous avons mises en place dans le chapitre prcdent dans notre systme d'inscription. Le principe est trs
semblable, seules certaines conditions de vrifications changent. De mme, afin de respecter MVC vous pourrez prendre exemple
sur la conception utilise dans le chapitre prcdent : beans, objets mtiers et servlets "nettoyes" !
Enfin concernant le renvoi vers le formulaire de cration en cas d'erreur(s), avec affichage des erreurs spcifiques chaque
champ posant problme, l encore vous pouvez vous inspirer de ce que nous avons dvelopp dans le chapitre prcdent !
Bref, vous l'aurez compris, ce TP est une application pure et simple de ce que vous venez de dcouvrir travers la mise en place
de notre systme d'inscription. Je m'arrte donc ici pour les conseils, vous avez toutes les informations et tous les outils en main
pour remplir votre mission ! Lancez-vous, ne vous dcouragez pas et surpassez-vous !

Correction
La longueur du sujet est trompeuse : le travail que vous devez fournir est en ralit assez important ! J'espre que vous avez bien
pris le temps de rflchir l'architecture que vous mettez en place, la manire dont vos classes et objets s'interconnectent et
la logique de validation mettre en place. Comme toujours, ce n'est pas la seule manire de faire, le principal est que votre
solution respecte les consignes que je vous ai donnes !
Prenez le temps de rflchir, de chercher et coder par vous-mmes. Si besoin, n'hsitez pas relire le sujet ou retourner
lire les deux prcdents chapitres. La pratique est trs importante, ne vous ruez pas sur la solution !

Code des objets mtier


Secret (cliquez pour afficher)
Objet mtier grant le formulaire de cration d'un client :
Code : Java - com.sdzee.tp.forms.CreationClientForm
package com.sdzee.tp.forms;

www.siteduzero.com

Partie 4 : Une application interactive !

224/345

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.sdzee.tp.beans.Client;
public final class
private static
private static
private static
private static
"telephoneClient";
private static

CreationClientForm {
final String CHAMP_NOM
final String CHAMP_PRENOM
final String CHAMP_ADRESSE
final String CHAMP_TELEPHONE

= "nomClient";
= "prenomClient";
= "adresseClient";
=

final String CHAMP_EMAIL

= "emailClient";

private String
resultat;
private Map<String, String> erreurs
HashMap<String, String>();

= new

public Map<String, String> getErreurs() {


return erreurs;
}
public String getResultat() {
return resultat;
}
public Client creerClient( HttpServletRequest request ) {
String nom = getValeurChamp( request, CHAMP_NOM );
String prenom = getValeurChamp( request, CHAMP_PRENOM );
String adresse = getValeurChamp( request, CHAMP_ADRESSE );
String telephone = getValeurChamp( request,
CHAMP_TELEPHONE );
String email = getValeurChamp( request, CHAMP_EMAIL );
Client client = new Client();
try {
validationNom( nom );
} catch ( Exception e ) {
setErreur( CHAMP_NOM, e.getMessage() );
}
client.setNom( nom );
try {
validationPrenom( prenom );
} catch ( Exception e ) {
setErreur( CHAMP_PRENOM, e.getMessage() );
}
client.setPrenom( prenom );
try {
validationAdresse( adresse );
} catch ( Exception e ) {
setErreur( CHAMP_ADRESSE, e.getMessage() );
}
client.setAdresse( adresse );
try {
validationTelephone( telephone );
} catch ( Exception e ) {
setErreur( CHAMP_TELEPHONE, e.getMessage() );
}
client.setTelephone( telephone );
try {
validationEmail( email );
} catch ( Exception e ) {
setErreur( CHAMP_EMAIL, e.getMessage() );
}

www.siteduzero.com

Partie 4 : Une application interactive !

225/345

client.setEmail( email );
if ( erreurs.isEmpty() ) {
resultat = "Succs de la cration du client.";
} else {
resultat = "chec de la cration du client.";
}
}

return client;

private void validationNom( String nom ) throws Exception {


if ( nom != null ) {
if ( nom.length() < 2 ) {
throw new Exception( "Le nom d'utilisateur doit
contenir au moins 2 caractres." );
}
} else {
throw new Exception( "Merci d'entrer un nom
d'utilisateur." );
}
}
private void validationPrenom( String prenom ) throws
Exception {
if ( prenom != null && prenom.length() < 2 ) {
throw new Exception( "Le prnom d'utilisateur doit
contenir au moins 2 caractres." );
}
}
private void validationAdresse( String adresse ) throws
Exception {
if ( adresse != null ) {
if ( adresse.length() < 10 ) {
throw new Exception( "L'adresse de livraison doit
contenir au moins 10 caractres." );
}
} else {
throw new Exception( "Merci d'entrer une adresse de
livraison." );
}
}
private void validationTelephone( String telephone ) throws
Exception {
if ( telephone != null ) {
if ( !telephone.matches( "^\\d+$" ) ) {
throw new Exception( "Le numro de tlphone doit
uniquement contenir des chiffres." );
} else if ( telephone.length() < 4 ) {
throw new Exception( "Le numro de tlphone doit
contenir au moins 4 numros." );
}
} else {
throw new Exception( "Merci d'entrer un numro de
tlphone." );
}
}
{

private void validationEmail( String email ) throws Exception

if ( email != null && !email.matches(


"([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)" ) ) {
throw new Exception( "Merci de saisir une adresse mail
valide." );
}
}
/*

www.siteduzero.com

Partie 4 : Une application interactive !

226/345

* Ajoute un message correspondant au champ spcifi la map des


erreurs.
*/
private void setErreur( String champ, String message ) {
erreurs.put( champ, message );
}
/*
* Mthode utilitaire qui retourne null si un champ est vide, et
son contenu
* sinon.
*/
private static String getValeurChamp( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur;
}
}
}

Objet mtier grant le formulaire de cration d'une commande :


Code : Java - com.sdzee.tp.forms.CreationCommandeForm
package com.sdzee.tp.forms;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.sdzee.tp.beans.Client;
import com.sdzee.tp.beans.Commande;
public final class CreationCommandeForm {
private static final String CHAMP_DATE
"dateCommande";
private static final String CHAMP_MONTANT
"montantCommande";
private static final String CHAMP_MODE_PAIEMENT
"modePaiementCommande";
private static final String CHAMP_STATUT_PAIEMENT
"statutPaiementCommande";
private static final String CHAMP_MODE_LIVRAISON
"modeLivraisonCommande";
private static final String CHAMP_STATUT_LIVRAISON
"statutLivraisonCommande";
private static final String FORMAT_DATE
"dd/MM/yyyy HH:mm:ss";
private String
resultat;
private Map<String, String> erreurs
HashMap<String, String>();
public Map<String, String> getErreurs() {
return erreurs;
}

www.siteduzero.com

=
=
=
=
=
=
=

= new

Partie 4 : Une application interactive !

227/345

public String getResultat() {


return resultat;
}
public Commande creerCommande( HttpServletRequest request ) {
/*
* L'objet mtier pour valider la cration d'un client existe
dj, il
* est donc dconseill de dupliquer ici son contenu ! A la place,
il
* suffit de passer la requte courante l'objet mtier existant
et de
* rcuprer l'objet Client cr.
*/
CreationClientForm clientForm = new CreationClientForm();
Client client = clientForm.creerClient( request );
/*
* Et trs important, il ne faut pas oublier de rcuprer le
contenu de
* la map d'erreur cre par l'objet mtier CreationClientForm
dans la
* map d'erreurs courante, actuellement vide.
*/
erreurs = clientForm.getErreurs();
/*
* Ensuite, il suffit de procder normalement avec le reste des
champs
* spcifiques une commande.
*/
/*
* Rcupration et conversion de la date en String selon le
format
* choisi.
*/
DateTime dt = new DateTime();
DateTimeFormatter formatter = DateTimeFormat.forPattern(
FORMAT_DATE );
String date = dt.toString( formatter );
String montant = getValeurChamp( request, CHAMP_MONTANT );
String modePaiement = getValeurChamp( request,
CHAMP_MODE_PAIEMENT );
String statutPaiement = getValeurChamp( request,
CHAMP_STATUT_PAIEMENT );
String modeLivraison = getValeurChamp( request,
CHAMP_MODE_LIVRAISON );
String statutLivraison = getValeurChamp( request,
CHAMP_STATUT_LIVRAISON );
Commande commande = new Commande();
commande.setClient( client );
commande.setDate( date );
double valeurMontant = -1;
try {
valeurMontant = validationMontant( montant );
} catch ( Exception e ) {
setErreur( CHAMP_MONTANT, e.getMessage() );
}
commande.setMontant( valeurMontant );
try {
validationModePaiement( modePaiement );
} catch ( Exception e ) {
setErreur( CHAMP_MODE_PAIEMENT, e.getMessage() );

www.siteduzero.com

Partie 4 : Une application interactive !

228/345

}
commande.setModePaiement( modePaiement );
try {
validationStatutPaiement( statutPaiement );
} catch ( Exception e ) {
setErreur( CHAMP_STATUT_PAIEMENT, e.getMessage() );
}
commande.setStatutPaiement( statutPaiement );
try {
validationModeLivraison( modeLivraison );
} catch ( Exception e ) {
setErreur( CHAMP_MODE_LIVRAISON, e.getMessage() );
}
commande.setModeLivraison( modeLivraison );
try {
validationStatutLivraison( statutLivraison );
} catch ( Exception e ) {
setErreur( CHAMP_STATUT_LIVRAISON, e.getMessage() );
}
commande.setStatutLivraison( statutLivraison );

if ( erreurs.isEmpty() ) {
resultat = "Succs de la cration de la commande.";
} else {
resultat = "chec de la cration de la commande.";
}
return commande;

private double validationMontant( String montant ) throws


Exception {
double temp;
if ( montant != null ) {
try {
temp = Double.parseDouble( montant );
if ( temp < 0 ) {
throw new Exception( "Le montant doit tre un
nombre positif." );
}
} catch ( NumberFormatException e ) {
temp = -1;
throw new Exception( "Le montant doit tre un
nombre." );
}
} else {
temp = -1;
throw new Exception( "Merci d'entrer un montant." );
}
return temp;
}
private void validationModePaiement( String modePaiement )
throws Exception {
if ( modePaiement != null ) {
if ( modePaiement.length() < 2 ) {
throw new Exception( "Le mode de paiement doit
contenir au moins 2 caractres." );
}
} else {
throw new Exception( "Merci d'entrer un mode de
paiment." );
}
}
private void validationStatutPaiement( String statutPaiement )
throws Exception {
if ( statutPaiement != null && statutPaiement.length() < 2

www.siteduzero.com

Partie 4 : Une application interactive !

229/345

) {

throw new Exception( "Le statut de paiement doit


contenir au moins 2 caractres." );
}
}
private void validationModeLivraison( String modeLivraison )
throws Exception {
if ( modeLivraison != null ) {
if ( modeLivraison.length() < 2 ) {
throw new Exception( "Le mode de livraison doit
contenir au moins 2 caractres." );
}
} else {
throw new Exception( "Merci d'entrer un mode de
livraison." );
}
}
private void validationStatutLivraison( String statutLivraison
) throws Exception {
if ( statutLivraison != null && statutLivraison.length() <
2 ) {
throw new Exception( "Le statut de livraison doit
contenir au moins 2 caractres." );
}
}
/*
* Ajoute un message correspondant au champ spcifi la map des
erreurs.
*/
private void setErreur( String champ, String message ) {
erreurs.put( champ, message );
}
/*
* Mthode utilitaire qui retourne null si un champ est vide, et
son contenu
* sinon.
*/
private static String getValeurChamp( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur;
}
}
}

Code des servlets


Secret (cliquez pour afficher)
Servlet grant la cration de client :
Code : Java - com.sdzee.tp.servlets.CreationClient
package com.sdzee.tp.servlets;
import java.io.IOException;

www.siteduzero.com

Partie 4 : Une application interactive !


import
import
import
import

230/345

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import com.sdzee.tp.beans.Client;
import com.sdzee.tp.forms.CreationClientForm;
public class CreationClient extends HttpServlet {
public static final String ATT_CLIENT = "client";
public static final String ATT_FORM
= "form";
public static final String VUE_SUCCES = "/afficherClient.jsp";
public static final String VUE_FORM
= "/creerClient.jsp";
public void doPost( HttpServletRequest request,
HttpServletResponse response ) throws ServletException,
IOException {
/* Prparation de l'objet formulaire */
CreationClientForm form = new CreationClientForm();
/* Traitement de la requte et rcupration du bean en
rsultant */
Client client = form.creerClient( request );
*/

/* Ajout du bean et de l'objet mtier l'objet requte


request.setAttribute( ATT_CLIENT, client );
request.setAttribute( ATT_FORM, form );

if ( form.getErreurs().isEmpty() ) {
/* Si aucune erreur, alors affichage de la fiche
rcapitulative */
this.getServletContext().getRequestDispatcher(
VUE_SUCCES ).forward( request, response );
} else {
/* Sinon, r-affichage du formulaire de cration avec
les erreurs */
this.getServletContext().getRequestDispatcher(
VUE_FORM ).forward( request, response );
}
}
}

Servlet grant la cration de commande :


Code : Java - com.sdzee.tp.servlets.CreationCommande
package com.sdzee.tp.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import com.sdzee.tp.beans.Commande;
import com.sdzee.tp.forms.CreationCommandeForm;
public class CreationCommande extends HttpServlet {
public static final String ATT_COMMANDE = "commande";
public static final String ATT_FORM
= "form";

www.siteduzero.com

Partie 4 : Une application interactive !

231/345

public static final String VUE_SUCCES


"/afficherCommande.jsp";
public static final String VUE_FORM
"/creerCommande.jsp";

=
=

public void doPost( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/* Prparation de l'objet formulaire */
CreationCommandeForm form = new CreationCommandeForm();
/* Traitement de la requte et rcupration du bean en
rsultant */
Commande commande = form.creerCommande( request );
*/

/* Ajout du bean et de l'objet mtier l'objet requte


request.setAttribute( ATT_COMMANDE, commande );
request.setAttribute( ATT_FORM, form );

if ( form.getErreurs().isEmpty() ) {
/* Si aucune erreur, alors affichage de la fiche
rcapitulative */
this.getServletContext().getRequestDispatcher(
VUE_SUCCES ).forward( request, response );
} else {
/* Sinon, r-affichage du formulaire de cration avec
les erreurs */
this.getServletContext().getRequestDispatcher(
VUE_FORM ).forward( request, response );
}
}
}

Code des JSP


Secret (cliquez pour afficher)
Page de cration d'un client :
Code : JSP - /creerClient.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cration d'un client</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div>
<form method="post" action="<c:url
value="/creationClient"/>">
<fieldset>
<legend>Informations client</legend>
<label for="nomClient">Nom <span
class="requis">*</span></label>
<input type="text" id="nomClient"
name="nomClient" value="<c:out value="${client.nom}"/>" size="30"

www.siteduzero.com

Partie 4 : Une application interactive !

232/345

maxlength="30" />

<span
class="erreur">${form.erreurs['nomClient']}</span>
<br />
<label for="prenomClient">Prnom </label>
<input type="text" id="prenomClient"
name="prenomClient" value="<c:out value="${client.prenom}"/>"
size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['prenomClient']}</span>
<br />
<label for="adresseClient">Adresse de
livraison <span class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="<c:out value="${client.adresse}"/>"
size="30" maxlength="60" />
<span
class="erreur">${form.erreurs['adresseClient']}</span>
<br />
<label for="telephoneClient">Numro de
tlphone <span class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="<c:out
value="${client.telephone}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['telephoneClient']}</span>
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient"
name="emailClient" value="<c:out value="${client.email}"/>"
size="30" maxlength="60" />
<span
class="erreur">${form.erreurs['emailClient']}</span>
<br />

/>

<p class="info">${ form.resultat }</p>


</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br

</form>
</div>
</body>
</html>

Page de cration d'une commande :


Code : JSP - /creerCommande.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cration d'une commande</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div>
<form method="post" action="<c:url

www.siteduzero.com

Partie 4 : Une application interactive !

233/345

value="/creationCommande"/>">
<fieldset>
<legend>Informations client</legend>
<label for="nomClient">Nom <span
class="requis">*</span></label>
<input type="text" id="nomClient"
name="nomClient" value="<c:out value="${commande.client.nom}"/>"
size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['nomClient']}</span>
<br />
<label for="prenomClient">Prnom </label>
<input type="text" id="prenomClient"
name="prenomClient" value="<c:out
value="${commande.client.prenom}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['prenomClient']}</span>
<br />
<label for="adresseClient">Adresse de
livraison <span class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="<c:out
value="${commande.client.adresse}"/>" size="30" maxlength="60" />
<span
class="erreur">${form.erreurs['adresseClient']}</span>
<br />
<label for="telephoneClient">Numro de
tlphone <span class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="<c:out
value="${commande.client.telephone}"/>" size="30" maxlength="30"
/>
<span
class="erreur">${form.erreurs['telephoneClient']}</span>
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient"
name="emailClient" value="<c:out
value="${commande.client.email}"/>" size="30" maxlength="60" />
<span
class="erreur">${form.erreurs['emailClient']}</span>
<br />
</fieldset>
<fieldset>
<legend>Informations commande</legend>
<label for="dateCommande">Date <span
class="requis">*</span></label>
<input type="text" id="v" name="dateCommande"
value="<c:out value="${commande.date}"/>" size="30" maxlength="30"
disabled />
<span
class="erreur">${form.erreurs['dateCommande']}</span>
<br />
<label for="montantCommande">Montant <span
class="requis">*</span></label>
<input type="text" id="montantCommande"
name="montantCommande" value="<c:out
value="${commande.montant}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['montantCommande']}</span>
<br />
<label for="modePaiementCommande">Mode de

www.siteduzero.com

Partie 4 : Une application interactive !

234/345

paiement <span class="requis">*</span></label>


<input type="text" id="modePaiementCommande"
name="modePaiementCommande" value="<c:out
value="${commande.modePaiement}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['modePaiementCommande']}</span>
<br />
<label for="statutPaiementCommande">Statut du

paiement</label>

<input type="text" id="statutPaiementCommande"


name="statutPaiementCommande" value="<c:out
value="${commande.statutPaiement}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['statutPaiementCommande']}</span>
<br />
<label for="modeLivraisonCommande">Mode de
livraison <span class="requis">*</span></label>
<input type="text" id="modeLivraisonCommande"
name="modeLivraisonCommande" value="<c:out
value="${commande.modeLivraison}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['modeLivraisonCommande']}</span>
<br />
la livraison</label>

<label for="statutLivraisonCommande">Statut de

<input type="text"
id="statutLivraisonCommande" name="statutLivraisonCommande"
value="<c:out value="${commande.statutLivraison}"/>" size="30"
maxlength="30" />
<span
class="erreur">${form.erreurs['statutLivraisonCommande']}</span>
<br />

/>

<p class="info">${ form.resultat }</p>


</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br

</form>
</div>
</body>
</html>

Page d'affichage d'un client :


Code : JSP - /afficherClient.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Affichage d'un client</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div id="corps">
<p class="info">${ form.resultat }</p>
<p>Nom : <c:out value="${ client.nom }"/></p>
<p>Prnom : <c:out value="${ client.prenom }"/></p>
<p>Adresse : <c:out value="${ client.adresse }"/></p>

www.siteduzero.com

Partie 4 : Une application interactive !

235/345

<p>Numro de tlphone : <c:out value="${


client.telephone }"/></p>
<p>Email : <c:out value="${ client.email }"/></p>
</div>
</body>
</html>

Page d'affichage d'une commande :


Code : JSP - /afficherCommande.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Affichage d'une commande</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div id="corps">
<p class="info">${ form.resultat }</p>
<p>Client</p>
<p>Nom : <c:out value="${ commande.client.nom }"/></p>
<p>Prnom : <c:out value="${ commande.client.prenom
}"/></p>
<p>Adresse : <c:out value="${ commande.client.adresse
}"/></p>
<p>Numro de tlphone : <c:out value="${
commande.client.telephone }"/></p>
<p>Email : <c:out value="${ commande.client.email
}"/></p>
<p>Commande</p>
<p>Date : <c:out value="${ commande.date }"/></p>
<p>Montant : <c:out value="${ commande.montant
}"/></p>
<p>Mode de paiement : <c:out value="${
commande.modePaiement }"/></p>
<p>Statut du paiement : <c:out value="${
commande.statutPaiement }"/></p>
<p>Mode de livraison : <c:out value="${
commande.modeLivraison }"/></p>
<p>Statut de la livraison : <c:out value="${
commande.statutLivraison }"/></p>
</div>
</body>
</html>

www.siteduzero.com

Partie 4 : Une application interactive !

236/345

La session : connectez vos clients


Nous allons ici dcouvrir par l'exemple comment utiliser la session.
La situation que nous allons mettre en place est un systme de connexion des utilisateurs. Nous allons grandement nous inspirer
de ce que nous venons de faire dans le prcdent chapitre avec notre systme d'inscription, et allons directement appliquer les
bonnes pratiques dcouvertes. L encore, nous n'allons pas pouvoir mettre en place un systme complet de A Z, puisqu'il
nous manque toujours la gestion des donnes. Mais ce n'est pas important : ce qui compte, c'est que vous tenez l une occasion
de plus pour pratiquer la gestion des formulaires en suivant MVC !

Le formulaire
La premire chose que nous allons mettre en place est le formulaire de connexion, autrement dit la vue. Cela ne va pas nous
demander trop d'efforts : nous allons reprendre l'architecture de la page JSP que nous avons cre dans le chapitre prcdent, et
l'adapter nos nouveaux besoins !
Voici le code de notre page connexion.jsp, placer sous le rpertoire /WEB-INF :
Code : JSP - /WEB-INF/connexion.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Connexion</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="connexion">
<fieldset>
<legend>Connexion</legend>
<p>Vous pouvez vous connecter via ce formulaire.</p>
<label for="nom">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email" value="<c:out
value="${utilisateur.email}"/>" size="20" maxlength="60" />
<span class="erreur">${form.erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span class="erreur">${form.erreurs['motdepasse']}</span>
<br />
<input type="submit" value="Connexion"
class="sansLabel" />
<br />
<p class="${empty form.erreurs ? 'succes' :
'erreur'}">${form.resultat}</p>
</fieldset>
</form>
</body>
</html>

Nous reprenons la mme architecture que pour le systme d'inscription : notre JSP exploite un objet form contenant les
ventuels messages d'erreurs, et un objet utilisateur contenant les donnes saisies et valides.
Par ailleurs, nous rutilisons la mme feuille de style.

Le principe de la session
Avant d'aller plus loin, nous devons nous attarder un instant sur ce qu'est une session.

www.siteduzero.com

Partie 4 : Une application interactive !

237/345

Pourquoi les sessions existent-elles ?

Notre application web est base sur le protocole HTTP, qui est un protocole dit "sans tat" : cela signifie que le serveur, une fois
qu'il a envoy une rponse la requte d'un client, ne conserve pas les donnes le concernant. Autrement dit, le serveur traite
les clients requte par requte et est absolument incapable de faire un rapprochement entre leur origine : pour lui, chaque
nouvelle requte mane d'un nouveau client, puisqu'il oublie le client aprs l'envoi de chaque rponse... Oui, le serveur HTTP est
un peu gteux !
C'est pour pallier cette lacune que le concept de session a t cr : il permet au serveur de mmoriser des informations relatives
au client d'une requte l'autre.
Qu'est-ce qu'une session en Java EE ?

Souvenez-vous, nous en avions dj parl dans ce paragraphe ddi la porte des objets ainsi que dans ce chapitre sur la JSTL
Core :
la session reprsente un espace mmoire allou pour chaque utilisateur, permettant de sauvegarder des informations tout
le long de leur visite ;
le contenu d'une session est conserv jusqu' ce que l'utilisateur ferme son navigateur, reste inactif trop longtemps, ou
encore lorsqu'il se dconnecte du site ;
l'objet Java sur lequel se base une session est l'objet HttpSession ;
il existe un objet implicite sessionScope permettant d'accder directement au contenu de la session depuis une expression
EL dans une page JSP.
Comment manipuler cet objet depuis une servlet ?

Pour commencer, il faut le rcuprer depuis l'objet HttpServletRequest. Cet objet propose en effet une mthode
getSession(), qui permet de rcuprer la session associe la requte HTTP en cours si elle existe, ou d'en crer une si elle
n'existe pas encore :
Code : Java - Rcupration de la session depuis la requte
HttpSession session = request.getSession();

Ainsi tant que cette ligne de code n'a pas t appele, la session n'existe pas !

Ensuite, lorsque nous tudions attentivement la documentation de cet objet, nous remarquons entre autres :
qu'il propose un couple de mthodes setAttribute() / getAttribute(), permettant la mise en place d'objets au
sein de la session et leur rcupration, tout comme dans l'objet HttpServletRequest ;
qu'il propose une mthode getId(), retournant un identifiant unique permettant de dterminer qui appartient telle
session.
Nous savons donc maintenant qu'il nous suffit d'appeler le code suivant pour enregistrer un objet en session depuis notre
servlet, puis le rcuprer :
Code : Java - Exemple de manipulations d'objets en session
/* Cration ou rcupration de la session */
HttpSession session = request.getSession();
/* Mise en session d'une chane de caractres */
String exemple = "abc";
session.setAttribute( "chaine", exemple );

www.siteduzero.com

Partie 4 : Une application interactive !

238/345

/* Rcupration de l'objet depuis la session */


String chaine = (String) session.getAttribute( "chaine" );

C'est tout ce que nous avons besoin de savoir pour le moment.


Observez l'enchanement lors de la premire visite d'un utilisateur sur une page ou servlet contenant un appel
request.getSession() :

1. le navigateur de l'utilisateur envoie une requte au serveur ;


2. la servlet ne trouve aucune session existante lors de l'appel getSession(), et cre donc un nouvel objet
HttpSession qui contient un identifiant unique ;
3. le serveur place automatiquement l'identifiant de l'objet session dans la rponse renvoye au navigateur de l'utilisateur ;
4. le navigateur enregistre l'identifiant que le serveur lui a envoy.
Observez alors ce qui se passe lors des visites suivantes :

1. le navigateur place automatiquement l'identifiant enregistr dans la requte qu'il envoie au serveur ;
2. la servlet retrouve la session associe l'utilisateur lors de l'appel getSession(), grce l'identifiant unique que le
navigateur a plac dans la requte ;
3. le serveur sait que le navigateur du client a dj enregistr l'identifiant de la session courante, et renvoie donc une
rponse classique l'utilisateur : il sait qu'il n'est pas ncessaire de lui transmettre nouveau l'identifiant !
Vous avez maintenant tout en main pour comprendre comment l'tablissement d'une session fonctionne. En ce qui concerne les
rouages du systme, chaque chose en son temps : dans la dernire partie de ce chapitre, nous analyserons comment tout cela
s'organise dans les coulisses !

www.siteduzero.com

Partie 4 : Une application interactive !

239/345

Trs bien, nous avons compris comment a marche. Maintenant dans notre cas, qu'avons-nous besoin d'enregistrer en
session ?
En effet, c'est une trs bonne question : qu'est-il intressant et utile de stocker en session ? Rappelons-le, notre objectif est de
connecter un utilisateur : nous souhaitons donc tre capable de le reconnatre d'une requte l'autre.
La premire intuition qui nous vient l'esprit, c'est naturellement de sauvegarder l'adresse mail et le mot de passe de l'utilisateur
dans un objet, et de placer cet objet dans la session !

Le modle
D'aprs ce que nous venons de dduire, nous pouvons nous inspirer ce que nous avons cr dans le chapitre prcdent. Il va
nous falloir :
un bean reprsentant un utilisateur, que nous placerons en session lors de la connexion ;
un objet mtier reprsentant le formulaire de connexion, pour traiter et valider les donnes et connecter l'utilisateur.
En ce qui concerne l'utilisateur, nous n'avons besoin de rien de nouveau : nous disposons dj du bean cr pour le systme
d'inscription ! Vous devez maintenant bien mieux saisir le caractre rutilisable du JavaBean, que je vous vantais dans ce
chapitre.
En ce qui concerne le formulaire, l par contre nous allons devoir crer un nouvel objet mtier. Eh oui, nous n'y coupons pas :
chaque nouveau formulaire, nous allons devoir mettre en place un nouvel objet. Vous dcouvrez ici un des inconvnients
majeurs de l'application de MVC dans une application Java EE uniquement base sur le trio objets mtier - servlets - pages JSP : il
faut rcrire les mthodes de rcupration, conversion et validation des paramtres de la requte HTTP chaque nouvelle
requte traite !
Plus loin dans ce cours, lorsque nous aurons acquis un bagage assez important pour nous lancer au-del du Java EE
"nu", nous dcouvrirons comment les dveloppeurs ont russi rendre ces tapes entirement automatises en
utilisant un framework MVC pour construire leurs applications. En attendant, vous allez devoir faire preuve de
patience et tre assidu, nous avons encore du pain sur la planche !

Nous devons donc crer un objet mtier, que nous allons nommer ConnexionForm et qui va grandement s'inspirer de l'objet
InscriptionForm :
Code : Java - com.sdzee.forms.ConnexionForm
package com.sdzee.forms;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.sdzee.beans.Utilisateur;
public final class ConnexionForm {
private static final String CHAMP_EMAIL
private static final String CHAMP_PASS
private String
resultat;
private Map<String, String> erreurs
String>();

= "email";
= "motdepasse";
= new HashMap<String,

public String getResultat() {


return resultat;
}
public Map<String, String> getErreurs() {
return erreurs;
}
public Utilisateur connecterUtilisateur( HttpServletRequest request

www.siteduzero.com

Partie 4 : Une application interactive !


) {

240/345

/* Rcupration des champs du formulaire */


String email = getValeurChamp( request, CHAMP_EMAIL );
String motDePasse = getValeurChamp( request, CHAMP_PASS );
Utilisateur utilisateur = new Utilisateur();

/* Validation du champ email. */


try {
validationEmail( email );
} catch ( Exception e ) {
setErreur( CHAMP_EMAIL, e.getMessage() );
}
utilisateur.setEmail( email );
/* Validation du champ mot de passe. */
try {
validationMotDePasse( motDePasse );
} catch ( Exception e ) {
setErreur( CHAMP_PASS, e.getMessage() );
}
utilisateur.setMotDePasse( motDePasse );
/* Initialisation du rsultat global de la validation. */
if ( erreurs.isEmpty() ) {
resultat = "Succs de la connexion.";
} else {
resultat = "chec de la connexion.";
}
return utilisateur;
}
/**
* Valide l'adresse email saisie.
*/
private void validationEmail( String email ) throws Exception {
if ( email != null && !email.matches(
"([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)" ) ) {
throw new Exception( "Merci de saisir une adresse mail
valide." );
}
}
/**
* Valide le mot de passe saisi.
*/
private void validationMotDePasse( String motDePasse ) throws
Exception {
if ( motDePasse != null ) {
if ( motDePasse.length() < 3 ) {
throw new Exception( "Le mot de passe doit contenir
au moins 3 caractres." );
}
} else {
throw new Exception( "Merci de saisir votre mot de
passe." );
}
}
/*
* Ajoute un message correspondant au champ spcifi la map des
erreurs.
*/
private void setErreur( String champ, String message ) {
erreurs.put( champ, message );
}
/*
* Mthode utilitaire qui retourne null si un champ est vide, et son

www.siteduzero.com

Partie 4 : Une application interactive !

241/345

contenu
* sinon.
*/
private static String getValeurChamp( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur;
}
}
}

Nous retrouvons ici la mme architecture que dans l'objet InscriptionForm :


des constantes d'identification des champs du formulaire ;
des mthodes de validation des champs ;
une mthode de gestion des erreurs ;
une mthode centrale, connecterUtilisateur(), qui fait intervenir les mthodes suscites et renvoie un bean
Utilisateur.
Rien de nouveau n'entre en jeu pour l'instant. Si vous ne comprenez pas bien ce code, vous devez relire attentivement les deux
chapitres prcdents : tout y est expliqu !

La servlet
Afin de rendre tout ce petit monde oprationnel, nous devons mettre en place une servlet ddie la connexion. Une fois n'est
pas coutume, nous allons grandement nous inspirer de ce que nous avons cr dans les chapitres prcdents. Voici donc le code
de la servlet nomme Connexion, place tout comme sa grande sur dans le package com.sdzee.servlets :
Code : Java - com.sdzee.servlets.Connexion
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import com.sdzee.beans.Utilisateur;
import com.sdzee.forms.ConnexionForm;
public class Connexion extends HttpServlet {
public static final String ATT_USER
= "utilisateur";
public static final String ATT_FORM
= "form";
public static final String ATT_SESSION_USER = "sessionUtilisateur";
public static final String VUE
= "/WEBINF/connexion.jsp";
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/* Affichage de la page de connexion */
this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
public void doPost( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/* Prparation de l'objet formulaire */
ConnexionForm form = new ConnexionForm();

www.siteduzero.com

Partie 4 : Une application interactive !

242/345

/* Traitement de la requte et rcupration du bean en


rsultant */
Utilisateur utilisateur = form.connecterUtilisateur( request
);
/* Rcupration de la session depuis la requte */
HttpSession session = request.getSession();
/**
* Si aucune erreur de validation n'a eu lieu, alors ajout du bean
* Utilisateur la session, sinon suppression du bean de la
session.
*/
if ( form.getErreurs().isEmpty() ) {
session.setAttribute( ATT_SESSION_USER, utilisateur );
} else {
session.setAttribute( ATT_SESSION_USER, null );
}
*/

/* Stockage du formulaire et du bean dans l'objet request


request.setAttribute( ATT_FORM, form );
request.setAttribute( ATT_USER, utilisateur );

this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
}

Au niveau de la structure, rien de nouveau : la servlet joue bien le rle d'aiguilleur, en appelant les traitements prsents dans
l'objet ConnexionForm, et en rcuprant le bean utilisateur. Ce qui change cette fois, c'est bien entendu la gestion de la session,
surligne en jaune dans le code ci-dessus :
la ligne 33, nous appelons la mthode request.getSession() pour crer une session ou rcuprer la session
existante ;
dans le bloc if lignes 39 43, nous enregistrons le bean utilisateur en tant qu'attribut de session uniquement si aucune
erreur de validation n'a t envoye lors de l'excution de la mthode connecterUtilisateur(). partir du
moment o une seule erreur est dtecte, c'est dire si form.getErreurs.isEmpty() renvoie false, alors le
bean utilisateur est supprim de la session, via un passage de l'attribut null.
Pour terminer, voici la configuration de cette servlet dans le fichier web.xml de l'application :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>Inscription</servlet-name>
<servlet-class>com.sdzee.servlets.Inscription</servlet-class>
</servlet>
<servlet>
<servlet-name>Connexion</servlet-name>
<servlet-class>com.sdzee.servlets.Connexion</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Inscription</servlet-name>
<url-pattern>/inscription</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Connexion</servlet-name>
<url-pattern>/connexion</url-pattern>
</servlet-mapping>
</web-app>

www.siteduzero.com

Partie 4 : Une application interactive !

243/345

Une fois tout ce code bien en place, vous pouvez accder la page de connexion via votre navigateur en vous rendant sur l'URL
http://localhost:8080/pro/connexion. Ci-dessous, le rsultat attendu :

Formulaire de connexion.

Oui mais voil, nous n'avons pas encore de moyen de tester le bon fonctionnement de ce semblant de systme de connexion ! Et
pour cause, les seuls messages que nous affichons dans notre vue, ce sont les rsultats des vrifications du contenu des
champs du formulaire... Ci-dessous, le rsultat actuel respectivement lors d'un chec et d'un succs de la validation :

chec de la connexion.

Succs de la connexion.
Ce qu'il serait maintenant intressant de vrifier dans notre vue, c'est le contenu de la session. Et comme le hasard fait trs bien
les choses, je vous ai justement rappel en dbut de chapitre qu'il existe un objet implicite nomm sessionScope, ddi l'accs
au contenu de la session !

Les vrifications
Test du formulaire de connexion
Pour commencer, nous allons donc modifier notre page JSP afin d'afficher le contenu de la session :
Code : JSP - /WEB-INF/connexion.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>

www.siteduzero.com

Partie 4 : Une application interactive !

244/345

<meta charset="utf-8" />


<title>Connexion</title>
<link type="text/css" rel="stylesheet" href="form.css" />
</head>
<body>
<form method="post" action="connexion">
<fieldset>
<legend>Connexion</legend>
<p>Vous pouvez vous connecter via ce formulaire.</p>
<label for="nom">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email"
value="<c:out value="${utilisateur.email}"/>" size="20"
maxlength="60" />
<span class="erreur">${form.erreurs['email']}</span>
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span
class="erreur">${form.erreurs['motdepasse']}</span>
<input type="submit" value="Connexion"
class="sansLabel" />
<p class="${empty form.erreurs ? 'succes' :
'erreur'}">${form.resultat}</p>
<%-- Vrification de la prsence d'un objet utilisateur en session -%>
<c:if test="${!empty sessionScope.sessionUtilisateur}">
<%-- Si l'utilisateur existe en session, alors on affiche son
adresse email. --%>
<p class="succes">Vous tes connect(e) avec l'adresse :
${sessionScope.sessionUtilisateur.email}</p>
</c:if>
</fieldset>
</form>
</body>
</html>

Dans cette courte modification, vous pouvez remarquer :


l'utilisation de l'objet implicite sessionScope pour cibler la porte session ;
la mise en place d'un test conditionnel via la balise <c:if/>. Son contenu (les lignes 32 et 33) s'affichera uniquement si
le test est valid ;
le test de l'existence d'un objet via l'expression ${!empty ...}. Si aucun objet n'est trouv, ce test renvoie false ;
l'accs au bean sessionUtilisateur de la session via l'expression ${sessionScope.sessionUtilisateur} ;
l'accs la proprit email du bean sessionUtilisateur via l'expression
${sessionScope.sessionUtilisateur.email}.
Rappelez-vous : nous pourrions trs bien accder l'objet en crivant simplement ${sessionUtilisateur}, et
l'expression EL chercherait alors d'elle-mme un objet nomm sessionUtilisateur dans chaque porte. Mais je vous ai
dj dit que la bonne pratique tait de rserver cette criture l'accs des objets de la porte page, et de toujours
accder aux objets des autres portes en prcisant l'objet implicite correspondant (requestScope, sessionScope ou
applicationScope).

Accdez maintenant la page http://localhost:8080/pro/connexion, et entrez des donnes valides. Voici le rsultat attendu aprs
succs de la connexion :

www.siteduzero.com

Partie 4 : Une application interactive !

245/345

Ensuite, r-affichez la page http://localhost:8080/pro/connexion, mais attention pas en appuyant sur F5 ni en actualisant la page :
cela renverrait les donnes de votre formulaire ! Non, r-entrez simplement l'URL dans le mme onglet de votre navigateur, ou
bien ouvrez un nouvel onglet. Voici le rsultat attendu :

Vous pouvez alors constater que la mmorisation de l'utilisateur a fonctionn ! Lorsqu'il a reu la deuxime requte d'affichage du
formulaire, le serveur vous a reconnu : il sait que vous tes le client qui a effectu la requte de connexion auparavant, et a
conserv vos informations dans la session. En outre, vous voyez galement que les informations qui avaient t saisies dans les
champs du formulaire lors de la premire requte sont quant elles bien videmment perdues : elles n'avaient t gres que via
l'objet request, et ont donc t dtruites aprs envoi de la premire rponse au client.
Vous devez maintenant mieux comprendre cette histoire de porte des objets : l'objet qui a t enregistr en session
reste accessible sur le serveur au fil des requtes d'un mme client, alors que l'objet qui a t enregistr dans la requte
n'est accessible que lors d'une requte donne, et disparat du serveur ds que la rponse est envoye au client.

Pour finir, testons l'effacement de l'objet de la session lorsqu'une erreur de validation survient. Remplissez le formulaire avec des
donnes invalides, et constatez :

Le contenu du corps de la balise <c:if/> n'est ici pas affich. Cela signifie que le test de prsence de l'objet en session a
retourn false, et donc que notre servlet a bien pass l'objet utilisateur null dans la session. En conclusion, jusqu'
prsent tout roule !

Test de la destruction de session


www.siteduzero.com

Partie 4 : Une application interactive !

246/345

Je vous l'ai rappel en dbut de chapitre, la session peut tre dtruite dans plusieurs circonstances :
l'utilisateur ferme son navigateur ;
la session expire aprs une priode d'inactivit de l'utilisateur ;
l'utilisateur se dconnecte.

L'utilisateur ferme son navigateur


Ce paragraphe va tre trs court. Faites le test vous-mmes :
1.
2.
3.
4.

ouvrez un navigateur et affichez le formulaire de connexion ;


entrez des donnes valides et connectez-vous ;
fermez votre navigateur ;
rouvrez-le, et rendez-vous nouveau sur le formulaire de connexion.

Vous constaterez alors que le serveur ne vous a pas reconnu : les informations vous concernant n'existent plus, et le serveur
considre que vous tes un nouveau client.

La session expire aprs une priode d'inactivit de l'utilisateur


Par dfaut avec Tomcat, la dure maximum de validit impose aprs laquelle la session sera automatiquement dtruite par le
serveur est de 30 minutes. Vous vous doutez bien que nous n'allons pas poireauter une demi-heure devant notre cran pour
vrifier si cela fonctionne bien : vous avez la possibilit via le fichier web.xml de votre application de personnaliser cette dure.
Ouvrez-le dans Eclipse et modifiez-le comme suit :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<session-config>
<session-timeout>1</session-timeout>
</session-config>
<servlet>
<servlet-name>Inscription</servlet-name>
<servlet-class>com.sdzee.servlets.Inscription</servlet-class>
</servlet>
<servlet>
<servlet-name>Connexion</servlet-name>
<servlet-class>com.sdzee.servlets.Connexion</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Inscription</servlet-name>
<url-pattern>/inscription</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Connexion</servlet-name>
<url-pattern>/connexion</url-pattern>
</servlet-mapping>
</web-app>

Le champ <session-timeout> permet de dfinir en minutes le temps d'inactivit de l'utilisateur aprs lequel sa session sera
dtruite. Je l'ai ici rabaiss une minute, uniquement pour effectuer notre vrification. Redmarrez Tomcat afin que la
modification apporte au fichier soit prise en compte, puis :
1. ouvrez un navigateur et affichez le formulaire de connexion ;
2. entrez des donnes valides et connectez-vous ;
3. attendez quelques minutes, puis affichez nouveau le formulaire, dans la mme page ou dans un nouvel onglet.
Vous constaterez alors que le serveur vous a oubli : les informations vous concernant n'existent plus, et le serveur considre

www.siteduzero.com

Partie 4 : Une application interactive !

247/345

que vous tes un nouveau client.


Une fois ce test effectu, ditez nouveau votre fichier web.xml et supprimez la section frachement ajoute : dans la
suite de nos exemples, nous n'allons pas avoir besoin de cette limitation.

L'utilisateur se dconnecte
Cette dernire vrification va ncessiter un peu de dveloppement. En effet, nous avons cr une servlet de connexion, mais
nous n'avons pas encore mis en place de servlet de dconnexion. Par consquent, il est pour le moment impossible pour le client
de se dconnecter volontairement du site, il est oblig de fermer son navigateur ou d'attendre que la dure d'inactivit soit
dpasse.
Comment dtruire manuellement une session ?

Il faut regarder dans la documentation de l'objet HttpSession pour rpondre cette question : nous y trouvons une mthode
invalidate(), qui supprime une session et les objets qu'elle contient, et envoie une exception si jamais elle est applique sur
une session dj dtruite.
Crons sans plus attendre notre nouvelle servlet nomme Deconnexion :
Code : Java - com.sdzee.servlets.Deconnexion
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

public class Deconnexion extends HttpServlet {


public static final String URL_REDIRECTION =
"http://www.siteduzero.com";
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/* Rcupration et destruction de la session en cours */
HttpSession session = request.getSession();
session.invalidate();
/* Redirection vers le site du zro ! */
response.sendRedirect( URL_REDIRECTION );
}
}

Vous remarquez ici deux nouveauts :


l'appel la mthode invalidate() de l'objet HttpSession ;
la redirection vers la page de connexion via la mthode sendRedirect() de l'objet HttpServletResponse, en
lieu de place du forwarding que nous utilisions auparavant.
Quelle est la diffrence entre la redirection et le forwarding ?

En ralit, vous le savez dj ! Eh oui, vous ne l'avez pas encore appliqu depuis une servlet, mais je vous ai dj expliqu le
principe lorsque nous avons dcouvert la balise <c:redirect/>, dans cette partie du chapitre portant sur la JSTL Core.

www.siteduzero.com

Partie 4 : Une application interactive !

248/345

Pour rappel donc, une redirection HTTP implique l'envoi d'une rponse au client, alors que le forwarding s'effectue sur le
serveur et le client n'en est pas tenu inform. Cela implique notamment que via un forwarding il est uniquement possible de
cibler des pages internes l'application, alors que via la redirection il est possible d'atteindre n'importe quelle URL publique ! En
l'occurrence, j'ai dans notre servlet fait en sorte que lorsque vous vous dconnectez, vous tes redirig vers votre site web
prfr.
Fin du rappel, nous allons de toute manire y revenir dans le prochain paragraphe. Pour le moment, concentrons-nous sur la
destruction de notre session !
Dclarons notre servlet dans le fichier web.xml de notre application :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>Inscription</servlet-name>
<servlet-class>com.sdzee.servlets.Inscription</servlet-class>
</servlet>
<servlet>
<servlet-name>Connexion</servlet-name>
<servlet-class>com.sdzee.servlets.Connexion</servlet-class>
</servlet>
<servlet>
<servlet-name>Deconnexion</servlet-name>
<servlet-class>com.sdzee.servlets.Deconnexion</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Inscription</servlet-name>
<url-pattern>/inscription</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Connexion</servlet-name>
<url-pattern>/connexion</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Deconnexion</servlet-name>
<url-pattern>/deconnexion</url-pattern>
</servlet-mapping>
</web-app>

Redmarrez Tomcat pour que la modification du fichier web.xml soit prise en compte, et testez alors comme suit :
1.
2.
3.
4.

ouvrez un navigateur et affichez le formulaire de connexion ;


entrez des donnes valides et connectez-vous ;
entrez l'URL http://localhost:8080/pro/deconnexion ;
affichez nouveau le formulaire de connexion.

Vous constaterez alors que lors de votre retour, le serveur ne vous reconnat pas : la session a bien t dtruite.

Diffrence entre forwarding et redirection


Avant de continuer, puisque nous y sommes, testons cette histoire de forwarding et de redirection. Modifiez le code de la
servlet comme suit :
Code : Java - com.sdzee.servlets.Deconnexion
package com.sdzee.servlets;
import java.io.IOException;
import javax.servlet.ServletException;

www.siteduzero.com

Partie 4 : Une application interactive !


import
import
import
import

249/345

javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

public class Deconnexion extends HttpServlet {


public static final String VUE = "/connexion";
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/* Rcupration et destruction de la session en cours */
HttpSession session = request.getSession();
session.invalidate();
/* Affichage de la page de connexion */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
}

Nous avons ici simplement mis en place un forwarding vers la servlet de connexion : une fois dconnect, vous allez visualiser
le formulaire de connexion dans votre navigateur. Oui, mais voyez plutt :

Forwarding.
Vous comprenez ce qu'il s'est pass ? Comme je vous l'ai expliqu dans plusieurs chapitres, le client n'est pas au courant qu'un
forwarding a t ralis ct serveur. Pour lui, la page jointe est /pro/deconnexion, et c'est bien elle qui lui a renvoy une
rponse HTTP. Par consquent, l'URL dans la barre d'adresse de votre navigateur n'a pas chang ! Pourtant, ct serveur a t
effectu un petit enchanement de forwardings :

Avec un forwarding

www.siteduzero.com

Partie 4 : Une application interactive !


1.
2.
3.
4.

250/345

l'utilisateur accde la page de dconnexion depuis son navigateur ;


la servlet de dconnexion transfre la requte vers la servlet de connexion via un forwarding ;
la servlet de connexion transfre la requte vers la JSP du formulaire de connexion via un forwarding ;
la JSP renvoie le formulaire l'utilisateur.

Ce que vous devez comprendre avec ce schma, c'est que du point de vue du client, pour qui le serveur est comme une grosse
bote noire, la rponse envoye par la JSP finale correspond la requte vers la servlet de dconnexion qu'il a effectue. C'est
donc pour cette raison que l'utilisateur croit que la rponse est issue de la servlet de dconnexion, et que son navigateur lui
affiche toujours l'URL de la page de dconnexion dans la barre d'adresse : il ne voit pas ce qu'il se passe ct serveur, et ne sait
pas qu'en ralit sa requte a t balade de servlet en servlet.
Voyons maintenant ce qui se passerait si nous utilisions une redirection vers la page de connexion la place du forwarding dans
la servlet de dconnexion :

Avec une redirection


1. l'utilisateur accde la page de dconnexion depuis son navigateur ;
2. la servlet de dconnexion envoie une demande de redirection au navigateur vers la servlet de connexion, via un
sendRedirect( "/pro/connexion" ) ;
3. le navigateur de l'utilisateur excute alors la redirection et effectue alors une nouvelle requte vers la servlet de connexion
;
4. la servlet de connexion transfre la requte vers la JSP du formulaire de connexion via un forwarding ;
5. la JSP renvoie le formulaire l'utilisateur.
Cette fois, vous voyez bien que la rponse envoye par la JSP finale correspond la seconde requte effectue par le navigateur,
savoir celle vers la servlet de connexion. Ainsi, l'URL affiche dans la barre d'adresse du navigateur est bien celle de la page de
connexion, et l'utilisateur n'est pas drout.
Alors certes, dans le cas de notre page de dconnexion et de notre forwarding , le fait que le client ne soit pas au courant du
cheminement de sa requte au sein du serveur n'a rien de troublant, seule l'URL n'est pas en accord avec l'affichage final. En
effet, si le client appuie sur F5 et actualise la page, cela va appeler nouveau la servlet de dconnexion, qui va supprimer sa
session si elle existe, puis nouveau faire un forwarding , etc. puis finir par afficher le formulaire de connexion nouveau.
Seulement imaginez maintenant que nous n'avons plus affaire un systme de dconnexion, mais un systme de gestion de
compte en banque, dans lequel la servlet de dconnexion deviendrait une servlet de transfert d'argent, et la servlet de connexion
deviendrait une servlet d'affichage du solde du compte. Si nous gardons ce systme de forwarding , alors aprs que le client
effectue un transfert d'argent, il est redirig de manire transparente vers l'affichage du solde de son compte. Et l, a devient
problmatique : si le client ne fait pas attention, et qu'il actualise la page en pensant simplement actualiser l'affichage de son
solde, il va en ralit nouveau effectuer un transfert d'argent, puisque l'URL de son navigateur est reste fige sur la premire
servlet contacte...
Vous comprenez mieux maintenant pourquoi je vous avais conseill d'utiliser <c:redirect/> plutt que <jsp:forward/>
dans le chapitre sur la JSTL Core, et pourquoi dans notre exemple j'ai ici mis en place une redirection HTTP via

www.siteduzero.com

Partie 4 : Une application interactive !

251/345

sendRedirect() plutt qu'un forwarding ?


Avant de poursuivre, ditez le code de votre servlet de dconnexion et remettez en place la redirection HTTP vers votre
site prfr, comme je vous l'ai montr avant de faire cet apart sur le forwarding .

Derrire les rideaux


La thorie : principe de fonctionnement
C'est bien joli tout a, mais nous n'avons toujours pas abord la question fatidique :
Comment fonctionnent les sessions ?

Jusqu' prsent, nous ne sommes pas inquits de ce qui se passe derrire les rideaux. Et pourtant croyez-moi, il y a de quoi faire
!
La chose la plus importante retenir, c'est que c'est vous qui contrlez l'existence d'une session dans votre application. Un objet
HttpSession ddi un utilisateur sera cr ou rcupr uniquement lorsque la page qu'il visite implique un appel
request.getSession(), en d'autres termes uniquement lorsque vous aurez plac un tel appel dans votre code. En ce qui
concerne la gestion de l'objet, c'est le conteneur de servlets qui va s'en charger, en le crant et le stockant en mmoire. Au
passage, le serveur dispose d'un moyen pour identifier chaque session qu'il cre : il leur attribue un identifiant unique, que nous
pouvons d'ailleurs retrouver via la mthode session.getId().
Ensuite, le conteneur va mettre en place un lment particulier dans la rponse HTTP qu'il va renvoyer au client : un Cookie.
Nous reviendrons plus tard sur ce ce que sont exactement ces cookies, et sur comment les manipuler. Pour le moment, voyez
simplement un cookie comme un simple marqueur, un petit fichier texte qui :
contient des informations envoyes par le serveur ;
est stock par votre navigateur, directement sur votre poste ;
a obligatoirement un nom et une valeur.
En l'occurrence, le cookie mis en place lors de la gestion d'une session utilisateur par le serveur se nomme JSESSIONID, et
contient l'identifiant de session unique en tant que valeur.
Pour rsumer, le serveur va placer directement chez le client son identifiant de session. Et donc chaque nouveau client, lorsqu'il
cre une session, le serveur va envoyer son identifiant au navigateur du client.

Comment est gr ce cookie ?

Je vous l'ai dj dit, nous allons y revenir plus en dtails dans un prochain chapitre. Toutefois, nous pouvons dj esquisser
brivement ce qui se passe dans les coulisses. La spcification du cookie HTTP, qui constitue un contrat auquel tout navigateur
web dcent ainsi que tout serveur web doit adhrer, est trs claire : elle demande au navigateur de renvoyer ce cookie dans les
requtes suivantes tant que le cookie reste valide.
Voil donc la cl du systme : le conteneur de servlets va analyser chaque requte HTTP entrante, y chercher le cookie ayant
pour nom JSESSIONID et utiliser sa valeur, c'est--dire l'identifiant de session, afin de rcuprer l'objet HttpSession associ
dans la mmoire du serveur.

Quand les donnes ainsi stockes deviennent-elles obsoltes ?

Ct serveur, vous le savez dj : l'objet HttpSesssion existera tant que sa dure de vie n'aura pas dpass le temps qu'il est
possible de spcifier dans la section <session-timeout> du fichier web.xml, qui est par dfaut de trente minutes. Donc si le
client n'utilise plus l'application pendant plus de trente minutes, le conteneur de servlets dtruira sa session. Aucune des
requtes suivantes, y compris celles contenant le cookie, n'auront alors accs la prcdente session : le conteneur de servlets
en crera une nouvelle.
Ct client, le cookie de session a une dure de vie galement, qui par dfaut est limite au temps durant lequel le navigateur
reste ouvert. Lorsque le client ferme son navigateur, le cookie est donc dtruit ct client. Si le client ouvre nouveau son
navigateur, le cookie associ la prcdente session ne sera alors plus envoy. Nous revenons alors au principe gnral que je

www.siteduzero.com

Partie 4 : Une application interactive !

252/345

vous ai nonc quelques lignes plus tt : un appel request.getSession() retournerait alors un nouvel objet
HttpSession, et mettrait ainsi en place un nouveau cookie contenant un nouvel identifiant de session.
Plutt que de vous ressortir les schmas prcdents en modifiant et compltant leurs lgende et explications pour y faire
apparatre la gestion du cookie, je vais vous faire pratiquer ! Nous allons directement tester notre petit systme de connexion, et
analyser ce qui se trame dans les entrailles des changes HTTP...

La pratique : scrutons nos requtes et rponses


Pour commencer, nous allons reprendre notre exemple de connexion et analyser les changes qu'il engendre :
1. redmarrez votre serveur Tomcat ;
2. fermez votre navigateur, puis ouvrez-le nouveau ;
3. supprimez toutes les donnes qui y sont automatiquement enregistres. Depuis Firefox ou Chrome, il suffit d'appuyer
simultanment sur Ctrl + Maj + Suppr pour qu'un menu de suppression du cache, des cookies et autres donnes diverses
apparaisse :

Suppression des donnes sous firefox

Suppression des

donnes sous Chrome


4. ouvrez un nouvel onglet vide, et appuyez alors sur F12 pour lancer Firebug depuis Firefox, ou l'outil quivalent intgr

www.siteduzero.com

Partie 4 : Une application interactive !

253/345

depuis Chrome ;
5. cliquez alors sur l'onglet Rseau de Firebug, ou sur l'onglet Network de l'outil intgr Chrome :

Onglet rseau sous Firebug

Onglet network sous Chrome

Le tout premier accs


Rendez-vous ensuite sur la page http://localhost:8080/pro/connexion. Les donnes enregistres ct client ont t effaces, et le
serveur a t redmarr, il s'agit donc ici de notre toute premire visite sur une page du site. En outre, nous savons que la servlet
Connexion associe cette page contient un appel request.getSession(). Observez alors ce qui s'affiche dans votre
outil :

www.siteduzero.com

Partie 4 : Une application interactive !

254/345

Cookie dans la rponse avec l'outil Firebug.

www.siteduzero.com

Partie 4 : Une application interactive !

255/345

Cookie dans la rponse avec l'outil de Chrome.


Vous pouvez ici remarquer plusieurs choses importantes :
la rponse renvoye par le serveur contient une instruction Set-Cookie, destine mettre en place le cookie de session
dans le navigateur du client ;
le nom du cookie est bien JSESSIONID, et sa valeur est bien un long identifiant unique ;
bien que je sois le seul rel client qui accde au site, le serveur considre mes visites depuis Firefox et Chrome comme
tant issues de deux clients distincts, et gnre donc deux sessions diffrentes. Vrifiez les identifiants, ils sont bien
diffrents d'un cran l'autre.
Dornavant, je vous afficherai uniquement des captures d'cran ralises avec l'outil de Chrome, pour ne pas
surcharger d'images ce chapitre. Si vous utilisez Firebug, reportez vous la capture prcdente si jamais vous ne vous
souvenez plus o regarder les informations relatives aux changes HTTP.

L'accs suivant, avec la mme session


Dans la foule, rendez-vous nouveau sur cette mme page de connexion (actualisez la page via un appui sur F5 par exemple).
Observez alors :

www.siteduzero.com

Partie 4 : Une application interactive !

256/345

Cookie dans la requte.


L encore, vous pouvez remarquer plusieurs choses importantes :
un cookie est cette fois envoy par le navigateur au serveur, dans le paramtre Cookie de l'en-tte de la requte HTTP
effectue ;
sa valeur correspond celle contenue dans le cookie envoy par le serveur dans la rponse prcdente ;
aprs rception de la premire rponse contenant l'instruction Set-Cookie, le navigateur avait donc bien sauvegard le
cookie gnr par le serveur, et le renvoie automatiquement lors des requtes suivantes ;
dans la deuxime rponse du serveur, il n'y a cette fois plus d'instruction Set-Cookie : le serveur ayant reu un cookie
nomm JSESSIONID depuis le client, et ayant trouv dans sa mmoire une session correspondant l'identifiant contenu
dans la valeur du cookie, il sait que le client a dj enregistr la session en cours et qu'il n'est pas ncessaire de demander
nouveau la mise en place d'un cookie !

L'accs suivant, aprs une dconnexion !


Rendez-vous maintenant sur la page http://localhost:8080/pro/deconnexion, puis retournez ensuite sur
http://localhost:8080/pro/connexion. Observez alors :

www.siteduzero.com

Partie 4 : Une application interactive !

257/345

Cookie dans la requte et la rponse.


Cette fois encore, vous pouvez remarquer plusieurs choses importantes :
deux cookies nomms JSESSIONID interviennent : un dans la requte et un dans la rponse ;
la valeur de celui prsent dans la requte contient l'identifiant de notre prcdente session. Puisque nous n'avons pas
ferm notre navigateur ni supprim les cookies enregistrs, le navigateur considre que la session est toujours ouverte
ct serveur, et envoie donc par dfaut le cookie qu'il avait enregistr lors de l'change prcdent !
la valeur de celui prsent dans la rponse contient un nouvel identifiant de session. Le serveur ayant supprim la session
de sa mmoire lors de la dconnexion du client (souvenez-vous du code de notre servlet de dconnexion), il ne trouve
aucune session qui corresponde l'identifiant envoy par le navigateur dans le cookie de la requte. Il cre donc une
nouvelle session, et demande aussitt au navigateur de remplacer le cookie existant par celui contenant le nouveau
numro de session, toujours via l'instruction Set-Cookie de la rponse renvoye !

L'accs une page sans session


Nous allons cette fois accder une page qui n'implique aucun appel request.getSession(). Redmarrez Tomcat,
effacez les donnes de votre navigateur via un Ctrl + Maj + Suppr, et rendez-vous alors sur la page
http://localhost:8080/pro/accesPublic.jsp. Observez alors :

www.siteduzero.com

Partie 4 : Une application interactive !

258/345

Cration de session par la JSP.


Pourquoi le serveur demande-t-il la mise en place d'un cookie de session dans le navigateur ?!

En effet, c'est un comportement troublant ! Je vous ai annonc qu'une session n'existait que lorsqu'un appel
request.getSession() tait effectu. Or, le contenu de notre page accesPublic.jsp ne fait pas intervenir de session, et
aucune servlet ne lui est associe : d'o sort cette session ? Eh bien rassurez-vous, je ne vous ai pas menti : c'est bien vous qui
contrlez la cration de la session. Seulement voil, il existe un comportement qui vous est encore inconnu, celui d'une page JSP
: par dfaut, une page JSP va toujours tenter de crer ou rcuprer une session.
Nous pouvons d'ailleurs le vrifier en jetant un oeil au code de la servlet auto-gnre par Tomcat. Nous l'avions dj fait lorsque
nous avions dcouvert les JSP pour la premire fois, et je vous avais alors fait remarquer que le rpertoire contenant ces fichiers
pouvait varier selon votre installation et votre systme. Voici un extrait du code du fichier accesPublic_jsp.java gnr :
Code : Java C:\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\pro\org\apache\jsp
\accesPublic_jsp.java
javax.servlet.http.HttpSession session = null;
...

www.siteduzero.com

Partie 4 : Une application interactive !

259/345

session = pageContext.getSession();

Voil donc l'explication de l'existence d'une session lors de l'accs notre page JSP : dans le code auto-gnr, il existe un appel
la mthode getSession() !
Comment viter la cration automatique d'une session depuis une page JSP ?

La solution qui s'offre nous est l'utilisation de la directive page. Voici la ligne ajouter en dbut de page pour empcher la
cration d'une session :
Code : JSP
<%@ page session="false" %>

Toutefois, comprenez bien : cette directive dsactive la session sur tout la page JSP. Autrement dit, en procdant ainsi
vous interdisez la manipulation de sessions depuis votre page JSP. Dans ce cas prcis, tout va bien, notre page n'en fait
pas intervenir. Mais dans une page qui accde des objets prsents en session, vous ne devez bien videmment pas
mettre en place cette directive !

ditez-donc votre page accesPublic.jsp et ajoutez-y cette directive en dbut de code. Redmarrez alors Tomcat, effacez les
donnes de votre navigateur via un Ctrl + Maj + Suppr, et rendez-vous nouveau sur la page
http://localhost:8080/pro/accesPublic.jsp. Observez cette fois :

www.siteduzero.com

Partie 4 : Une application interactive !

260/345

Dsactivation de la session dans la JSP.


Vous pouvez cette fois remarquer qu'aucun cookie n'intervient dans l'change HTTP ! Le serveur ne cherche pas crer ni
rcuprer de session, et par consquent il ne demande pas la mise en place d'un cookie dans le navigateur de l'utilisateur.
Dans un rel projet, ce genre d'optimisations n'a absolument aucun impact sur une application de petite envergure,
vous pouvez trs bien vous en passer. Mais sur une application trs forte frquentation ou simplement sur une page
trs fort trafic, en dsactivant l'accs la session lorsqu'elle n'est pas utilise, vous pouvez gagner en performances
et en espace mmoire disponibles : vous empcherez ainsi la cration d'objets inutiliss par le serveur, qui occuperont
de la place jusqu' ce qu'ils soient dtruits aprs la priode d'inactivit dpasse.

L'accs une page sans cookie


Dernier scenario et non des moindres, l'accs une page faisant intervenir un appel request.getSession() depuis un
navigateur qui n'accepte pas les cookies ! Eh oui, tous les navigateurs ne gardent pas leurs portes ouvertes, et certains refusent
la sauvegarde de donnes sous forme de cookies. Procdez comme suit pour bloquer les cookies depuis votre navigateur.
Depuis Firefox :
1. Allez sur la page http://localhost:8080/pro/connexion.
2. Faites un clic droit dans la page et slectionnez Informations sur la page.
3. Slectionnez alors le panneau Permissions.

www.siteduzero.com

Partie 4 : Une application interactive !

261/345

4. Sous Dfinir des cookies, dcochez Permissions par dfaut et cochez Bloquer :

5. Fermer la fentre "Informations sur la page".


Depuis Chrome :
1. Cliquez sur l'icne reprsentant une cl molette
2.
3.
4.
5.

qui est situe dans la barre d'outils du navigateur.

Slectionnez Paramtres.
Cliquez sur Afficher les paramtres avancs.
Dans la section "Confidentialit", cliquez sur le bouton Paramtres de contenu.
Dans la section "Cookies", modifiez les paramtres suivants :

www.siteduzero.com

Partie 4 : Une application interactive !

262/345

Redmarrez ensuite Tomcat, effacez les donnes de votre navigateur via un Ctrl + Maj + Suppr, et rendez-vous sur la page
http://localhost:8080/pro/connexion. Vous observerez alors que la rponse du serveur contient une instruction Set-Cookie.
Actualisez maintenant la page en appuyant sur F5, et vous constaterez cette fois que la requte envoye par votre navigateur ne
contient pas de cookie, et que la rponse du serveur contient nouveau une instruction Set-Cookie prsentant un identifiant de
session diffrent ! Et c'est tout fait logique :
le navigateur n'accepte plus les cookies, il n'a donc pas enregistr le premier identifiant envoy par le serveur dans la
premire rponse. Par consquent, il n'a pas envoy d'identifiant dans la requte suivante ;
le serveur ne trouvant aucune information de session dans la seconde requte envoye par le navigateur du client, il le
considre comme un nouveau visiteur, cre une nouvelle session et lui demande d'en enregistrer le nouvel identifiant
dans un cookie.

Ok, c'est logique. Mais dans ce cas, comment le serveur peut-il associer une session un utilisateur ?

Voil en effet une excellente question : comment le serveur va-t-il tre capable de retrouver des informations en session s'il n'est
pas capable de reconnatre un visiteur d'une requte l'autre ? tant donn l'tat actuel de notre code, la rponse est simple : il
ne peut pas ! D'ailleurs, vous pouvez vous en rendre compte simplement :

www.siteduzero.com

Partie 4 : Une application interactive !

263/345

1. rendez-vous sur la page de connexion, saisissez des donnes correctes et validez le formulaire. Observez alors :

2. ouvrez alors un nouvel onglet, et rendez-vous nouveau sur la page de connexion. Observez cette fois :

Lors de nos prcdents tests, dans la partie sur les vrifications, le formulaire r-affichait l'adresse mail avec laquelle vous vous
tiez connect auparavant. Cette fois, aucune information n'est r-affiche et le formulaire de connexion apparat nouveau
vierge. Vous constatez donc bien l'incapacit du serveur vous reconnatre !
Pas de panique, nous allons y remdier trs simplement. Dans notre page connexion.jsp, nous allons modifier une ligne de code :
Code : JSP - /WEB-INF/connexion.jsp
<!-- Dans la page connexion.jsp, remplacez la ligne suivante : -->
<form method="post" action="connexion">
<!-- Par cette ligne : -->
<form method="post" action="<c:url value="/connexion" />">

Si vous reconnaissez ici la balise <c:url/> de la JSTL Core, vous devez galement vous souvenir qu'elle est quipe pour la
gestion automatique des sessions. Je vous avais en effet dj expliqu que cette balise avait l'effet suivant :
Code : JSP
<%-- L'url ainsi gnre --%>
<c:url value="test.jsp" />
<%-- Sera rendue ainsi dans la page web finale,
si le cookie est prsent --%>
test.jsp
<%-- Et sera rendue sous cette forme si le cookie est absent --%>
test.jsp;jsessionid=BB569C7F07C5E887A4D

Et a, c'est exactement ce dont nous avons besoin ! Puisque notre navigateur n'accepte plus les cookies, nous n'avons pas
d'autre choix que de faire passer l'identifiant de session directement au sein de l'URL.

www.siteduzero.com

Partie 4 : Une application interactive !

264/345

Une fois la modification sur la page connexion.jsp effectue, suivez ce scnario de tests :
rendez-vous nouveau sur la page http://localhost:8080/pro/connexion, et regardez la fois la rponse envoye par le
serveur et le code source de la page de connexion. Vous constaterez alors que puisque le serveur ne dtecte aucun
cookie prsent chez le client, il va d'un ct tenter de passer l'identifiant de session via l'instruction Set-Cookie, et de
l'autre gnrer une URL prcisant l'identifiant de session. Voyez plutt :

connectez-vous alors avec des donnes valides. Vous retrouverez alors dans la barre d'adresse de votre navigateur l'URL
modifie par la balise <c:url/>, contenant l'identifiant de session pass par le serveur :

ouvrez un nouvel onglet, et copiez/collez l'URL dans la barre d'adresse pour y ouvrir nouveau la page de connexion en
conservant le JSESSIONID. Vous constaterez cette fois que le serveur vous a bien reconnu en se basant sur l'identifiant
contenu dans l'URL que vous lui transmettez, et qu'il est capable de retrouver l'adresse mail avec laquelle vous vous tes

www.siteduzero.com

Partie 4 : Une application interactive !

265/345

connects :

accdez maintenant la page http://localhost:8080/pro/connexion sans prciser le JSESSIONID dans l'URL, et constatez
que le serveur est nouveau incapable de vous reconnatre et vous affiche un formulaire vierge !

Nous en avons enfin termin avec notre batterie de tests, et avec tout ce que vous avez dcouvert, les sessions n'ont maintenant
presque plus aucun secret pour vous !

Le bilan
Voici un rcapitulatif des points importants que vous devez bien comprendre et assimiler :
une session est un espace mmoire allou sur le serveur, et dont le contenu n'est accessible que depuis le serveur ;
afin de savoir quel client est associ telle session cre, le serveur transmet au client l'identifiant de la session qui lui
est ddie, le JSESSIONID, dans les en-ttes de la rponse HTTP sous forme d'un cookie ;
si le navigateur accepte les cookies, il stocke alors ce cookie contenant l'identifiant de session, et le retransmet au serveur
dans les en-ttes de chaque requte HTTP qui va suivre ;
si le serveur lui renvoie un nouveau numro, autrement dit si le serveur a ferm l'ancienne session et en a ouvert une
nouvelle, alors le navigateur remplace l'ancien numro stock par ce nouveau numro, en crasant l'ancien cookie par le
nouveau ;
si le navigateur n'accepte pas les cookies, alors le serveur dispose d'un autre moyen pour identifier le client : il est
capable de chercher l'identifiant directement dans l'URL de la requte, et pas uniquement dans ses en-ttes ;
il suffit au dveloppeur de manipuler correctement les URL qu'il met en place dans son code pour permettre une gestion
continue des sessions, indpendante de l'acceptation ou non des cookies ct client.
Nous en avons termin avec la dcouverte des sessions, et j'espre que cet exemple pratique vous aura fait comprendre
simplement les concepts cls.
Vous avez maintenant un outil puissant votre disposition, et ne vous fiez pas uniquement au titre du chapitre : s'il est vrai que
les sessions peuvent tre utilises pour raliser un systme de connexion, ce n'est absolument pas le seul usage qu'il est
possible d'en faire ! Nous nous en sommes ici servis pour stocker les informations relatives l'identit de nos visiteurs, mais
elles peuvent bien entendu vous servir pour stocker n'importe quoi : les commandes en cours des clients dans le cas d'un site
d'e-commerce, l'historique des transactions bancaires des clients dans le cas d'un site de finance, la liste des dernires
interventions dans le cas du site du zro...

www.siteduzero.com

Partie 4 : Une application interactive !

266/345

Le filtre : crez un espace membre


Maintenant que nous savons manipuler les sessions et connecter nos utilisateurs, il serait intressant de pouvoir mettre en place
un espace membre dans notre application : c'est un ensemble de pages web qui est uniquement accessible aux utilisateurs
connects.
Pour ce faire, nous allons commencer par tudier le principe sur une seule page, via une servlet classique. Puis nous allons
tendre ce systme tout un ensemble de page, et dcouvrir un nouveau composant cousin de la servlet : le filtre !

Restreindre l'accs une page


Ce principe est massivement utilis dans la plupart des applications web : les utilisateurs enregistrs et connects un site ont
bien souvent accs plus de contenu et de fonctionnalits que les simples visiteurs.
Comment mettre en place une telle restriction d'accs ?

Jusqu' prsent, nous avons pris l'habitude de placer toutes nos JSP sous le rpertoire /WEB-INF, et de les rendre accessibles
travers des servlets. Nous savons donc que chaque requte qui leur est adresse passe d'abord par une servlet. Ainsi pour
limiter l'accs une page donne, la premire intuition qui nous vient l'esprit, c'est de nous servir de la servlet qui lui est
associe pour effectuer un test sur le contenu de la session, afin de vrifier si le client est dj connect ou non.

Les pages d'exemple


Mettons en place pour commencer deux pages JSP :
une dont nous allons plus tard restreindre l'accs aux utilisateurs connects uniquement, nomme accesRestreint.jsp et
place sous /WEB-INF ;
une qui sera accessible tous les visiteurs, nomme accesPublic.jsp et place sous la racine du projet (symbolise par le
dossier WebContent sous Eclipse).
Le contenu de ces pages importe peu, voici les exemples basiques que je vous propose :
Code : JSP - /WEB-INF/accesRestreint.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Accs restreint</title>
</head>
<body>
<p>Vous tes connect(e) avec l'adresse
${sessionScope.sessionUtilisateur.email}, vous avez bien accs
l'espace restreint.</p>
</body>
</html>

Code : JSP - /accesPublic.jsp


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Accs public</title>
</head>
<body>
<p>Vous n'avez pas accs l'espace restreint : vous devez
vous <a href="connexion">connecter</a> d'abord. </p>
</body>
</html>

www.siteduzero.com

Partie 4 : Une application interactive !

267/345

Rien de particulier signaler ici, si ce n'est l'utilisation d'une expression EL dans la page restreinte, afin d'accder l'adresse mail
de l'utilisateur enregistr en session, travers l'objet implicite sessionScope.

La servlet de contrle
Ce qu'il nous faut raliser maintenant, c'est ce fameux contrle sur le contenu de la session avant d'autoriser l'accs la page
accesRestreint.jsp. Voyez plutt :
Code : Java - com.sdzee.servlets.Restriction
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

public class Restriction extends HttpServlet {


public static final String ACCES_PUBLIC
=
"/accesPublic.jsp";
public static final String ACCES_RESTREINT = "/WEBINF/accesRestreint.jsp";
public static final String ATT_SESSION_USER =
"sessionUtilisateur";
public void doGet( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/* Rcupration de la session depuis la requte */
HttpSession session = request.getSession();
/**
* Si l'objet utilisateur n'existe pas dans la session en cours,
alors
* l'utilisateur n'est pas connect.
*/
if ( session.getAttribute( ATT_SESSION_USER ) == null ) {
/* Redirection vers la page publique */
response.sendRedirect( request.getContextPath() +
ACCES_PUBLIC );
} else {
/* Affichage de la page restreinte */
this.getServletContext().getRequestDispatcher(
ACCES_RESTREINT ).forward( request, response );
}
}
}

Comme vous le voyez, le procd est trs simple : il suffit de rcuprer la session, de tester si l'attribut sessionUtilisateur y existe
dj, et de rediriger vers la page restreinte ou publique selon le rsultat du test.
Remarquez au passage l'emploi d'une redirection dans le cas de la page publique, et d'un forwarding dans le cas de la
page prive. Vous devez maintenant tre familiers avec le principe, je vous l'ai expliqu dans le chapitre prcdent. Ici, si
j'avais mis en place un forwarding en lieu et place de la redirection HTTP pour la page publique, alors l'URL dans le
navigateur de l'utilisateur n'aurait pas t mise jour en cas d'chec de l'accs la page restreinte.
Par ailleurs, vous devez galement prter attention la manire dont j'ai construit l'URL utilise pour la redirection, la ligne 26.
Vous tes dj au courant que contrairement au forwarding qui est limit aux pages internes, la redirection HTTP permet quant
elle d'envoyer la requte n'importe quelle page, y compris des pages provenant d'autres sites. Ce que vous ne savez pas
encore, moins d'avoir lu attentivement les documentations respectivement des mthodes getRequestDispatcher() et

www.siteduzero.com

Partie 4 : Une application interactive !

268/345

sendRedirect(), c'est que l'URL prise en argument par la mthode de forwarding est relative au contexte de l'application,
alors que l'URL prise en argument par la mthode de redirection est relative la racine de l'application !
Concrtement, qu'est-ce que a implique ?

Cette diffrence est trs importante :


l'URL passe la mthode getRequestDispatcher() doit tre interne l'application. En loccurrence, dans notre
projet cela signifie qu'il est impossible de prciser une URL qui cible une page en dehors du projet pro. Ainsi, un appel
getRequestDispatcher( "/accesPublic.jsp" ) ciblera automatiquement la page /pro/accesPublic.jsp,
vous n'avez pas prciser vous-mme le contexte /pro ;
l'URL passe la mthode sendRedirect() peut tre externe l'application. Cela veut dire que vous devez
manuellement spcifier l'application dans laquelle se trouve votre page, et non pas faire comme avec la mthode de
forwarding , dans laquelle par dfaut toute URL est considre comme tant interne l'application. Cela signifie donc que
nous devons prciser le contexte de l'application dans l'URL passe sendRedirect(). En l'occurrence, nous
devons lui dire que nous souhaitons joindre une page contenue dans le projet pro : plutt que d'crire en dur
/pro/accesPublic.jsp, et risquer de devoir manuellement modifier cette URL si nous changeons le nom du contexte du
projet plus tard, nous utilisons ici un appel request.getContextPath(), qui retourne automatiquement le
contexte de l'application courante, c'est--dire /pro dans notre cas.
Bref, vous l'aurez compris, vous devez tre attentif aux mthodes que vous employez et la manire dont elles vont
grer les URL que vous leur transmettez. Entre les URL absolues, les URL relatives la racine de l'application, les URL
relatives au contexte de l'application et les URL relatives au rpertoire courant, il est parfois difficile de ne pas s'emmler
les crayons !

Pour terminer, voici sa configuration dans le fichier web.xml de notre application :


Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>Inscription</servlet-name>
<servlet-class>com.sdzee.servlets.Inscription</servlet-class>
</servlet>
<servlet>
<servlet-name>Connexion</servlet-name>
<servlet-class>com.sdzee.servlets.Connexion</servlet-class>
</servlet>
<servlet>
<servlet-name>Deconnexion</servlet-name>
<servlet-class>com.sdzee.servlets.Deconnexion</servlet-class>
</servlet>
<servlet>
<servlet-name>Restriction</servlet-name>
<servlet-class>com.sdzee.servlets.Restriction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Inscription</servlet-name>
<url-pattern>/inscription</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Connexion</servlet-name>
<url-pattern>/connexion</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Deconnexion</servlet-name>
<url-pattern>/deconnexion</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Restriction</servlet-name>
<url-pattern>/restriction</url-pattern>

www.siteduzero.com

Partie 4 : Une application interactive !

269/345

</servlet-mapping>
</web-app>

N'oubliez pas de redmarrer Tomcat pour que ces modifications soient prises en compte.

Test du systme
Pour vrifier le bon fonctionnement de cet exemple d'accs restreint, suivez le scnario suivant :
1. redmarrez Tomcat, afin de faire disparatre toute session qui serait encore active ;
2. rendez-vous sur la page http://localhost:8080/pro/restriction, et constatez au passage la redirection (changement d'URL) :

Acces restreint.
3. cliquez alors sur le lien vers la page de connexion, entrez des informations valides et connectez-vous :

Connexion.
4. rendez-vous nouveau sur la page http://localhost:8080/pro/restriction, et constatez au passage l'absence de redirection
(l'URL ne change pas) :

Acces restreint.
5. allez maintenant sur la page http://localhost:8080/pro/deconnexion :

Deconnexion.
6. retournez une dernire fois sur la page http://localhost:8080/pro/restriction.

www.siteduzero.com

Partie 4 : Une application interactive !

270/345

Acces restreint.

Sans grande surprise, le systme fonctionne bien : nous devons tre connects pour accder la page dont l'accs est restreint,
sinon nous sommes redirigs vers la page publique.

Le problme
Oui, parce qu'il y a un lger problme ! Dans cet exemple, nous nous sommes occups de deux pages : une page prive, une page
publique. C'tait rapide, simple et efficace. Maintenant si je vous demande d'tendre la restriction 100 pages prives, comment
comptez-vous vous y prendre ?
En l'tat actuel de vos connaissances, vous n'avez pas d'autres moyens que de mettre en place un test sur le contenu de la
session dans chacune des 100 servlets contrlant l'accs aux 100 pages prives. Vous vous doutez bien que ce n'est absolument
pas viable, et qu'il nous faut apprendre une autre mthode. Le remde nos soucis s'appelle le filtre, et nous allons le dcouvrir
dans le paragraphe suivant.

Le principe du filtre
Gnralits
Qu'est-ce qu'un filtre ?

Un filtre est un objet Java qui peut modifier les en-ttes et le contenu d'une requte ou d'une rponse. Il se positionne avant la
servlet, et intervient donc en amont dans le cycle de traitement d'une requte par le serveur. Il peut tre associ une ou
plusieurs servlets. Voici un schma reprsentant le cas o plusieurs filtres seraient associs notre servlet de connexion :

Vous pouvez d'ores et dj remarquer sur cette illustration que les filtres peuvent intervenir la fois sur la requte entrante et sur
la rponse mise, et qu'ils s'appliquent dans un ordre prcis et en cascade.
Quelle est la diffrence entre un filtre et une servlet ?

Alors qu'un composant web comme la servlet est utilis pour gnrer une rponse HTTP envoyer au client, le filtre quant lui
ne cre habituellement pas de rponse, il se contente gnralement d'appliquer d'ventuelles modifications la paire requte /
rponse existante. Voici une liste des actions les plus communes ralisables par un filtre :
interroger une requte et agir en consquence ;
empcher la paire requte / rponse d'tre transmise plus loin, autrement dit bloquer son cheminement dans l'application ;
modifier les en-ttes et le contenu de la requte courante ;
modifier les en-ttes et le contenu de la rponse courante.

www.siteduzero.com

Partie 4 : Une application interactive !

271/345

Quel est l'intrt d'un filtre ?

Le filtres offre trois avantages majeurs, qui sont interdpendants :


il permet de modifier de manire transparente un change HTTP. En effet, il n'implique pas ncessairement la cration
d'une rponse, et peut se contenter de modifier la paire requte / rponse existante.
tout comme la servlet, il est dfini par un mapping , et peut ainsi tre appliqu plusieurs requtes.
plusieurs filtres peuvent tre appliqus en cascade la mme requte.
C'est la combinaison de ces trois proprits qui fait du filtre un composant parfaitement adapt tous les traitements de masse,
ncessitant d'tre appliqus systmatiquement tout ou partie des pages d'une application. titre d'exemple, on peut citer les
usages suivants : l'authentification des visiteurs, la gnration de logs, la conversion d'images, la compression de donnes ou
encore le chiffrement de donnes.

Fonctionnement
Regardons maintenant comment est construit un filtre. l'instar de sa cousine la servlet, qui doit obligatoirement implmenter
l'interface Servlet, le filtre doit implmenter l'interface Filter. Mais cette fois, contrairement au cas de la servlet qui peut par
exemple hriter de HttpServlet, il n'existe ici pas de classe fille. Lorsque nous tudions la documentation de l'interface, nous
remarquons qu'elle est plutt succincte, elle ne contient que trois dfinitions de mthodes : init(), doFilter() et
destroy().
Vous le savez, lorsqu'une classe Java implmente une interface, elle doit redfinir chaque mthode prsente dans cette interface.
Ainsi, voici le code de la structure vide d'un filtre :
Code : Java - Exemple d'un filtre
import java.io.IOException;
import
import
import
import
import
import

javax.servlet.Filter;
javax.servlet.FilterChain;
javax.servlet.FilterConfig;
javax.servlet.ServletException;
javax.servlet.ServletRequest;
javax.servlet.ServletResponse;

public class ExempleFilter implements Filter {


public void init( FilterConfig config ) throws ServletException
{
// ...
}
public void doFilter( ServletRequest request, ServletResponse
response, FilterChain chain ) throws IOException,
ServletException {
// ...
}

public void destroy() {


// ...
}

Les mthodes init() et destroy() concernent le cycle de vie du filtre dans l'application. Nous allons y revenir en apart
dans le paragraphe suivant. La mthode qui va contenir les traitements effectus par le filtre est donc doFilter(). Vous
pouvez d'ailleurs le deviner en regardant les arguments qui lui sont transmis : elle reoit en effet la requte et la rponse, ainsi
qu'un troisime lment, la chane des filtres.
quoi sert cette chane ?

www.siteduzero.com

Partie 4 : Une application interactive !

272/345

Elle vous est encore inconnue, mais elle est en ralit un objet relativement simple : je vous laisse jeter un oeil sa courte
documentation. Je vous ai annonc un peu plus tt que plusieurs filtres pouvaient tre appliqus la mme requte. Eh bien
c'est travers cette chane qu'un ordre va pouvoir tre tabli : chaque filtre qui doit tre appliqu la requte va tre inclus la
chane, qui ressemble en fin de compte une file d'invocations.
Cette chane est entirement gre par le conteneur, vous n'avez pas vous en soucier. La seule chose que vous allez contrler,
c'est le passage d'un filtre l'autre dans cette chane via l'appel de sa seule et unique mthode, elle aussi nomme doFilter().
Comment l'ordre des filtres dans la chane est-il tabli ?

Tout comme une servlet, un filtre doit tre dclar dans le fichier web.xml de l'application pour tre reconnu :
Code : XML - Exemple de dclaration de filtres
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
...
<filter>
<filter-name>Exemple</filter-name>
<filter-class>package.ExempleFilter</filter-class>
</filter>
<filter>
<filter-name>SecondExemple</filter-name>
<filter-class>package.SecondExempleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Exemple</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>SecondExemple</filter-name>
<url-pattern>/page</url-pattern>
</filter-mapping>
...
</web-app>

Vous reconnaissez ici la structure des blocs utiliss pour dclarer une servlet, la seule diffrence rside dans le nommage des
champs : <servlet> devient <filter>, <servlet-name> devient <filter-name>, etc.
Eh bien l encore, de la mme manire que pour les servlets, l'ordre des dclarations des mappings des filtres dans le fichier est
important : c'est cet ordre qui va tre suivi lors de l'invocation de plusieurs filtres appliqus une mme requte. En d'autres
termes, c'est dans cet ordre que la chane des filtres va tre automatiquement initialise par le conteneur. Ainsi, si vous souhaitez
qu'un filtre soit appliqu avant un autre, placez son mapping avant le mapping du second dans le fichier web.xml de votre
application.

Cycle de vie
Avant de passer l'application pratique et la mise en place d'un filtre, penchons-nous un instant sur la manire dont le
conteneur le gre. Une fois n'est pas coutume, il y a l encore de fortes similitudes avec une servlet. Lorsque l'application web
dmarre, le conteneur de servlets va crer une instance du filtre et la garder en mmoire durant toute l'existence de l'application.
La mme instance va tre rutilise pour chaque requte entrante dont l'URL correspond au contenu du champ <urlpattern> du mapping du filtre. Lors de l'instanciation, la mthode init() est appele par le conteneur : si vous souhaitez
passer des paramtres d'initialisation au filtre, vous pouvez alors les rcuprer depuis l'objet FilterConfig pass en
argument la mthode.
Pour chacune de ces requtes, la mthode doFilter() va tre appele. Ensuite c'est videmment au dveloppeur, vous
donc, de dcider quoi faire dans cette mthode : une fois vos traitements appliqus, soit vous appelez la mthode doFilter()
de l'objet FilterChain pour passer au filtre suivant dans la liste, soit vous effectuez une redirection ou un forwarding pour

www.siteduzero.com

Partie 4 : Une application interactive !

273/345

changer la destination d'origine de la requte.


Enfin, je me rpte mais il est possible de faire en sorte que plusieurs filtres s'appliquent la mme URL. Ils seront alors appels
dans le mme ordre que celui de leurs dclarations de mapping dans le fichier web.xml de l'application.

Restreindre l'accs un ensemble de pages


Restreindre un rpertoire
Aprs cette longue introduction plutt abstraite, lanons-nous et essayons d'utiliser un filtre pour rpondre notre problme :
mettre en place une restriction d'accs sur un groupe de pages. C'est probablement l'utilisation la plus classique du filtre dans
une application web !
Dans notre cas, nous allons nous en servir pour vrifier la prsence d'un utilisateur dans la session :
s'il est prsent, notre filtre laissera la requte poursuivre son cheminement jusqu' la page souhaite ;
s'il n'existe pas, notre filtre redirigera l'utilisateur vers la page publique.

Pour cela, nous allons commencer par crer un rpertoire que nous allons placer la racine de notre projet et nommer restreint,
dans lequel nous allons dplacer le fichier accesRestreint.jsp et y placer les deux fichiers suivants :
Code : JSP - /restreint/accesRestreint2.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Accs restreint 2</title>
</head>
<body>
<p>Vous tes connect(e) avec l'adresse
${sessionScope.sessionUtilisateur.email}, vous avez bien accs
l'espace restreint numro 2.</p>
</body>
</html>

Code : JSP - /restreint/accesRestreint3.jsp


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Accs restreint 3</title>
</head>
<body>
<p>Vous tes connect(e) avec l'adresse
${sessionScope.sessionUtilisateur.email}, vous avez bien accs
l'espace restreint numro 3.</p>
</body>
</html>

Voici un aperu de larborescence que vous devez alors obtenir :

www.siteduzero.com

Partie 4 : Une application interactive !

274/345

Arborescence sous Eclipse.

C'est de ce rpertoire restreint que nous allons limiter l'accs aux utilisateurs connects. Souvenez-vous bien du point suivant :
pour le moment, nos pages JSP n'tant pas situes sous le rpertoire /WEB-INF, elles sont accessibles au public directement
depuis leur URL respective. Par exemple, vous pouvez vous rendre sur http://localhost:8080/pro/restreint/accesRestreint.jsp
mme sans tre connect, le seul problme que vous rencontrerez est l'absence de l'adresse email dans le message affich.
Supprimez ensuite la servlet Restriction que nous avions dveloppe en dbut de chapitre, ainsi que sa dclaration
dans le fichier web.xml : elle nous est dornavant inutile.
Nous pouvons maintenant crer notre filtre. Je vous propose de le placer dans un nouveau package com.sdzee.filters, et
de le nommer RestrictionFilter. Voyez ci-dessous comment procder aprs un Ctrl + N sous Eclipse :

www.siteduzero.com

Partie 4 : Une application interactive !

275/345

Cration d'un filtre.

Et remplacez alors le code gnr automatiquement par Eclipse par le code suivant :
Code : Java - com.sdzee.filters.RestrictionFilter
package com.sdzee.filters;
import java.io.IOException;
import
import
import
import
import
import

javax.servlet.Filter;
javax.servlet.FilterChain;
javax.servlet.FilterConfig;
javax.servlet.ServletException;
javax.servlet.ServletRequest;
javax.servlet.ServletResponse;

public class RestrictionFilter implements Filter {


public void init( FilterConfig config ) throws ServletException
{
}
public void doFilter( ServletRequest req, ServletResponse resp,
FilterChain chain ) throws IOException,
ServletException {
}

www.siteduzero.com

Partie 4 : Une application interactive !

276/345

public void destroy() {


}

Rien de fondamental n'a chang par rapport la version gnre par Eclipse, j'ai simplement retir les commentaires et renomm
les arguments des mthodes pour que le code de notre filtre soit plus lisible par la suite.
Comme vous le savez, c'est dans la mthode doFilter() que nous allons raliser notre vrification. Puisque nous avons dj
dvelopp cette fonctionnalit dans une servlet en dbut de chapitre, il nous suffit de reprendre son code et de l'adapter un peu :
Code : Java - com.sdzee.filters.RestrictionFilter
package com.sdzee.filters;
import java.io.IOException;
import
import
import
import
import
import
import
import
import

javax.servlet.Filter;
javax.servlet.FilterChain;
javax.servlet.FilterConfig;
javax.servlet.ServletException;
javax.servlet.ServletRequest;
javax.servlet.ServletResponse;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

public class RestrictionFilter implements Filter {


public static final String ACCES_PUBLIC
=
"/accesPublic.jsp";
public static final String ATT_SESSION_USER =
"sessionUtilisateur";
{

public void init( FilterConfig config ) throws ServletException


}

public void doFilter( ServletRequest req, ServletResponse res,


FilterChain chain ) throws IOException,
ServletException {
/* Cast des objets request et response */
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
/* Rcupration de la session depuis la requte */
HttpSession session = request.getSession();
/**
* Si l'objet utilisateur n'existe pas dans la session en cours,
alors
* l'utilisateur n'est pas connect.
*/
if ( session.getAttribute( ATT_SESSION_USER ) == null ) {
/* Redirection vers la page publique */
response.sendRedirect( request.getContextPath() +
ACCES_PUBLIC );
} else {
/* Affichage de la page restreinte */
chain.doFilter( request, response );
}
}

public void destroy() {


}

Quelques explications s'imposent :

www.siteduzero.com

Partie 4 : Une application interactive !

277/345

aux lignes 25 et 26, vous constatez que nous convertissons les objets transmis en argument notre mthode
doFilter(). La raison est simple : comme je vous l'ai dj dit, il n'existe pas de classe fille implmentant l'interface
Filter, alors que ct servlet nous avons bien HttpServlet qui implmente Servlet. Ce qui signifie que notre
filtre n'est pas spcialis, il implmente uniquement Filter et peut traiter n'importe quel type de requte et pas
seulement les requtes HTTP. C'est donc pour cela que nous devons manuellement spcialiser nos objets, en effectuant
un cast vers les objets ddis aux requtes et rponses HTTP : c'est seulement en procdant cette conversion que nous
aurons accs ensuite la session, qui est propre l'objet HttpServletRequest, et n'existe pas dans l'objet
ServletRequest.
la ligne 40, nous avons remplac le forwarding auparavant en place dans notre servlet par un appel la mthode
doFilter() de l'objet FilterChain. Celle-ci a en effet une particularit intressante : si un autre filtre existe aprs
le filtre courant dans la chane, alors c'est vers ce filtre que la requte va tre transmise. Par contre, si aucun autre filtre
n'est prsent ou si le filtre courant est le dernier de la chane, alors c'est vers la ressource initialement demande que la
requte va tre achemine. En l'occurrence, nous n'avons qu'un seul filtre en place, notre requte sera donc logiquement
transmise la page demande.
Pour mettre en scne notre filtre, il nous faut enfin le dclarer dans le fichier web.xml de notre application :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<filter>
<filter-name>RestrictionFilter</filter-name>
<filter-class>com.sdzee.filters.RestrictionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RestrictionFilter</filter-name>
<url-pattern>/restreint/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Inscription</servlet-name>
<servlet-class>com.sdzee.servlets.Inscription</servlet-class>
</servlet>
<servlet>
<servlet-name>Connexion</servlet-name>
<servlet-class>com.sdzee.servlets.Connexion</servlet-class>
</servlet>
<servlet>
<servlet-name>Deconnexion</servlet-name>
<servlet-class>com.sdzee.servlets.Deconnexion</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Inscription</servlet-name>
<url-pattern>/inscription</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Connexion</servlet-name>
<url-pattern>/connexion</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Deconnexion</servlet-name>
<url-pattern>/deconnexion</url-pattern>
</servlet-mapping>
</web-app>

la ligne 9, vous pouvez remarquer l'url-pattern prcis : le caractre * signifie que notre filtre va tre appliqu toutes les
pages prsentes sous le rpertoire /restreint.
Redmarrez ensuite Tomcat pour que les modifications effectues soient prises en compte, puis suivez ce scnario de tests :
1. essayez d'accder la page http://localhost:8080/pro/restreint/accesRestreint.jsp, et constatez la redirection vers la page

www.siteduzero.com

Partie 4 : Une application interactive !

278/345

publique :

Acces restreint.
2. rendez-vous sur la page de connexion et connectez-vous avec des informations valides :

Connexion.
3. essayez nouveau d'accder la page http://localhost:8080/pro/restreint/accesRestreint.jsp, et constatez le succs de
l'opration :

Acces restreint.
4. essayez alors d'accder aux pages accesRestreint2.jsp et accesRestreint3.jsp, et constatez l encore le succs de
l'opration ;
5. rendez-vous sur la page de dconnexion :

Deconnexion.
6. puis tentez alors d'accder la page http://localhost:8080/pro/restreint/accesRestreint.jsp et constatez cette fois l'chec
de l'opration :

Acces restreint.

www.siteduzero.com

Partie 4 : Une application interactive !

279/345

Notre problme est bel et bien rgl ! Nous sommes maintenant capables de bloquer l'accs un ensemble de pages avec une
simple vrification dans un unique filtre : nous n'avons pas besoin de dupliquer le contrle effectu dans des servlets appliques
chacune des pages !

Restreindre l'application entire


Avant de nous quitter, regardons brivement comment forcer l'utilisateur se connecter pour accder notre application. Ce
principe est par exemple souvent utilis sur les intranets d'entreprise, o la connexion est gnralement obligatoire ds l'entre
sur le site.
La premire chose faire, c'est de modifier la porte d'application du filtre. Puisque nous souhaitons couvrir l'intgralit des
requtes entrantes, il suffit d'utiliser le caractre * appliqu la racine. La dclaration de notre filtre devient donc :
Code : XML - /WEB-INF/web.xml
<filter>

<filter-name>RestrictionFilter</filter-name>
<filter-class>com.sdzee.filters.RestrictionFilter</filter-

class>
</filter>
<filter-mapping>
<filter-name>RestrictionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Redmarrez Tomcat pour que la modification soit prise en compte.


Maintenant, vous devez rflchir ce que nous venons de mettre en place : nous avons ordonn notre filtre de bloquer toutes
les requtes entrantes si l'utilisateur n'est pas connect. Le problme, c'est que si nous ne changeons pas le code de notre filtre,
alors l'utilisateur ne pourra jamais accder notre site !
Pourquoi ? Notre filtre le redirigera vers la page accesPublic.jsp comme il le faisait dans le cas de la restriction d'accs
au rpertoire restreint, non ?
Eh bien non, plus maintenant ! La mthode de redirection que nous avons mise en place va bien tre appele, mais comme vous
le savez elle va dclencher un change HTTP, un aller-retour avec le navigateur du client. Et donc le client va renvoyer
automatiquement une requte, qui va son tour tre intercepte par notre filtre. Le client n'tant toujours pas connect, le mme
phnomne va se reproduire, etc. Si vous y tenez, vous pouvez essayer : vous verrez alors votre navigateur vous avertir que la
page que vous essayez de contacter pose problme. Voici les messages affichs respectivement par Chrome et Firefox :

www.siteduzero.com

Partie 4 : Une application interactive !

280/345

Echec de la restriction.

Echec de la restriction.
La solution est simple :
1. il faut envoyer l'utilisateur vers la page de connexion, et non plus vers la page accesPublic.jsp ;
2. il faut effectuer non plus une redirection HTTP mais un forwarding , afin qu'aucun nouvel change HTTP n'ait lieu et que
la demande aboutisse.
Voici ce que devient donc le code de notre filtre :
Code : Java - com.sdzee.filters.RestrictionFilter
package com.sdzee.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;

www.siteduzero.com

Partie 4 : Une application interactive !


import
import
import
import
import
import
import

281/345

javax.servlet.FilterConfig;
javax.servlet.ServletException;
javax.servlet.ServletRequest;
javax.servlet.ServletResponse;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

public class RestrictionFilter implements Filter {


public static final String ACCES_CONNEXION = "/connexion";
public static final String ATT_SESSION_USER =
"sessionUtilisateur";
{

public void init( FilterConfig config ) throws ServletException


}

public void doFilter( ServletRequest req, ServletResponse res,


FilterChain chain ) throws IOException,
ServletException {
/* Cast des objets request et response */
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
/* Rcupration de la session depuis la requte */
HttpSession session = request.getSession();
/**
* Si l'objet utilisateur n'existe pas dans la session en cours,
alors
* l'utilisateur n'est pas connect.
*/
if ( session.getAttribute( ATT_SESSION_USER ) == null ) {
/* Redirection vers la page publique */
request.getRequestDispatcher( ACCES_CONNEXION ).forward( request,
response );
} else {
/* Affichage de la page restreinte */
chain.doFilter( request, response );
}
}

public void destroy() {


}

C'est tout pour le moment. Testez alors d'accder la page http://localhost:8080/pro/restreint/accesRestreint.jsp, vous obtiendrez
:

Ratage du CSS.

www.siteduzero.com

Partie 4 : Une application interactive !

282/345

Vous pouvez alors constater que notre solution fonctionne, l'utilisateur est maintenant bien redirig vers la page de connexion.
Oui, mais...
O est pass le design de notre page ?!

Eh bien la rponse est simple : il a t bloqu ! En ralit lorsque vous accdez une page web sur laquelle est attache une
feuille de style CSS, votre navigateur va dans les coulisses envoyer une deuxime requte au serveur pour rcuprer
silencieusement cette feuille et ensuite appliquer les styles au contenu HTML. Et vous pouvez le deviner, cette seconde requte
a bien videmment t bloque par notre super-filtre !
Comment rgler ce problme ?

Il y a plusieurs solutions envisageables. Voici les deux plus courantes :


ne plus appliquer le filtre la racine de l'application, mais seulement sur des rpertoires ou pages en particulier, en
prenant soin d'viter de restreindre l'accs notre page CSS ;
continuer appliquer le filtre sur toute l'application, mais dplacer notre feuille de style dans un rpertoire, et ajouter un
passe-droit au sein de la mthode doFilter() du filtre.
Je vais vous expliquer cette seconde mthode. Une bonne pratique d'organisation consiste en effet placer sous un rpertoire
commun toutes les ressources destines tre incluses, afin de permettre un traitement simplifi. Par "ressources incluses", on
entend gnralement les feuilles de style CSS, les feuilles Javascript ou encore les images, bref tout ce qui est susceptible d'tre
inclus dans une page HTML ou une page JSP.
Pour commencer, crez donc un rpertoire nomm inc sous la racine de votre application et placez-y notre fichier CSS :

Inc.

Puisque nous venons de dplacer le fichier, nous devons galement modifier son appel dans la page de connexion :
Code : JSP - /WEB-INF/connexion.jsp
<!-- Dans le fichier connexion.jsp, remplacez l'appel suivant : -->
<link type="text/css" rel="stylesheet" href="form.css" />
<!-- Par celui-ci : -->
<link type="text/css" rel="stylesheet" href="inc/form.css" />

www.siteduzero.com

Partie 4 : Une application interactive !

283/345

Pour terminer, nous devons raliser dans la mthode doFilter() de notre filtre ce fameux passe-droit sur le dossier inc :
Code : Java - com.sdzee.filters.RestrictionFilter
package com.sdzee.filters;
import java.io.IOException;
import
import
import
import
import
import
import
import
import

javax.servlet.Filter;
javax.servlet.FilterChain;
javax.servlet.FilterConfig;
javax.servlet.ServletException;
javax.servlet.ServletRequest;
javax.servlet.ServletResponse;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

public class RestrictionFilter implements Filter {


public static final String ACCES_CONNEXION = "/connexion";
public static final String ATT_SESSION_USER =
"sessionUtilisateur";
{

public void init( FilterConfig config ) throws ServletException


}

public void doFilter( ServletRequest req, ServletResponse res,


FilterChain chain ) throws IOException,
ServletException {
/* Cast des objets request et response */
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
/* Non-filtrage des ressources statiques */
String chemin = request.getRequestURI().substring(
request.getContextPath().length() );
if ( chemin.startsWith( "/inc" ) ) {
chain.doFilter( request, response );
return;
}
/* Rcupration de la session depuis la requte */
HttpSession session = request.getSession();
/**
* Si l'objet utilisateur n'existe pas dans la session en cours,
alors
* l'utilisateur n'est pas connect.
*/
if ( session.getAttribute( ATT_SESSION_USER ) == null ) {
/* Redirection vers la page publique */
request.getRequestDispatcher( ACCES_CONNEXION ).forward(
request, response );
} else {
/* Affichage de la page restreinte */
chain.doFilter( request, response );
}
}

public void destroy() {


}

Explications :

www.siteduzero.com

Partie 4 : Une application interactive !

284/345

la ligne 29, nous rcuprons l'URL d'appel de la requte HTTP via la mthode getRequestURI(), puis nous plaons
dans la chane chemin sa partie finale, c'est--dire la partie situe aprs le contexte de l'application. Typiquement, dans
notre cas si nous nous rendons sur http://localhost:8080/pro/restreint/accesRestreint.jsp, la mthode
getRequestURI() va renvoyer /pro/restreint/accesRestreint.jsp et chemin va contenir uniquement
/restreint/accesRestreint.jsp.
la ligne 30, nous testons si cette chane chemin commence par /inc : si c'est le cas, cela signifie que la page demande
est une des ressources statiques que nous avons places sous le rpertoire inc, et qu'il ne faut donc pas lui appliquer le
filtre !
la ligne 31, nous laissons donc la requte poursuivre son cheminement en appelant la mthode doFilter() de la
chane.

Faites les modifications, enregistrez et tentez d'accder la page http://localhost:8080/pro/connexion :

CSS OK.
Le rsultat est parfait, cela fonctionne ! Oui, mais...
Quoi encore ? Il n'y a plus de problme, toute l'application fonctionne maintenant !

Toute ? Non ! Un irrductible souci rsiste encore et toujours... Par exemple, rendez-vous maintenant sur la page
http://localhost:8080/pro/restreint/accesRestreint.jsp :

Ratage du CSS.
Pourquoi la feuille de style n'est-elle pas applique notre formulaire de connexion dans ce cas ?

Eh bien cette fois, c'est cause du forwarding que nous avons mis en place dans notre filtre ! Eh oui, souvenez-vous : le
forwarding ne modifie pas l'URL ct client, comme vous pouvez d'ailleurs le voir sur cette dernire illustration. Cela veut dire
que le navigateur du client reoit bien le formulaire de connexion, mais ne sait pas que c'est la page /connexion.jsp qui le lui a
renvoy, il croit qu'il s'agit tout bonnement du retour de la page demande, c'est--dire /restreint/accesRestreint.jsp.
De ce fait, lorsqu'il va silencieusement envoyer une requte au serveur pour rcuprer la feuille CSS associe la page de
conenxion, le navigateur va navement se baser sur l'URL qu'il a en mmoire pour interprter l'appel suivant :

www.siteduzero.com

Partie 4 : Une application interactive !

285/345

Code : JSP - Extrait de connexion.jsp


<link type="text/css" rel="stylesheet" href="inc/form.css" />

En consquence, il va considrer que l'URL relative "inc/form.css" se rapporte au rpertoire qu'il pense tre le rpertoire courant,
savoir /restreint (puisque pour lui, le formulaire a t affich par /restreint/accesRestreint.jsp). Ainsi, le navigateur va
demander au serveur de lui renvoyer la page /restreint/inc/forms.css, alors que cette page n'existe pas ! Voil pourquoi le design
de notre formulaire semble avoir disparu.
Pour rgler ce problme, nous n'allons ni toucher au filtre ni au forwarding , mais nous allons tirer parti de la JSTL pour modifier
la page connexion.jsp :
Code : JSP - /WEB-INF/connexion.jsp
<!-- Dans le fichier connexion.jsp, remplacez l'appel suivant : -->
<link type="text/css" rel="stylesheet" href="inc/form.css" />
<!-- Par celui-ci : -->
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/form.css"/>" />

Vous vous rappelez de ce que je vous avais expliqu propos de la balise <c:url/> ? Je vous avais dit qu'elle ajoutait
automatiquement aux URL absolues qu'elle contenait le contexte de l'application. C'est exactement ce que nous souhaitons : dans
ce cas, le rendu de la balise sera /pro/inc/form.css. Le navigateur reconnatra donc ici une URL absolue et non plus une URL
relative comme c'tait le cas auparavant, et il ralisera correctement l'appel au fichier CSS !
Dans ce cas, pourquoi ne pas avoir directement crit l'URL absolue "/pro/inc/form.css" dans l'appel ? Pourquoi
s'embter avec <c:url/> ?
Pour la mme raison que nous avions utilis request.getContextPath() dans la servlet que nous avions dveloppe en
premire partie de ce chapitre : si demain nous dcidons de changer le nom du contexte, notre page fonctionnera toujours avec la
balise <c:url/>, alors qu'il faudra diter et modifier l'URL absolue entre la main sinon. J'espre que cette fois, vous avez
bien compris !
Une fois la modification effectue, voici le rsultat :

CSS OK.
Finalement, nous y sommes : tout fonctionne comme prvu !

Dsactiver le filtre
Une fois vos dveloppements et tests termins, pour plus de commodit dans les exemples suivre vous pouvez dsactiver ce
filtre, en commentant simplement sa dclaration dans le fichier web.xml de votre application :

www.siteduzero.com

Partie 4 : Une application interactive !

286/345

Code : XML - /WEB-INF/web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app>
...
<!-<filter>
<filter-name>RestrictionFilter</filter-name>
<filter-class>com.sdzee.filters.RestrictionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RestrictionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->
...
</web-app>

Il faudra redmarrer Tomcat pour que la modification soit prise en compte.


Dans cet imposant chapitre, qu'il s'agisse de rappels ou de nouveaux concepts, je vous ai communiqu normment
d'informations utiles. Prenez bien le temps d'effectuer chacune des modifications au travers desquelles je vous guide, d'analyser
calmement les diffrentes erreurs rencontres et d'assimiler et retenir les conseils de conception que je vous enseigne.
Une fois que vous avez bien digr, filez au chapitre suivant et attaquez le dessert : des cookies vous attendent ! Miam !

www.siteduzero.com

Partie 4 : Une application interactive !

287/345

Le cookie : le navigateur vous ouvre ses portes


Nous avons dj bien entam la dcouverte du cookie malgr nous, lorsque nous avons tudi le fonctionnement des sessions,
mais nous allons tout de mme prendre la peine de rappeler les concepts qui se cachent sous cette technologie. Nous allons
ensuite mettre en pratique la thorie dans un exemple concret, et terminer sur une discussion autour de leur scurit.

Le principe du cookie
Le principe gnral est simple : il s'agit un petit fichier plac directement dans le navigateur du client. Il lui est envoy par le
serveur travers les en-ttes de la rponse HTTP, et ne contient que du texte. Il est propre un site ou une partie d'un site en
particulier, et sera renvoy par le navigateur dans toutes les requtes HTTP adresses ce site ou cette partie du site.

Ct HTTP
Pour commencer, le cookie est une notion qui est lie au protocole HTTP, et qui est dfinie par la RFC 6265
depuis avril 2011.
Cette nouvelle version de la norme rend caduque la version 2965, qui elle-mme remplaait la version 2109. Si vous avez du temps
perdre, vous pouvez chercher les modifications apportes au fil des volutions, c'est un excellent exercice d'entrainement
d'analyse de RFC, ces documents massifs qui font office de rfrence absolue dans bon nombre de domaines !
a, c'tait pour la thorie. Dans la pratique, dans le chapitre portant sur les sessions nous avons dj analys des changes
HTTP impliquant des transferts de cookies de serveur vers navigateur et inversement, et avons dcouvert que :
un cookie a obligatoirement un nom et une valeur associe ;
un cookie peut se voir attribuer certaines options, comme une date d'expiration ;
le serveur demande la mise en place ou le remplacement d'un cookie par le paramtre Set-Cookie dans l'en-tte de la
rponse HTTP qu'il envoie au client ;
le client transmet au serveur un cookie par le paramtre Cookie dans l'en-tte de la requte HTTP qu'il envoie au serveur.
C'est tout ce qu'il se passe dans les coulisses du protocole HTTP, il s'agit uniquement d'un paramtre dans la requte ou dans la
rponse.

Ct Java EE
La plate-forme Java EE permet de manipuler un cookie travers l'objet Java Cookie. Sa documentation claire et concise nous
informe notamment que :
un cookie doit obligatoirement avoir un nom et une valeur ;
il est possible d'attribuer des options un cookie, telles qu'une date d'expiration ou un numro de version. Toutefois, elle
nous prcise ici que certains navigateurs prsentent des bugs dans leur gestion de ces options, et qu'il est prfrable
d'en limiter l'usage autant que faire se peut afin de rendre notre application aussi multiplateforme que possible ;
la mthode addCookie() de l'objet HttpServletResponse est utilise pour ajouter un cookie la rponse qui
sera envoye client ;
la mthode getCookies() de l'objet HttpServletRequest est utilise pour rcuprer la liste des cookies
envoys par le client ;
par dfaut, les objets ainsi crs respectent la toute premire norme dcrivant les cookies HTTP, une norme encore plus
ancienne que la 2109 dont je vous ai parl dans le paragraphe prcdent, afin d'assurer la meilleure interoprabilit
possible. La documentation de la mthode setVersion() nous prcise mme que la version 2109 est considre
comme "rcente et exprimentale". Bref, la documentation commence srieusement dater... Peu importe, tout ce dont
nous avons besoin pour le moment tait dj dcrit dans le tout premier document, pas de soucis se faire !
Voil tout ce qu'il vous est ncessaire de savoir pour attaquer. Bien videmment, n'hsitez pas parcourir plus en profondeur la
Javadoc de l'objet Cookie pour en connatre davantage !
Avant de passer la pratique, comprenez bien que cookies et sessions sont deux concepts totalement distincts ! Mme
s'il est vrai que l'tablissement d'une session en Java EE peut s'appuyer sur un cookie, il ne faut pas confondre les deux
notions : la session est un espace mmoire allou sur le serveur dans lequel vous pouvez placer n'importe quel type
d'objets, alors que le cookie est un espace mmoire allou dans le navigateur du client dans lequel vous ne pouvez
placer que du texte.

Souvenez-vous de vos clients !


Pour illustrer la mise en place d'un cookie chez l'utilisateur, nous allons donner notre formulaire de connexion... une mmoire !
Plus prcisment, nous allons donner le choix l'utilisateur d'enregistrer ou non la date de sa dernire connexion, via une case

www.siteduzero.com

Partie 4 : Une application interactive !

288/345

cocher dans notre formulaire. S'il fait ce choix, alors nous allons stocker la date et l'heure de sa connexion dans un cookie et le
placer dans son navigateur. Ainsi, son retour aprs dconnexion, nous serons en mesure de lui afficher depuis combien de
temps il ne s'est pas connect.
Ce systme ne fera donc intervenir qu'un seul cookie, charg de sauvegarder la date de connexion.
Alors bien videmment, c'est une simple fonctionnalit que je vous fais mettre en place titre d'application pratique uniquement :
elle est aisment faillible, par exemple si l'utilisateur supprime les cookies de son navigateur, les bloque, ou encore s'il se
connecte depuis un autre poste ou un autre navigateur. Mais peu importe, le principal est que vous travailliez la manipulation de
cookies, et au passage cela vous donnera une occasion :
de travailler nouveau la manipulation des dates avec la bibliothque JodaTime ;
de dcouvrir comment traiter une case cocher, c'est--dire un champ de formulaire HTML de type <input
type="checkbox"/>.
D'une pierre... trois coups !

Reprise de la servlet
Le plus gros de notre travail va se concentrer sur la servlet de connexion. C'est ici que nous allons devoir manipuler notre unique
cookie, et effectuer diffrentes vrifications. En reprenant calmement notre systme, nous pouvons identifier les deux besoins
suivants :
1. l'affichage du formulaire de connexion par un visiteur, il nous faut vrifier si le cookie enregistrant la date de la
prcdente connexion a t envoy dans la requte HTTP par le navigateur du client. Si oui, alors cela signifie que le
visiteur s'est dj connect par le pass avec ce navigateur, et que nous pouvons donc lui afficher depuis combien de
temps il ne s'est pas connect. Si non, alors il ne s'est jamais connect et nous lui affichons simplement le formulaire ;
2. la connexion d'un visiteur, il nous faut vrifier s'il a coch la case dans le formulaire, et si oui il nous faut rcuprer la
date courante, l'enregistrer dans un cookie et l'envoyer au navigateur du client travers la rponse HTTP.

l'affichage du formulaire
Lors de la rception d'une demande d'accs la page de connexion, la mthode doGet() de notre servlet va devoir :
vrifier si un cookie a t envoy par le navigateur dans les en-ttes de la requte ;
si oui, alors elle doit calculer la diffrence entre la date courante et la date prsente dans le cookie, et la transmettre la
JSP pour affichage.
Code : Java - com.sdzee.servlets.Connexion
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.Cookie;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import
import
import
import
import
import

org.joda.time.DateTime;
org.joda.time.Period;
org.joda.time.format.DateTimeFormat;
org.joda.time.format.DateTimeFormatter;
org.joda.time.format.PeriodFormatter;
org.joda.time.format.PeriodFormatterBuilder;

import com.sdzee.beans.Utilisateur;
import com.sdzee.forms.ConnexionForm;

www.siteduzero.com

Partie 4 : Une application interactive !

289/345

public class Connexion extends HttpServlet {


public static final String ATT_USER
"utilisateur";
public static final String ATT_FORM
public static final String ATT_INTERVALLE_CONNEXIONS =
"intervalleConnexions";
public static final String ATT_SESSION_USER
"sessionUtilisateur";

=
= "form";
=

public static final String COOKIE_DERNIERE_CONNEXION =


"derniereConnexion";
public static final String FORMAT_DATE = "dd/MM/yyyy HH:mm:ss";
public static final String
INF/connexion.jsp";

VUE

= "/WEB-

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException, IOException
{
/* Tentative de rcupration du cookie depuis la requte */
String derniereConnexion = getCookieValue( request,
COOKIE_DERNIERE_CONNEXION );
/* Si le cookie existe, alors calcul de la dure */
if ( derniereConnexion != null ) {
/* Rcupration de la date courante */
DateTime dtCourante = new DateTime();
/* Rcupration de la date prsente dans le cookie */
DateTimeFormatter formatter = DateTimeFormat.forPattern( FORMAT_DATE
);
DateTime dtDerniereConnexion = formatter.parseDateTime(
derniereConnexion );
/* Calcul de la dure de l'intervalle */
Period periode = new Period( dtDerniereConnexion, dtCourante );
/* Formatage de la dure de l'intervalle */
PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
.appendYears().appendSuffix( " an ", " ans " )
.appendMonths().appendSuffix( " mois " )
.appendDays().appendSuffix( " jour ", " jours " )
.appendHours().appendSuffix( " heure ", " heures " )
.appendMinutes().appendSuffix( " minute ", " minutes " )
.appendSeparator( "et " )
.appendSeconds().appendSuffix( " seconde", " secondes" )
.toFormatter();
String intervalleConnexions = periodFormatter.print( periode );
/* Ajout de l'intervalle en tant qu'attribut de la requte */
request.setAttribute( ATT_INTERVALLE_CONNEXIONS,
intervalleConnexions );
}
/* Affichage de la page de connexion */
this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
public void doPost( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
...
}
/**
* Mthode utilitaire grant la rcupration de la valeur d'un
cookie donn
* depuis la requte HTTP.
*/
private static String getCookieValue( HttpServletRequest request,
String nom ) {
Cookie[] cookies = request.getCookies();

www.siteduzero.com

Partie 4 : Une application interactive !

290/345

if ( cookies != null ) {
for ( Cookie cookie : cookies ) {
if ( cookie != null && nom.equals( cookie.getName() ) ) {
return cookie.getValue();
}
}
}
return null;
}
}

De plus amples explications :


j'ai choisi de nommer le cookie stock chez le client derniereConnexion ;
j'ai mis en place une mthode nomme getCookieValue(), ddie la recherche d'un cookie donn dans une
requte HTTP :
la ligne 74, elle rcupre tous les cookies prsents dans la requte grce la mthode
request.getCookies(), que je vous ai prsente un peu plus tt ;
la ligne 75, elle vrifie si des cookies existent, c'est--dire si request.getCookies() n'a pas retourn
null ;
la ligne 76, elle parcourt le tableau de cookies rcupr ;
la ligne 77, elle vrifie si un des ventuels cookies prsents dans le tableau a pour nom, rcupr par un appel
cookie.getName(), le paramtre nom pass en argument ;
la ligne 78, si un tel cookie est trouv, elle retourne sa valeur via un appel cookie.getValue().
la ligne 38, je teste si ma mthode getCookieValue() a retourn une valeur ou non ;
de la ligne 39 la ligne 58, je traite les dates grce aux mthodes de la bibliothque JodaTime. Je vous recommande
fortement d'aller vous-mme parcourir son guide d'utilisation ainsi que sa FAQ. C'est en anglais, mais les codes
d'exemples sont trs explicites. Voici quelques dtails en supplment des commentaires dj prsents dans le code de la
servlet :
j'ai pris pour convention le format "dd/MM/yyyy HH:mm:ss", et considre donc que la date sera stocke
sous ce format dans le cookie derniereConnexion plac dans le navigateur le client ;
les lignes 42 et 43 permettent de traduire la date prsente au format texte dans le cookie du client, en un objet
DateTime que nous utiliserons par la suite pour effectuer la diffrence avec la date courante ;
la ligne 45, je calcule la diffrence entre la date courante et la date de la dernire visite, c'est--dire l'intervalle de
temps coul ;
de la ligne 47 55, je cre un format d'affichage de mon choix l'aide de l'objet PeriodFormatterBuilder ;
la ligne 56 j'enregistre dans un String, via la mthode print(), l'intervalle mis en forme avec le format que
j'ai frachement dfini ;
enfin la ligne 58, je transmet l'intervalle mis en forme notre JSP, via un simple attribut de requte nomm
intervalleConnexions.
En fin de compte, si vous mettez de ct la tambouille que nous ralisons pour manipuler nos dates et calculer l'intervalle entre
deux connexions, vous vous rendrez compte que le traitement li au cookie en lui-mme est assez court : il suffit simplement de
vrifier le retour de la mthode request.getCookies(), chose que nous faisons ici grce notre mthode
getCookieValue().

la connexion du visiteur
La seconde tape, c'est maintenant de grer la connexion d'un visiteur. Il va falloir :
vrifier si la case est coche ou non ;
si oui, alors l'utilisateur souhaite qu'on se souvienne de lui et il nous faut :
rcuprer la date courante ;
la convertir au format texte choisi ;
l'enregistrer dans un cookie nomm derniereConnexion et l'envoyer au navigateur du client travers la rponse
HTTP.
si non, alors l'utilisateur ne souhaite pas qu'on se souvienne de lui et il nous faut :
demander la suppression du cookie nomm derniereConnexion qui existe ventuellement dj dans le navigateur
du client.

www.siteduzero.com

Partie 4 : Une application interactive !

291/345

Code : Java - com.sdzee.servlets.Connexion


package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.Cookie;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import
import
import
import
import
import

org.joda.time.DateTime;
org.joda.time.Period;
org.joda.time.format.DateTimeFormat;
org.joda.time.format.DateTimeFormatter;
org.joda.time.format.PeriodFormatter;
org.joda.time.format.PeriodFormatterBuilder;

import com.sdzee.beans.Utilisateur;
import com.sdzee.forms.ConnexionForm;
public class Connexion extends HttpServlet {
public static final String CHAMP_MEMOIRE = "memoire";
public static final
"utilisateur";
public static final
public static final
"intervalleConnexions";
public static final
"sessionUtilisateur";

String

ATT_USER

String
String

ATT_FORM
= "form";
ATT_INTERVALLE_CONNEXIONS =

String

ATT_SESSION_USER

public static final String COOKIE_DERNIERE_CONNEXION =


"derniereConnexion";
public static final int COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 1an
public static final String
"dd/MM/yyyy HH:mm:ss";

FORMAT_DATE

public static final String


INF/connexion.jsp";

VUE

= "/WEB-

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException, IOException
{
...
}
public void doPost( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/* Prparation de l'objet formulaire */
ConnexionForm form = new ConnexionForm();
/* Traitement de la requte et rcupration du bean en
rsultant */
Utilisateur utilisateur = form.connecterUtilisateur( request
);
/* Rcupration de la session depuis la requte */
HttpSession session = request.getSession();
/*
* Si aucune erreur de validation n'a eu lieu, alors ajout du bean
* Utilisateur la session, sinon suppression du bean de la
session.

www.siteduzero.com

Partie 4 : Une application interactive !


*/

292/345

if ( form.getErreurs.isEmpty() ) {
session.setAttribute( ATT_SESSION_USER, utilisateur );
} else {
session.setAttribute( ATT_SESSION_USER, null );
}

/* Si et seulement si la case du formulaire est coche */


if ( request.getParameter( CHAMP_MEMOIRE ) != null ) {
/* Rcupration de la date courante */
DateTime dt = new DateTime();
/* Formatage de la date et conversion en texte */
DateTimeFormatter formatter = DateTimeFormat.forPattern( FORMAT_DATE
);
String dateDerniereConnexion = dt.toString( formatter );
/* Cration du cookie, et ajout la rponse HTTP */
setCookie( response, COOKIE_DERNIERE_CONNEXION,
dateDerniereConnexion, COOKIE_MAX_AGE );
} else {
/* Demande de suppression du cookie du navigateur */
setCookie( response, COOKIE_DERNIERE_CONNEXION, "", 0 );
}
/* Stockage du formulaire et du bean dans l'objet request

*/

request.setAttribute( ATT_FORM, form );


request.setAttribute( ATT_USER, utilisateur );

this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
...
/**
* Mthode utilitaire grant la cration d'un cookie et son ajout
la
* rponse HTTP.
*/
private static void setCookie( HttpServletResponse response, String
nom, String valeur, int maxAge ) {
Cookie cookie = new Cookie( nom, valeur );
cookie.setMaxAge( maxAge );
response.addCookie( cookie );
}
}

Quelques explications supplmentaires :


la condition du bloc if la ligne 62 permet de dterminer si la case du formulaire, que j'ai choisi de nommer memoire, est
coche ;
les lignes 66 et 67 se basent sur la convention d'affichage choisie, savoir "dd/MM/yyyy HH:mm:ss", pour mettre
en forme la date proprement partir de l'objet DateTime frachement cr ;
j'utilise alors une mthode setCookie(), laquelle je transmets la rponse accompagne de trois paramtres :
un nom et une valeur, qui sont alors utiliss pour crer un nouvel objet Cookie la ligne 86 ;
un entier maxAge, utilis pour dfinir la dure de vie du cookie grce la mthode cookie.setMaxAge() ;
cette mthode se base pour finir sur un appel response.addCookie() dont je vous ai dj parl, pour
mettre en place une instruction Set-Cookie dans les en-ttes de la rponse HTTP.
la ligne 72, je demande au navigateur du client de supprimer l'ventuel cookie nomm derniereConnexion qu'il aurait
dj enregistr par le pass. En effet, si l'utilisateur n'a pas coch la case du formulaire, cela signifie qu'il ne souhaite pas
que nous lui affichions un message, et il nous faut donc nous assurer qu'aucun cookie enregistr lors d'une connexion
prcdente n'existe. Pour ce faire, il suffit de placer un nouveau cookie derniereConnexion dans la rponse HTTP avec
une dure de vie gale zro.

www.siteduzero.com

Partie 4 : Une application interactive !

293/345

Au passage, si vous vous rendez sur la documentation de la mthode setMaxAge(), vous dcouvrirez les trois types de
valeurs qu'elle accepte :
un entier positif, reprsentant le nombre de secondes avant expiration du cookie sauvegard. En l'occurrence, j'ai donn
notre cookie une dure de vie d'un an, soit 60*60*24*365 = 31536000 secondes ;
un entier ngatif, signifiant que le cookie ne sera stock que de manire temporaire et sera supprim ds que le navigateur
sera ferm. Si vous avez bien suivi et compris le chapitre sur les sessions, alors vous en avez probablement dj dduit
que c'est de cette manire qu'est stock le cookie JSESSIONID ;
zro, qui permet de supprimer simplement le cookie du navigateur.

retenir galement, le seul test valable pour s'assurer qu'un champ de type <input type="checkbox"/> est
coch, c'est de vrifier le retour de la mthode request.getParameter() : si null, alors la case n'est pas
coche ; sinon, alors la case est coche.

Reprise de la JSP
Pour achever notre systme, il nous reste ajouter la case cocher notre formulaire, ainsi qu'un message sur notre page de
connexion prcisant depuis combien de temps l'utilisateur ne s'est pas connect. Deux contraintes sont prendre en compte :
si l'utilisateur est dj connect, on ne lui affiche pas le message ;
si l'utilisateur ne s'est jamais connect, ou s'il n'a pas coch la case lors de sa dernire connexion, on ne lui affiche pas le
message.
Code : JSP - /WEB-INF/connexion.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Connexion</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/form.css"/>" />
</head>
<body>
<form method="post" action="<c:url value="/connexion" />">
<fieldset>
<legend>Connexion</legend>
<p>Vous pouvez vous connecter via ce formulaire.</p>
<c:if test="${empty sessionScope.sessionUtilisateur && !empty
requestScope.intervalleConnexions}">
<p class="info">(Vous ne vous tes pas connect(e) depuis ce
navigateur depuis ${requestScope.intervalleConnexions})</p>
</c:if>
<label for="nom">Adresse email <span
class="requis">*</span></label>
<input type="email" id="email" name="email"
value="<c:out value="${utilisateur.email}"/>" size="20"
maxlength="60" />
<span class="erreur">${form.erreurs['email']}</span>
<br />
<label for="motdepasse">Mot de passe <span
class="requis">*</span></label>
<input type="password" id="motdepasse"
name="motdepasse" value="" size="20" maxlength="20" />
<span
class="erreur">${form.erreurs['motdepasse']}</span>
<br />
<br />

www.siteduzero.com

Partie 4 : Une application interactive !

294/345

<label for="memoire">Se souvenir de moi</label>


<input type="checkbox" id="memoire" name="memoire" />
<br />
<input type="submit" value="Connexion"
class="sansLabel" />
<br />
<p class="${empty form.erreurs ? 'succes' :
'erreur'}">${form.resultat}</p>
<%-- Vrification de la prsence d'un objet
utilisateur en session --%>
<c:if test="${!empty
sessionScope.sessionUtilisateur}">
<%-- Si l'utilisateur existe en session, alors
on affiche son adresse email. --%>
<p class="succes">Vous tes connect(e) avec
l'adresse : ${sessionScope.sessionUtilisateur.email}</p>
</c:if>
</fieldset>
</form>
</body>
</html>

la ligne 14, vous remarquerez l'utilisation d'un test conditionnel par le biais de la balise <c:if/> de la JSTL Core :
la premire moiti du test permet de vrifier que la session ne contient pas d'objet nomm sessionUtilisateur, autrement
dit de vrifier que l'utilisateur n'est actuellement pas connect. Souvenez-vous : sessionUtilisateur est l'objet que nous
plaons en session lors de la connexion d'un visiteur, et qui n'existe donc que si une connexion a dj eu lieu ;
la seconde moiti du test permet de vrifier que la requte contient bien un intervalle de connexions, autrement dit de
vrifier si l'utilisateur s'tait dj connect ou non, et si oui s'il avait coch la case ou non. Rappelez-vous de nos
mthodes doGet() et doPost() : si le client n'a pas envoy le cookie derniereConnexion, alors cela signifie qu'il ne
s'est jamais connect par le pass, ou bien que lors de sa dernire connexion il n'a pas coch la case, et nous ne
transmettons pas d'intervalle la JSP.
Le corps de la balise <c:if/>, contenant notre message ainsi que l'intervalle transmis pour affichage travers l'attribut de
requte intervalleConnexions, est alors uniquement affich si la fois l'utilisateur n'est pas connect l'instant prsent, et qu'il a
coch la case lors de sa prcdente connexion.
Enfin, vous voyez que pour l'occasion j'ai ajout un style info notre feuille CSS, afin de mettre en forme le nouveau message :
Code : CSS - /inc/form.css
form .info {
font-style: italic;
color: #E8A22B;
}

Vrifications
Le scnario de tests va tre plutt lger. Pour commencer, redmarrez Tomcat, nettoyez les donnes de votre navigateur via Ctrl +
Maj + Suppr, et accdez la page de connexion. Vous devez alors visualiser le formulaire vierge :

www.siteduzero.com

Partie 4 : Une application interactive !

295/345

Appuyez sur F12 pour ouvrir l'outil d'analyse de votre navigateur, entrez des donnes valides dans le formulaire et connectezvous en cochant la case "Se souvenir de moi". Examinez alors la rponse renvoye par le serveur :

Vous pouvez constater la prsence de l'instruction Set-Cookie dans l'en-tte de la rponse HTTP, demandant la cration d'un
cookie nomm derniereConnexion qui :
contient bien la date de connexion, formate selon la convention choisie dans notre servlet ;
expire bien dans 31536000 secondes, soit un an aprs cration.

www.siteduzero.com

Partie 4 : Une application interactive !

296/345

Ouvrez alors un nouvel onglet et rendez-vous nouveau sur la page de connexion. Vous constaterez que le message contenant
l'intervalle ne vous est toujours pas affich, puisque vous tes connects et que l'expression EL dans notre JSP l'a dtect :

Dconnectez-vous alors en vous rendant sur http://localhost:8080/pro/deconnexion, puis rendez-vous nouveau sur la page de
connexion et observez :

Vous pouvez constater la prsence, dans l'en-tte Cookie de la requte envoye par le navigateur, du cookie nomm

www.siteduzero.com

Partie 4 : Une application interactive !

297/345

derniereConnexion, sauvegard lors de la prcdente connexion. Et bien videmment cette fois, le message vous est affich au
sein du formulaire de connexion, et vous prcise depuis combien de temps vous ne vous tes pas connects.
Connectez-vous nouveau, mais cette fois sans cocher la case "Se souvenir de moi". Observez alors l'change HTTP qui a lieu
:

Vous pouvez constater deux choses :


puisque vous vous tiez connects en cochant la case du formulaire auparavant, votre navigateur avait enregistr la date
de connexion dans un cookie, et ce cookie existe encore. Cela explique pourquoi le navigateur envoie un cookie
derniereConnexion contenant la date de votre premire connexion dans l'en-tte Cookie de la requte ;
puisque cette fois vous n'avez pas coch la case du formulaire, la servlet renvoie une demande de suppression du cookie
travers la rponse HTTP. Cela explique la prsence de l'instruction Set-Cookie contenant un cookie vide et dont la date
d'expiration est le... 1er janvier 1970 !

www.siteduzero.com

Partie 4 : Une application interactive !

298/345

Pourquoi le cookie contient-il une date d'expiration ?

Tout simplement parce qu'il n'existe pas de proprit ni de champ optionnel dans l'instruction Set-Cookie permettant de
supprimer un cookie. Ainsi, la seule solution qui s'offre nous est de prciser une date d'expiration antrieure la date courante,
afin que le navigateur en dduise que le cookie est expir et qu'il doit le supprimer. Ceci est fait automatiquement lorsque nous
donnons notre cookie un maxAge gal zro.
Pourquoi le 1er janvier 1970 ?

Il s'agit de la date considre comme le temps d'origine par votre systme. Ainsi en ralit, lorsque nous donnons notre cookie
un maxAge gal zro, cela se traduit dans l'en-tte HTTP par cette date butoir : de cette manire, le serveur est certain que le
cookie sera supprim par le navigateur, peu importe la date courante sur la machine cliente.

propos de la scurit
Vous devez bien comprendre que contrairement aux sessions, bien gardes sur le serveur, le systme des cookies est loin d'tre
un coffre-fort. Principalement parce que l'information que vous y stockez est place chez le client, et que par consquent vous
n'avez absolument aucun contrle dessus. Par exemple, rien n'indique que ce que vous y placez ne soit pas lu et dtourn par
une personne malveillante qui aurait accs la machine du client son insu.
L'exemple le plus flagrant est le stockage du nom d'utilisateur et du mot de passe directement dans un cookie. En plaant en clair
ces informations dans le navigateur du client, vous les exposez au vol par un tiers malveillant, qui pourra alors voler le compte de
votre client...
Ainsi, il y a une rgle suivre lorsque vous utilisez des cookies : n'y stockez jamais d'informations sensibles en clair.

Rassurez-vous toutefois, le systme est loin d'tre une vraie passoire. Simplement, lorsque vous dvelopperez des applications
ncessitant un bon niveau de scurit, ce sont des considrations que vous devrez tt ou tard prendre en compte. Autant vous
en faire prendre conscience ds maintenant !
La base de connaissance associe aux cookies est plutt mince, comme vous pouvez le constater travers ce lger chapitre. En
revanche, le panel d'usages qui gravite autour d'eux est immense : nous pouvons par exemple citer la gestion des paniers de
commandes sur les sites d'achats en ligne, les systmes de connexion ou d'authentification automatiques, ou encore le choix de
la langue par dfaut dans le cas d'un site multilingue, autant de fonctionnalits qui sont trs souvent bases sur les cookies !
Dans la partie suivante de ce cours, lorsque nous aurons dcouvert et assimil la gestion des bases de donnes, nous
reviendrons sur les cookies et amliorerons notre systme de connexion et d'espace membre.

www.siteduzero.com

Partie 4 : Une application interactive !

299/345

TP Fil rouge - tape 4


Les sessions constituant dj un gros morceau elles seules, dans cette tape du fil rouge vous n'allez manipuler ni filtres ni
cookies. Et croyez-moi, mme sans a vous avez du pain sur la planche !

Objectifs
Fonctionnalits
Vous allez devoir effectuer une modification importante, qui va impacter presque tout votre code existant : je vous demande dans
cette tape d'enregistrer en session les clients et commandes crs par un utilisateur. Cela pourrait trs bien tre un jeu d'enfants,
si je ne vous demandais rien d'autre derrire... Mais ne rvez-pas, vous n'tes pas ici pour vous tourner les pouces !

Enregistrement en session
Pour commencer, comme je viens de vous l'annoncer, vous allez devoir enregistrer en session les clients et commandes crs par
un utilisateur. Ainsi, les informations saisies par l'utilisateur ne seront plus perdues aprs validation d'un formulaire de cration !

Liste rcapitulative des clients et commandes crs


Deuximement, vous allez devoir crer deux nouvelles pages :
listerClients.jsp, qui listera les clients crs par l'utilisateur ;
listerCommandes.jsp, qui listera les commandes cres par l'utilisateur.
Vous en profiterez pour mettre jour la page menu.jsp en y ajoutant deux liens vers ces deux nouvelles pages frachement cres.

Un formulaire de cration de commande intelligent


Troisimement, et cette fois il va vous falloir rflchir davantage, je vous demande de modifier le formulaire de cration de
commandes. Maintenant que votre application est capable d'enregistrer les clients crs par l'utilisateur, vous allez lui donner un
choix lorsqu'il cre une commande :
si la commande qu'il veut crer concerne un nouveau client, alors affichez-lui les champs permettant la saisie des
informations du nouveau client, comme vous le faisiez dj auparavant ;
si la commande qu'il veut crer concerne un client dj existant, alors affichez-lui une liste droulante des clients
existants, lui permettant de choisir son client et lui vitant ainsi de saisir nouveau ses informations.

Systme de suppression des clients et commandes


Quatrimement, vous allez devoir mettre en place un systme permettant la suppression d'un client ou d'une commande
enregistre dans la session. Vous allez ensuite devoir complter vos pages listerClients.jsp et listerCommandes.jsp pour
qu'elles affichent ct de chaque client et commande un lien vers ce systme, permettant la suppression de l'entit
correspondante.
Enfin, vous devrez vous prparer une tasse un Thermos de caf ou de th bien fort, parce qu'avec tout ce travail, vous n'tes pas
couchs !

Exemples de rendus
Liste des clients cres au cours de la session, ici avec quatre clients :

www.siteduzero.com

Partie 4 : Une application interactive !

300/345

Liste des commandes lorsqu'aucune commande n'a t cre au cours de la session :

Formulaire de cration d'une commande lorsque la case "Nouveau client : Oui" est coche :

www.siteduzero.com

Partie 4 : Une application interactive !

301/345

Formulaire de cration d'une commande lorsque la case "Nouveau client : Non" est coche :

www.siteduzero.com

Partie 4 : Une application interactive !

302/345

Liste des commandes lorsque deux commandes ont t cres au cours de la session :

Conseils
Enregistrement en session
Concernant l'aspect technique de cette problmatique, vous avez toutes les informations dans le chapitre sur ce sujet : il vous
suffit de rcuprer la session en cours depuis l'objet requte, et d'y mettre en place des attributs. Concernant la mise en place
dans ce cas prcis par contre, il y a une question que vous allez devoir vous poser : quel type d'attributs enregistrer en session ?
Autrement dit, comment stocker les clients et commandes ? C'est une bonne question. Essayez d'y rflchir par vous-mmes
avant de lire le conseil qui suit...
Ici, ce qui vous intresse c'est d'enregistrer les clients et les commandes crs. Une liste de clients et une liste de commandes

www.siteduzero.com

Partie 4 : Une application interactive !

303/345

pourraient donc a priori faire l'affaire, mais retrouver quelque chose dans une liste, ce n'est pas simple... Pourtant, vous aimeriez
bien pouvoir identifier facilement un client ou une commande dans ces listes. Pour cette raison, une Map semble la solution
adapte. Oui mais comment organiser cette Map ? Les objets Client et Commande seront bien entendu les valeurs, mais qu'estce qui va bien pouvoir servir de cl ? Il y a tout un tas de solutions possibles, mais je vous conseille pour le moment de mettre en
place la moins contraignante : considrez que le nom permet d'identifier de manire unique un client, et que la date permet
d'identifier de manire unique une commande. Cela implique que votre application ne permettra pas de crer deux commandes au
mme instant, ni de crer deux clients portant le mme nom. Ce n'est pas gnial comme comportement, mais pour le moment votre
application ne gre toujours pas les donnes, donc a ne vous pose absolument aucun problme ! Vous aurez tout le loisir de
rgler ce petit souci dans l'tape 6 du fil rouge !
Bref, je vous conseille donc de placer en session une Map<String, Client> contenant les clients identifis par
leur nom, et une Map<String, Commande> contenant les commandes identifies par leur date.

Liste rcapitulative des clients et commandes crs


Deux pages JSP accdant directement aux attributs stocks en session suffisent ici. Vous pouvez mettre en place des servlets en
amont si vous le souhaitez, mais pour le moment elles ne sont pas ncessaires.
Dans chacune de celles-ci, le plus simple est de gnrer un tableau HTML qui affichera ligne par ligne les clients ou commandes
crs (voir les exemples de rendu). Pour cela, il vous suffit de parcourir les Map enregistres en tant qu'attributs de session
l'aide de la balise de boucle JSTL <c:forEach/>. Relisez le passage du cours sur la JSTL si vous avez oubli comment itrer
sur une collection, et relisez la correction de l'exercice sur la JSTL Core si vous avez oubli comme atteindre les cls et valeurs
d'une Map depuis une EL ! Dans le corps de cette boucle, vous placerez les balises HTML ncessaires la cration des lignes du
tableau HTML, contenant les entres de la Map des clients ou des commandes.
En bonus, pour arer la lecture du tableau final dans le navigateur, vous pouvez utiliser un compteur au sein de votre boucle
pour alterner la couleur de fond d'une ligne l'autre. Cela se fait par exemple en testant simplement si l'indice est pair ou impair.
Second bonus, vous pouvez mettre en place un test vrifiant si les objets prsents en sessions existent ou non, via par exemple
la balise <c:choose/> : si non, alors vous pouvez par exemple afficher un message signalant qu'aucun client ou aucune
commande n'existe (voir les exemples de rendu).

Un formulaire de cration de commande intelligent


En ce qui concerne cette modification, vous allez devoir rflchir un peu la solution mettre en place : comment donnez un
choix l'utilisateur ? Si vous regardez les exemples de rendu que je vous ai donns ci-dessus, vous verrez que j'ai mis en place
deux simples boutons de type <input type="radio" /> :
au clic sur "Oui", la premire partie du formulaire classique s'affiche ;
au clic sur "Non", un nouveau champ <select> listant les clients existants remplace la premire partie du formulaire !
Bien entendu, vous n'tes pas forcs d'utiliser ce moyen ! Si vous souhaitez que votre apprentissage soit efficace, alors vous
devez rflchir par vous-mmes cette petite problmatique et lui trouver une solution adapte sans mon aide. Ce petit exercice
de conception donnera du fil retorde vos neurones et vous fera prendre encore un peu plus d'aisance avec le Java EE !
En outre, la solution que je propose ici est un peu volue, car elle implique un petit morceau de code Javascript pour permettre
la modification du formulaire au clic sur un bouton radio. Si vous ne la sentez pas, prenez le temps et pensez un autre systme
plus simple et peut-tre moins volu graphiquement qui permettrait l'utilisateur de choisir entre une liste des clients existant et
un formulaire classique comme vous l'affichiez par dfaut auparavant. Ne vous dcouragez pas, testez et russissez !
Note : une telle modification du formulaire va bien videmment impliquer une modification de l'objet mtier qui y est
associ, c'est--dire CreationCommandeForm. En effet puisque vous proposez la rutilisation d'un client existant
l'utilisateur dans le formulaire, vous devrez faire en sorte dans votre objet mtier de ne valider les informations clients
que si un nouveau client a t cr, et simplement rcuprer l'objet Client existant si l'utilisateur choisit un ancien client
dans la liste !

Systme de suppression des clients et commandes


Pour terminer, il vous suffit ici de crer deux servlets, ddies chacune la suppression d'un client et d'une commande de la Map
prsente en session. Vous contacterez ces servlets via de simples liens HTML depuis vos pages listerClients.jsp ou

www.siteduzero.com

Partie 4 : Une application interactive !

304/345

listerCommandes.jsp, il faudra donc y implmenter la mthode doGet(). Ces liens contiendront alors soit un nom de client soit
une date de commande en tant que paramtre d'URL, et les servlets se chargeront alors de retirer l'entre correspondante de la
Map des clients ou des commandes, grce la mthode remove().
Dans les exemples de rendus ci-dessus, les croix rouges affiches en fin de chaque ligne des tableaux sont des liens vers les
servlets de suppression respectives, que vous pouvez par exemple nommer SuppressionClient et SuppressionCommande.

Correction
Cette fois, la longueur du sujet n'est pas trompeuse : le travail que vous devez fournir est bien important !
Posez-vous
calmement les bonnes questions, faites l'analogie avec ce que vous avez appris dans les chapitres de cours et n'oubliez pas les
bases que vous avez dcouvertes auparavant (cration d'une servlet, modification du fichier web.xml, utilisation de la JSTL, etc.).
Comme toujours, ce n'est pas la seule manire de faire, le principal est que votre solution respecte les consignes que je vous ai
donnes !
Prenez le temps de rflchir, de chercher et coder par vous-mmes. Si besoin, n'hsitez pas relire le sujet ou retourner
lire les prcdents chapitres. La pratique est trs importante, ne vous ruez pas sur la solution !

Pour que cette correction soit entirement fonctionnelle, vous devrez inclure la bibliothque jQuery dans votre projet,
ainsi que le fichier image suivant (clic-droit, enregistrer sous... et nommez-le supprimer.png).

Le code des vues


Secret (cliquez pour afficher)
Ajout des deux nouveaux liens dans la page menu.jsp :
Code : JSP - /inc/menu.jsp
<div id="menu">
<p><a href="<c:url value="/creerClient.jsp"/>">Crer un
nouveau client</a></p>
<p><a href="<c:url value="/creerCommande.jsp"/>">Crer une
nouvelle commande</a></p>
<p><a href="<c:url value="/listerClients.jsp"/>">Voir les clients
existants</a></p>
<p><a href="<c:url value="/listerCommandes.jsp"/>">Voir les
commandes existantes</a></p>
</div>

Modification du formulaire de cration d'une commande :


Code : JSP - creerCommande.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cration d'une commande</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div>
<form method="post" action="<c:url value="/creationCommande"/>">
<fieldset>
<legend>Informations client</legend>
<%-- Si et seulement si la Map des clients en session n'est pas vide, alors on
propose un choix l'utilisateur --%>

www.siteduzero.com

Partie 4 : Une application interactive !

305/345

<c:if test="${ !empty sessionScope.clients }">


<label for="choixNouveauClient">Nouveau client ? <span
class="requis">*</span></label>
<input type="radio" name="choixNouveauClient" value="nouveauClient" checked />
Oui
<input type="radio" name="choixNouveauClient" value="ancienClient" /> Non
<br/><br />
</c:if>
<div id="nouveauClient">

<label for="nomClient">Nom <span


class="requis">*</span></label>
<input type="text" id="nomClient" name="nomClient"
value="<c:out value="${commande.client.nom}"/>" size="30" maxlength="30" />
<span class="erreur">${form.erreurs['nomClient']}</span>
<br />
<label for="prenomClient">Prnom </label>
<input type="text" id="prenomClient" name="prenomClient"
value="<c:out value="${commande.client.prenom}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['prenomClient']}</span>
<br />
<label for="adresseClient">Adresse de livraison <span
class="requis">*</span></label>
<input type="text" id="adresseClient"
name="adresseClient" value="<c:out value="${commande.client.adresse}"/>"
size="30" maxlength="60" />
<span
class="erreur">${form.erreurs['adresseClient']}</span>
<br />
<label for="telephoneClient">Numro de tlphone <span
class="requis">*</span></label>
<input type="text" id="telephoneClient"
name="telephoneClient" value="<c:out value="${commande.client.telephone}"/>"
size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['telephoneClient']}</span>
<br />
<label for="emailClient">Adresse email</label>
<input type="email" id="emailClient" name="emailClient"
value="<c:out value="${commande.client.email}"/>" size="30" maxlength="60" />
<span
class="erreur">${form.erreurs['emailClient']}</span>
<br />
</div>
<%-- Si et seulement si la Map des clients en session n'est pas vide, alors on
cre la liste droulante --%>
<c:if test="${ !empty sessionScope.clients }">
<div id="ancienClient">
<select name="listeClients" id="listeClients">
<option value="">Choisissez un client...</option>
<%-- Boucle sur la map des clients --%>
<c:forEach items="${ sessionScope.clients }" var="mapClients">
<%-- L'expression EL ${mapClients.value} permet de cibler l'objet Client stock
en tant que valeur dans la Map,
et on cible ensuite simplement ses proprits nom et prenom comme on le ferait
avec n'importe quel bean. --%>
<option value="${ mapClients.value.nom }">${ mapClients.value.prenom } ${
mapClients.value.nom }</option>
</c:forEach>
</select>
</div>
</c:if>
</fieldset>
<fieldset>

www.siteduzero.com

Partie 4 : Une application interactive !

306/345

<legend>Informations commande</legend>
<label for="dateCommande">Date <span
class="requis">*</span></label>
<input type="text" id="v" name="dateCommande" value="<c:out
value="${commande.date}"/>" size="30" maxlength="30" disabled />
<span class="erreur">${form.erreurs['dateCommande']}</span>
<br />
<label for="montantCommande">Montant <span
class="requis">*</span></label>
<input type="text" id="montantCommande"
name="montantCommande" value="<c:out value="${commande.montant}"/>" size="30"
maxlength="30" />
<span
class="erreur">${form.erreurs['montantCommande']}</span>
<br />
<label for="modePaiementCommande">Mode de paiement <span
class="requis">*</span></label>
<input type="text" id="modePaiementCommande"
name="modePaiementCommande" value="<c:out value="${commande.modePaiement}"/>"
size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['modePaiementCommande']}</span>
<br />
paiement</label>

<label for="statutPaiementCommande">Statut du

<input type="text" id="statutPaiementCommande"


name="statutPaiementCommande" value="<c:out
value="${commande.statutPaiement}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['statutPaiementCommande']}</span>
<br />
<label for="modeLivraisonCommande">Mode de livraison <span
class="requis">*</span></label>
<input type="text" id="modeLivraisonCommande"
name="modeLivraisonCommande" value="<c:out value="${commande.modeLivraison}"/>"
size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['modeLivraisonCommande']}</span>
<br />
livraison</label>

<label for="statutLivraisonCommande">Statut de la

<input type="text" id="statutLivraisonCommande"


name="statutLivraisonCommande" value="<c:out
value="${commande.statutLivraison}"/>" size="30" maxlength="30" />
<span
class="erreur">${form.erreurs['statutLivraisonCommande']}</span>
<br />
<p class="info">${ form.resultat }</p>
</fieldset>
<input type="submit" value="Valider" />
<input type="reset" value="Remettre zro" /> <br />
</form>
</div>
<%-- Inclusion de la bibliothque jQuery. Vous trouverez des cours sur
JavaScript et jQuery aux adresses suivantes :
- http://www.siteduzero.com/tutoriel-3-309961-dynamisez-vos-sites-web-avecjavascript.html
- http://www.siteduzero.com/tutoriel-3-659477-un-site-web-dynamique-avecjquery.html
Si vous ne souhaitez pas tlcharger et ajouter jQuery votre projet, vous
pouvez utiliser la version fournie directement en ligne par Google :

www.siteduzero.com

Partie 4 : Une application interactive !

307/345

<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script
--%>
<script src="<c:url value="/inc/jquery.min.js"/>"></script>
<%-- Petite fonction jQuery permettant le remplacement de la premire partie du
formulaire par la liste droulante, au clic sur le bouton radio. --%>
<script>
$(document).ready(function(){
/* 1 - Au lancement de la page, on cache le bloc d'lments du formulaire
correspondant aux clients existants */
var $ancienClient = $("#ancienClient");
$ancienClient.hide();
/* 2 - Au clic sur un des deux boutons radio "choixNouveauClient", on affiche le
bloc d'lments correspondant (nouveau ou ancien client) */
$('input[name=choixNouveauClient]:radio').click(function(){
$("#nouveauClient").hide();
$ancienClient.hide();
var divId = $(this).val();
$("#" + divId).show();
});
});
</script>
</body>
</html>

Ajout des styles CSS des lments des tableaux :


Code : CSS - /inc/style.css
...
/* Tableaux ------------------------------------------------------------------------------------*/
table{
border-collapse: collapse;
}
tr.pair{
background-color: #efefef;
}
tr.impair{
background-color: #fff;
}
th{
color: #0568CD;
border: 1px solid #0568CD;
padding: 5px;
}
th.action{
border: 1px solid #900;
color: #900;
}
td{
border: 1px solid #ddd;
padding: 5px;
}
td.action{
text-align: center;
}

Cration des pages listant les clients et commandes crs :

www.siteduzero.com

Partie 4 : Une application interactive !

308/345

Code : JSP - /listerClients.jsp


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Liste des clients existants</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div id="corps">
<c:choose>
<%-- Si aucun client n'existe en session, affichage
d'un message par dfaut. --%>
<c:when test="${ empty sessionScope.clients }">
<p class="erreur">Aucun client enregistr.</p>
</c:when>
<%-- Sinon, affichage du tableau. --%>
<c:otherwise>
<table>
<tr>
<th>Nom</th>
<th>Prnom</th>
<th>Adresse</th>
<th>Tlphone</th>
<th>Email</th>
<th class="action">Action</th>
</tr>
<%-- Parcours de la Map des clients en session, et
utilisation de l'objet varStatus. --%>
<c:forEach items="${ sessionScope.clients }"
var="mapClients" varStatus="boucle">
<%-- Simple test de parit sur l'index de
parcours, pour alterner la couleur de fond de chaque ligne du
tableau. --%>
<tr class="${boucle.index % 2 == 0 ? 'pair' :
'impair'}">
<%-- Affichage des proprits du bean Client,
qui est stock en tant que valeur de l'entre courante de la map -%>
<td><c:out value="${ mapClients.value.nom
}"/></td>
<td><c:out value="${ mapClients.value.prenom
}"/></td>
<td><c:out value="${ mapClients.value.adresse
}"/></td>
<td><c:out value="${
mapClients.value.telephone }"/></td>
<td><c:out value="${ mapClients.value.email
}"/></td>
<%-- Lien vers la servlet de suppression, avec
passage du nom du client - c'est--dire la cl de la Map - en
paramtre grce la balise <c:param/>. --%>
<td class="action">
<a href="<c:url
value="/suppressionClient"><c:param name="nomClient" value="${
mapClients.key }" /></c:url>">
<img src="<c:url
value="/inc/supprimer.png"/>" alt="Supprimer" />
</a>
</td>
</tr>
</c:forEach>
</table>
</c:otherwise>

www.siteduzero.com

Partie 4 : Une application interactive !

309/345

</c:choose>
</div>
</body>
</html>

Code : JSP - /listerCommandes.jsp


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Liste des commandes existantes</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/style.css"/>" />
</head>
<body>
<c:import url="/inc/menu.jsp" />
<div id="corps">
<c:choose>
<%-- Si aucune commande n'existe en session, affichage
d'un message par dfaut. --%>
<c:when test="${ empty sessionScope.commandes }">
<p class="erreur">Aucune commande enregistre.</p>
</c:when>
<%-- Sinon, affichage du tableau. --%>
<c:otherwise>
<table>
<tr>
<th>Client</th>
<th>Date</th>
<th>Montant</th>
<th>Mode de paiement</th>
<th>Statut de paiement</th>
<th>Mode de livraison</th>
<th>Statut de livraison</th>
<th class="action">Action</th>
</tr>
<%-- Parcours de la Map des commandes en session,
et utilisation de l'objet varStatus. --%>
<c:forEach items="${ sessionScope.commandes }"
var="mapCommandes" varStatus="boucle">
<%-- Simple test de parit sur l'index de
parcours, pour alterner la couleur de fond de chaque ligne du
tableau. --%>
<tr class="${boucle.index % 2 == 0 ? 'pair' :
'impair'}">
<%-- Affichage des proprits du bean
Commande, qui est stock en tant que valeur de l'entre courante
de la map --%>
<td><c:out value="${
mapCommandes.value.client.prenom } ${
mapCommandes.value.client.nom }"/></td>
<td><c:out value="${ mapCommandes.value.date
}"/></td>
<td><c:out value="${
mapCommandes.value.montant }"/></td>
<td><c:out value="${
mapCommandes.value.modePaiement }"/></td>
<td><c:out value="${
mapCommandes.value.statutPaiement }"/></td>
<td><c:out value="${
mapCommandes.value.modeLivraison }"/></td>
<td><c:out value="${
mapCommandes.value.statutLivraison }"/></td>
<%-- Lien vers la servlet de suppression, avec
passage de la date de la commande - c'est--dire la cl de la Map

www.siteduzero.com

Partie 4 : Une application interactive !

310/345

- en paramtre grce la balise <c:param/>. --%>


<td class="action">
<a href="<c:url
value="/suppressionCommande"><c:param name="dateCommande"
value="${ mapCommandes.key }" /></c:url>">
<img src="<c:url
value="/inc/supprimer.png"/>" alt="Supprimer" />
</a>
</td>
</tr>
</c:forEach>
</table>
</c:otherwise>
</c:choose>
</div>
</body>
</html>

Le code des servlets


Secret (cliquez pour afficher)
Ajout des deux servlets de suppression dans le fichier web.xml :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>CreationClient</servlet-name>
<servlet-class>com.sdzee.tp.servlets.CreationClient</servletclass>
</servlet>
<servlet>
<servlet-name>SuppressionClient</servlet-name>
<servlet-class>com.sdzee.tp.servlets.SuppressionClient</servletclass>
</servlet>
<servlet>
<servlet-name>CreationCommande</servlet-name>
<servlet-class>com.sdzee.tp.servlets.CreationCommande</servletclass>
</servlet>
<servlet>
<servlet-name>SuppressionCommande</servlet-name>
<servlet-class>com.sdzee.tp.servlets.SuppressionCommande</servletclass>
</servlet>
<servlet-mapping>
<servlet-name>CreationClient</servlet-name>
<url-pattern>/creationClient</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SuppressionClient</servlet-name>
<url-pattern>/suppressionClient</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CreationCommande</servlet-name>
<url-pattern>/creationCommande</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SuppressionCommande</servlet-name>

www.siteduzero.com

Partie 4 : Une application interactive !

311/345

<url-pattern>/suppressionCommande</url-pattern>
</servlet-mapping>
</web-app>

Cration des servlets de suppression :


Code : Java - com.sdzee.tp.servlets.SuppressionClient
package com.sdzee.tp.servlets;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import com.sdzee.tp.beans.Client;
public class SuppressionClient extends HttpServlet {
public static final String PARAM_NOM_CLIENT = "nomClient";
public static final String SESSION_CLIENTS = "clients";
public static final String VUE
"/listerClients.jsp";

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/* Rcupration du paramtre */
String nomClient = getValeurParametre( request,
PARAM_NOM_CLIENT );
/* Rcupration de la Map des clients enregistrs en
session */
HttpSession session = request.getSession();
Map<String, Client> clients = (HashMap<String, Client>)
session.getAttribute( SESSION_CLIENTS );
vides */

/* Si le nom du client et la Map des clients ne sont pas

if ( nomClient != null && clients != null ) {


/* Alors suppression du client de la Map */
clients.remove( nomClient );
/* Et remplacement de l'ancienne Map en session par
la nouvelle */
session.setAttribute( SESSION_CLIENTS, clients );
}

/* Redirection vers la fiche rcapitulative */


response.sendRedirect( request.getContextPath() + VUE );

/*
* Mthode utilitaire qui retourne null si un paramtre est vide,
et son
* contenu sinon.
*/
private static String getValeurParametre( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {

www.siteduzero.com

Partie 4 : Une application interactive !

312/345

return null;
} else {
return valeur;
}

Code : Java - com.sdzee.tp.servlets.SuppressionCommande


package com.sdzee.tp.servlets;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import com.sdzee.tp.beans.Commande;
public class SuppressionCommande extends HttpServlet {
public static final String PARAM_DATE_COMMANDE =
"dateCommande";
public static final String SESSION_COMMANDES
= "commandes";
public static final String VUE
"/listerCommandes.jsp";

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/* Rcupration du paramtre */
String dateCommande = getValeurParametre( request,
PARAM_DATE_COMMANDE );
/* Rcupration de la Map des commandes enregistres en
session */
HttpSession session = request.getSession();
Map<String, Commande> commandes = (HashMap<String,
Commande>) session.getAttribute( SESSION_COMMANDES );
/* Si la date de la commande et la Map des commandes ne
sont pas vides */
if ( dateCommande != null && commandes != null ) {
/* Alors suppression de la commande de la Map */
commandes.remove( dateCommande );
/* Et remplacement de l'ancienne Map en session par
la nouvelle */
session.setAttribute( SESSION_COMMANDES, commandes );
}

/* Redirection vers la fiche rcapitulative */


response.sendRedirect( request.getContextPath() + VUE );

/*
* Mthode utilitaire qui retourne null si un paramtre est vide,
et son
* contenu sinon.
*/
private static String getValeurParametre( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );

www.siteduzero.com

Partie 4 : Une application interactive !

313/345

String valeur = request.getParameter( nomChamp );


if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur;
}

Modification des servlets existantes pour l'enregistrement en session :


Code : Java - com.sdzee.tp.servlets.CreationClient
package com.sdzee.tp.servlets;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import com.sdzee.tp.beans.Client;
import com.sdzee.tp.forms.CreationClientForm;
public class CreationClient extends HttpServlet {
public static final String ATT_CLIENT
= "client";
public static final String ATT_FORM
= "form";
public static final String SESSION_CLIENTS = "clients";
public static final String VUE_SUCCES
"/afficherClient.jsp";
public static final String VUE_FORM
"/creerClient.jsp";

=
=

public void doPost( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/* Prparation de l'objet formulaire */
CreationClientForm form = new CreationClientForm();
/* Traitement de la requte et rcupration du bean en
rsultant */
Client client = form.creerClient( request );
*/

/* Ajout du bean et de l'objet mtier l'objet requte


request.setAttribute( ATT_CLIENT, client );
request.setAttribute( ATT_FORM, form );

/* Si aucune erreur */
if ( form.getErreurs().isEmpty() ) {
/* Alors rcupration de la map des clients dans la session */
HttpSession session = request.getSession();
Map<String, Client> clients = (HashMap<String, Client>)
session.getAttribute( SESSION_CLIENTS );
/* Si aucune map n'existe, alors initialisation d'une nouvelle
map */
if ( clients == null ) {
clients = new HashMap<String, Client>();
}
/* Puis ajout du client courant dans la map */
clients.put( client.getNom(), client );

www.siteduzero.com

Partie 4 : Une application interactive !

314/345

/* Et enfin (r)enregistrement de la map en session */


session.setAttribute( SESSION_CLIENTS, clients );
/* Affichage de la fiche rcapitulative */
this.getServletContext().getRequestDispatcher(
VUE_SUCCES ).forward( request, response );
} else {
/* Sinon, r-affichage du formulaire de cration avec
les erreurs */
this.getServletContext().getRequestDispatcher(
VUE_FORM ).forward( request, response );
}
}
}

Code : Java - com.sdzee.tp.servlets.CreationCommande


package com.sdzee.tp.servlets;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import com.sdzee.tp.beans.Client;
import com.sdzee.tp.beans.Commande;
import com.sdzee.tp.forms.CreationCommandeForm;
public class CreationCommande extends HttpServlet {
public static final String ATT_COMMANDE
= "commande";
public static final String ATT_FORM
= "form";
public static final String SESSION_CLIENTS = "clients";
public static final String SESSION_COMMANDES = "commandes";
public static final String VUE_SUCCES
"/afficherCommande.jsp";
public static final String VUE_FORM
"/creerCommande.jsp";

=
=

public void doPost( HttpServletRequest request,


HttpServletResponse response ) throws ServletException,
IOException {
/* Prparation de l'objet formulaire */
CreationCommandeForm form = new CreationCommandeForm();
/* Traitement de la requte et rcupration du bean en
rsultant */
Commande commande = form.creerCommande( request );
*/

/* Ajout du bean et de l'objet mtier l'objet requte


request.setAttribute( ATT_COMMANDE, commande );
request.setAttribute( ATT_FORM, form );

/* Si aucune erreur */
if ( form.getErreurs().isEmpty() ) {
/* Alors rcupration de la map des clients dans la session */
HttpSession session = request.getSession();
Map<String, Client> clients = (HashMap<String, Client>)
session.getAttribute( SESSION_CLIENTS );
/* Si aucune map n'existe, alors initialisation d'une nouvelle
map */

www.siteduzero.com

Partie 4 : Une application interactive !

315/345

map */
if ( clients == null ) {
clients = new HashMap<String, Client>();
}
/* Puis ajout du client de la commande courante dans la map */
clients.put( commande.getClient().getNom(), commande.getClient()
);
/* Et enfin (r)enregistrement de la map en session */
session.setAttribute( SESSION_CLIENTS, clients );
/* Ensuite rcupration de la map des commandes dans la session
*/
Map<String, Commande> commandes = (HashMap<String, Commande>)
session.getAttribute( SESSION_COMMANDES );
/* Si aucune map n'existe, alors initialisation d'une nouvelle
map */
if ( commandes == null ) {
commandes = new HashMap<String, Commande>();
}
/* Puis ajout de la commande courante dans la map */
commandes.put( commande.getDate(), commande );
/* Et enfin (r)enregistrement de la map en session */
session.setAttribute( SESSION_COMMANDES, commandes );
/* Affichage de la fiche rcapitulative */
this.getServletContext().getRequestDispatcher(
VUE_SUCCES ).forward( request, response );
} else {
/* Sinon, r-affichage du formulaire de cration avec
les erreurs */
this.getServletContext().getRequestDispatcher(
VUE_FORM ).forward( request, response );
}
}
}

Le code des objets mtiers


Secret (cliquez pour afficher)
Modification de l'objet grant la cration d'une commande :
Code : Java - com.sdzee.tp.forms.CreationCommandeForm
package com.sdzee.tp.forms;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.sdzee.tp.beans.Client;
import com.sdzee.tp.beans.Commande;
public final class CreationCommandeForm {
private static final String CHAMP_CHOIX_CLIENT =
"choixNouveauClient";
private static final String CHAMP_LISTE_CLIENTS = "listeClients";
private static final String CHAMP_DATE
=

www.siteduzero.com

Partie 4 : Une application interactive !

316/345

"dateCommande";
private static final String
"montantCommande";
private static final String
"modePaiementCommande";
private static final String
"statutPaiementCommande";
private static final String
"modeLivraisonCommande";
private static final String
"statutLivraisonCommande";

CHAMP_MONTANT

CHAMP_MODE_PAIEMENT

CHAMP_STATUT_PAIEMENT

CHAMP_MODE_LIVRAISON

CHAMP_STATUT_LIVRAISON =

private static final String ANCIEN_CLIENT = "ancienClient";


private static final String SESSION_CLIENTS = "clients";
private static final String FORMAT_DATE
=
"dd/MM/yyyy HH:mm:ss";
private String
resultat;
private Map<String, String> erreurs
HashMap<String, String>();

= new

public Map<String, String> getErreurs() {


return erreurs;
}
public String getResultat() {
return resultat;
}
public Commande creerCommande( HttpServletRequest request ) {
Client client;
/*
* Si l'utilisateur choisit un client dj existant, pas de
validation
* effectuer
*/
String choixNouveauClient = getValeurChamp( request,
CHAMP_CHOIX_CLIENT );
if ( ANCIEN_CLIENT.equals( choixNouveauClient ) ) {
/* Rcupration du nom du client choisi */
String nomAncienClient = getValeurChamp( request,
CHAMP_LISTE_CLIENTS );
/* Rcupration de l'objet client correspondant dans la session
*/
HttpSession session = request.getSession();
client = ( (Map<String, Client>) session.getAttribute(
SESSION_CLIENTS ) ).get( nomAncienClient );
} else {
/*
* Sinon on garde l'ancien mode, pour la validation des champs.
*
* L'objet mtier pour valider la cration d'un client existe dj
,
* il est donc dconseill de dupliquer ici son contenu ! A la
* place, il suffit de passer la requte courante l'objet mtier
* existant et de rcuprer l'objet Client cr.
*/
CreationClientForm clientForm = new
CreationClientForm();
client = clientForm.creerClient( request );
/*
* Et trs important, il ne faut pas oublier de rcuprer le
contenu
* de la map d'erreur cre par l'objet mtier CreationClientForm
* dans la map d'erreurs courante, actuellement vide.
*/
erreurs = clientForm.getErreurs();
}

www.siteduzero.com

Partie 4 : Une application interactive !

317/345

/*
* Ensuite, il suffit de procder normalement avec le reste des
champs
* spcifiques une commande.
*/
/*
* Rcupration et conversion de la date en String selon le
format
* choisi.
*/
DateTime dt = new DateTime();
DateTimeFormatter formatter = DateTimeFormat.forPattern(
FORMAT_DATE );
String date = dt.toString( formatter );
String montant = getValeurChamp( request, CHAMP_MONTANT );
String modePaiement = getValeurChamp( request,
CHAMP_MODE_PAIEMENT );
String statutPaiement = getValeurChamp( request,
CHAMP_STATUT_PAIEMENT );
String modeLivraison = getValeurChamp( request,
CHAMP_MODE_LIVRAISON );
String statutLivraison = getValeurChamp( request,
CHAMP_STATUT_LIVRAISON );
Commande commande = new Commande();
commande.setClient( client );
double valeurMontant = -1;
try {
valeurMontant = validationMontant( montant );
} catch ( Exception e ) {
setErreur( CHAMP_MONTANT, e.getMessage() );
}
commande.setMontant( valeurMontant );
commande.setDate( date );
try {
validationModePaiement( modePaiement );
} catch ( Exception e ) {
setErreur( CHAMP_MODE_PAIEMENT, e.getMessage() );
}
commande.setModePaiement( modePaiement );
try {
validationStatutPaiement( statutPaiement );
} catch ( Exception e ) {
setErreur( CHAMP_STATUT_PAIEMENT, e.getMessage() );
}
commande.setStatutPaiement( statutPaiement );
try {
validationModeLivraison( modeLivraison );
} catch ( Exception e ) {
setErreur( CHAMP_MODE_LIVRAISON, e.getMessage() );
}
commande.setModeLivraison( modeLivraison );
try {
validationStatutLivraison( statutLivraison );
} catch ( Exception e ) {
setErreur( CHAMP_STATUT_LIVRAISON, e.getMessage() );
}
commande.setStatutLivraison( statutLivraison );
if ( erreurs.isEmpty() ) {
resultat = "Succs de la cration de la commande.";

www.siteduzero.com

Partie 4 : Une application interactive !

318/345

} else {
resultat = "chec de la cration de la commande.";
}
return commande;

private double validationMontant( String montant ) throws


Exception {
double temp;
if ( montant != null ) {
try {
temp = Double.parseDouble( montant );
if ( temp < 0 ) {
throw new Exception( "Le montant doit tre un
nombre positif." );
}
} catch ( NumberFormatException e ) {
temp = -1;
throw new Exception( "Le montant doit tre un
nombre." );
}
} else {
temp = -1;
throw new Exception( "Merci d'entrer un montant." );
}
return temp;
}
private void validationModePaiement( String modePaiement )
throws Exception {
if ( modePaiement != null ) {
if ( modePaiement.length() < 2 ) {
throw new Exception( "Le mode de paiement doit
contenir au moins 2 caractres." );
}
} else {
throw new Exception( "Merci d'entrer un mode de
paiment." );
}
}
private void validationStatutPaiement( String statutPaiement )
throws Exception {
if ( statutPaiement != null && statutPaiement.length() < 2
) {
throw new Exception( "Le statut de paiement doit
contenir au moins 2 caractres." );
}
}
private void validationModeLivraison( String modeLivraison )
throws Exception {
if ( modeLivraison != null ) {
if ( modeLivraison.length() < 2 ) {
throw new Exception( "Le mode de livraison doit
contenir au moins 2 caractres." );
}
} else {
throw new Exception( "Merci d'entrer un mode de
livraison." );
}
}
private void validationStatutLivraison( String statutLivraison
) throws Exception {
if ( statutLivraison != null && statutLivraison.length() <
2 ) {
throw new Exception( "Le statut de livraison doit
contenir au moins 2 caractres." );
}

www.siteduzero.com

Partie 4 : Une application interactive !

319/345

}
/*
* Ajoute un message correspondant au champ spcifi la map des
erreurs.
*/
private void setErreur( String champ, String message ) {
erreurs.put( champ, message );
}
/*
* Mthode utilitaire qui retourne null si un champ est vide, et
son contenu
* sinon.
*/
private static String getValeurChamp( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur;
}
}
}

www.siteduzero.com

Partie 4 : Une application interactive !

320/345

Formulaires : l'envoi de fichiers


Nous savons grer toutes sortes de saisies simples - champs de type texte, case cocher, liste droulante, bouton radio, etc. mais il nous reste encore traiter le cas du champ de formulaire permettant l'envoi d'un fichier. C'est un gros chapitre qui vous
attend : il y a beaucoup de choses dcouvrir, prenez le temps de bien assimiler toutes les notions prsentes !

Cration du formulaire
Pour permettre au visiteur de naviguer et slectionner un fichier pour envoi via un champ de formulaire, il faut utiliser la balise
HTML <input type="file">. Pour rappel, et c'est d'ailleurs explicit dans la spcification HTML, pour envoyer un fichier
il faut utiliser la mthode POST lors de l'envoi des donnes du formulaire. En outre, nous y apprenons que l'attribut optionnel
enctype doit tre dfini "multipart/form-data".
Sans plus tarder, crons une page upload.jsp qui affiche un tel formulaire l'utilisateur :
Code : JSP - /WEB-INF/upload.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Envoi de fichier</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/form.css"/>" />
</head>
<body>
<form action="<c:url value="/upload" />" method="post"
enctype="multipart/form-data">
<fieldset>
<legend>Envoi de fichier</legend>
fichier</label>

<label for="description">Description du

<input type="text" id="description"


name="description" value="" />
<br />
<label for="fichier">Emplacement du fichier <span
class="requis">*</span></label>
<input type="file" id="fichier" name="fichier" />
<br />
<input type="submit" value="Envoyer"
class="sansLabel" />
<br />
</fieldset>
</form>
</body>
</html>

Remarquez bien dans les lignes surlignes :


l'utilisation de l'attribut optionnel enctype, dont nous n'avions pas besoin dans nos formulaires d'inscription et de
connexion puisqu'ils contenaient uniquement des champs classiques ;
la mise en place d'un champ <input type="file"/> ddi l'envoi de fichier.
C'est la seule page ncessaire : j'ai rutilis la mme feuille de style CSS que pour nos prcdents formulaires.

Rcupration des donnes


Mise en place
Vous commencez tre habitus maintenant : l'tape suivante est la mise en place de la servlet associe cette page.
Il nous faut donc crer une servlet, que nous allons nommer Upload et qui est presque vide pour l'instant :
Code : Java - com.sdzee.servlets.Upload

www.siteduzero.com

Partie 4 : Une application interactive !

321/345

package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class Upload extends HttpServlet {


public static final String VUE = "/WEB-INF/upload.jsp";
public void doGet( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Affichage de la page d'envoi de fichier */
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Mthode vide, pour l'instant... */
}
}

Puis l'associer la requte HTTP mise par le formulaire, en la dclarant dans le web.xml de notre application :
Code : XML - /WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
...
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.sdzee.servlets.Upload</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>Upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
</web-app>

Avec une telle configuration, nous pouvons accder au formulaire en nous rendant depuis notre navigateur sur
http://localhost:8080/pro/upload :

L'tape suivante consiste bien videmment complter notre servlet pour traiter les donnes reues !

Traitement des donnes


www.siteduzero.com

Partie 4 : Une application interactive !

322/345

Aprs avoir soumis un tel formulaire, les donnes envoyes sont dans un format binaire "multipart", et sont disponibles
dans le corps de la requte POST.
ce sujet, une subtilit importante mrite d'tre porte votre attention : ce format de requte n'est pas support par les
versions de Tomcat antrieures 7.0.6. L'explication de ce comportement rside principalement dans :
la version de l'API servlet utilise : ce n'est qu' partir de Java EE 6 que la version 3.0 du conteneur de servlets a t mise
en place. L'API en version 2.x ne supporte pas de telles requtes, elle ne sait grer que le enctype par dfaut.
un bug dans les premires ditions de Tomcat 7 : aucun problme en ce qui nous concerne, les versions rcentes ont
corrig ce problme.

Avec l'API servlet 2.x


Lorsque des donnes sont envoyes avec le type multipart, les mthodes request.getParameter() et consorts
retournent tous null. Il est en thorie possible d'analyser le corps de la requte vous-mmes en vous basant sur la mthode
getInputStream() de l'objet HttpServletRequest, mais c'est un vrai travail dorfvre qui requiert une parfaite
connaissance de la norme RFC2388 !
Nous n'allons pas tudier en dtails la mthode mettre en place avec cette ancienne version de l'API, mais je vais tout
de mme vous donner les lments principaux pour que vous sachiez par o commencer, si jamais vous devez travailler
un jour sur une application qui tourne sur une version de l'API antrieure la 3.0.

La coutume est plutt d'utiliser Apache Commons FileUpload pour parser les donnes multipart du formulaire. Cette
bibliothque est une trs robuste implmentation de la RFC2388, qui dispose d'excellents guide utilisateur et FAQ (ressources en
anglais, mais je vous recommande de parcourir les deux attentivement si vous travaillez avec cette version de l'API servlet). Pour
l'utiliser, il est ncessaire de placer les fichiers commons-fileupload.jar et commons-io.jar dans le rpertoire /WEB-INF/lib de
votre application.
Je vous prsente ici succinctement le principe gnral, mais je ne dtaille volontairement pas la dmarche et ne vous fais pas
mettre en place d'exemple pratique : vous allez le dcouvrir un peu plus bas, nous allons utiliser dans notre projet la dmarche
spcifique l'API servlet 3.0. Voici cependant un exemple montrant ce quoi devrait ressembler la mthode doPost() de votre
servlet d'upload si vous utilisez Apache Commons FileUpload :
Code : Java - Exemple d'utilisation de la bibliothque Apache Commons FileUpload
...
import
import
import
import

org.apache.commons.fileupload.FileItem;
org.apache.commons.fileupload.FileUploadException;
org.apache.commons.fileupload.disk.DiskFileItemFactory;
org.apache.commons.fileupload.servlet.ServletFileUpload;

...
public void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
try {
List<FileItem> items = new ServletFileUpload(new
DiskFileItemFactory()).parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
/* Traiter les champs classiques ici (input
type="text|radio|checkbox|etc", select, etc). */
String nomChamp = item.getFieldName();
String valeurChamp = item.getString();
/* ... (traitement faire) */
} else {
/* Traiter les champs de type fichier (input
type="file"). */
String nomChamp = item.getFieldName();
String nomFichier =
FilenameUtils.getName(item.getName());
InputStream contenuFichier = item.getInputStream();

www.siteduzero.com

Partie 4 : Une application interactive !


}

323/345

/* ... (traitement faire) */

}
} catch (FileUploadException e) {
throw new ServletException("chec de l'analyse de la requte
multipart.", e);
}
}

// ...

Je vous renvoie la documentation de la bibliothque si vous souhaitez en apprendre davantage sur son fonctionnement.
En guise d'ouverture pour cette solution, une alternative intressante ce systme serait d'intgrer tout cela dans un Filter
qui analyserait le contenu automatiquement et rinsrerait le tout dans la Map des paramtres de la requte, comme s'il s'agissait
d'un champ de formulaire classique, rendant ainsi possible de manire transparente :
l'utilisation d'un simple request.getParameter() comme lors de la rcupration d'un paramtre quelconque ;
l'obtention du fichier upload via request.getAttribute().
Vous pouvez trouver un tel exemple sur cet excellent article.

Avec l'API servlet 3.0


En ce qui nous concerne, notre application se base sur l'API servlet 3.0, la solution prcdente ne nous est donc pas ncessaire !
Dans cette dernire mouture, une nouvelle mthode getParts() est mise disposition dans l'objet
HttpServletRequest, et permet de collecter trs simplement les lments de donnes de type multipart ! Auparavant, il
tait impossible de parvenir cela simplement sans bibliothque externe.
Pour la petite histoire, afin de rendre cette fonctionnalit disponible, la plupart des conteneurs implmentant l'API
servlet 3.0 utilisent en ralit le code de la bibliothque Apache Commons FileUpload dans les coulisses ! C'est
notamment le cas de Tomcat 7 (Apache) et de GlassFish 3 (Oracle).
Pour commencer, nous devons complter la dclaration de notre servlet dans notre fichier web.xml avec une section
<multipart-config> afin de faire en sorte que la mthode getParts() fonctionne :
Code : XML - Extrait du fichier /WEB-INF/web.xml
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.sdzee.servlets.Upload</servlet-class>
<multipart-config>
<location>c:/fichiers</location>
<max-file-size>10485760</max-file-size> <!-- 10 Mo -->
<max-request-size>52428800</max-request-size> <!-- 5 x 10Mo -->
<file-size-threshold>1048576</file-size-threshold> <!-- 1 Mo -->
</multipart-config>
</servlet>

Vous remarquez que cette section s'ajoute au sein de la balise de dclaration <servlet> de notre servlet d'upload. Voici une
rapide description des paramtres optionnels existant :
<location> contient une URL absolue vers un rpertoire du systme. Un chemin relatif au contexte de l'application
n'est pas support dans cette balise, il s'agit bien l d'un chemin absolu vers le systme. Cette URL sera utilise pour
stocker temporairement un fichier lors du traitement des fragments d'une requte, lorsque la taille du fichier est plus
grande que la taille spcifie dans <file-size-threshold>. Si vous prcisez ici un rpertoire qui n'existe pas sur le
disque, alors Tomcat enverra une java.io.IOException lorsque vous tenterez d'envoyer un fichier plus gros que
cette limite.
<file-size-threshold> prcise la taille en octets partir de laquelle un fichier reu sera temporairement stock
sur le disque.
<max-file-size> prcise la taille maximum en octets autorise pour un fichier envoy. Si la taille d'un fichier

www.siteduzero.com

Partie 4 : Une application interactive !

324/345

envoy dpasse cette limite, le conteneur enverra une exception. En l'occurrence, Tomcat lancera une
IllegalStateException.
<max-request-size> prcise la taille maximum en octets autorise pour une requte multipart/form-data. Si la taille
totale des donnes envoyes dans une seule requte dpasse cette limite, le conteneur enverra une exception.
En paramtrant ainsi notre servlet, toutes les donnes multipart/form-data seront disponibles travers la mthode
request.getParts(). Celle-ci retourne une collection d'lments de type Part, et doit tre utilise en lieu de place de
l'habituelle mthode request.getParameter() pour rcuprer les contenus des champs de formulaire.
l'utilisation, il s'avre que c'est bien plus pratique que d'utiliser directement du pur Apache Commons FileUpload, comme c'tait
ncessaire avec les versions antrieures de l'API Servlet ! Par contre, je me rpte mais je viens de vous annoncer que les
contenus des champs du formulaire allaient maintenant tre disponibles en tant que collection d'lments de type Part, et a, a
va nous poser un petit problme... Car si vous tudiez attentivement l'interface Part, vous vous rendrez compte qu'elle est
plutt limite en termes d'abstraction : c'est simple, elle ne propose tout bonnement aucune mthode permettant de dterminer si
une donne reue renferme un champ classique ou un champ de type fichier !
Dans ce cas, comment savoir si une requte contient des fichiers ?

Heureusement, il va tre facile de nous en sortir par nous-mmes. Afin de dterminer si les donnes transmises dans une requte
HTTP contiennent d'ventuels fichiers ou non, il suffit d'analyser ses en-ttes. Regardez plutt ces deux extraits d'en-tte HTTP
(comments) :
Code : HTTP - Exemples de content-disposition dans l'en-tte d'une requte HTTP
// Pour un champ <input type="text"> nomm 'description'
Content-Disposition: form-data; name="description"
// Pour un champ <input type="file"> nomm 'fichier'
Content-Disposition: formdata; name="fichier"; filename="nom_du_fichier.ext"

Comme vous pouvez le constater, la seule diffrence est la prsence d'un attribut nomm filename. Il suffit donc de s'assurer
qu'une en-tte contient le mot-cl filename pour tre certain que le fragment trait est un fichier.

Tout cela est magnifique, mais comment allons-nous rcuprer le contenu des en-ttes relatif un fragment donn ?

Comme d'habitude, il n'y a pas de miracle : tout est dans la documentation !


Encore une fois, si vous tudiez attentivement
l'interface Part, vous constaterez qu'elle contient une mthode part.getHeader() qui renvoie l'en-tte correspondant
un lment. Exactement ce qu'il nous faut !
Ainsi, nous allons pouvoir examiner le contenu des en-ttes relatif chaque fragment de la requte, et y vrifier la prsence du
mot-cl filename afin de savoir si le champ trait est de type fichier ou non.
Lanons-nous, et implmentons un dbut de mthode doPost() dans notre servlet d'upload :
Code : Java - com.sdzee.servlets.Upload
...
public static final String CHAMP_DESCRIPTION = "description";
...
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException{
/* Rcupration du contenu du champ de description */
String description = request.getParameter( CHAMP_DESCRIPTION );
request.setAttribute( CHAMP_DESCRIPTION, description );

www.siteduzero.com

Partie 4 : Une application interactive !

325/345

/*
* Les donnes reues sont multipart, on doit donc utiliser la
mthode
* getParts()
*/
for ( Part part : request.getParts() ) {
/*
* Pour chaque donne issue de la requte, c'est--dire pour chaque
* fragment contenu dans le retour de la mthode getParts(), il faut
* dterminer s'il s'agit d'un champ classique ou d'un champ de type
* fichier : on dlgue cette opration la mthode utilitaire
* getNomFichier().
*/
String nomFichier = getNomFichier( part );
/*
* Si la mthode a renvoy quelque chose, il s'agit donc d'un champ
* de type fichier (input type="file").
*/
if ( nomFichier != null && !nomFichier.isEmpty() ) {
String nomChamp = part.getName();
request.setAttribute( nomChamp, nomFichier );
}
}
this.getServletContext().getRequestDispatcher( VUE ).forward(
request, response );
}
/*
* Mthode utilitaire qui a pour unique but d'analyser l'en-tte
"content-disposition",
* et de vrifier si le paramtre "filename" y est prsent. Si oui,
alors le champ trait
* est de type File et la mthode retourne son nom, sinon il s'agit
d'un champ de formulaire
* classique et la mthode retourne null.
*/
private static String getNomFichier( Part part ) {
/* Boucle sur chacun des paramtres de l'en-tte "contentdisposition". */
for ( String contentDisposition : part.getHeader( "contentdisposition" ).split( ";" ) ) {
/* Recherche de l'ventuelle prsence du paramtre "filename".
*/
if ( contentDisposition.trim().startsWith("filename") ) {
/* Si "filename" est prsent, alors renvoi de sa valeur,
c'est--dire du nom de fichier. */
return contentDisposition.substring(
contentDisposition.indexOf( '=' ) + 1 );
}
}
/* Et pour terminer, si rien n'a t trouv... */
return null;
}

Cette bauche est assez commente pour que vous puissiez comprendre son fonctionnement sans problmes. La boucle la
ligne 16 parcours chacun des fragments de donnes envoys par le formulaire. Il en existe un pour chaque champ, en
l'occurrence dans notre cas la boucle va faire deux tours : un premier tour sur le fragment correspondant au champ description, et
un second sur le fragment correspondant au champ fichier. Ensuite, l'intrieur de cette boucle il suffit d'analyser l'en-tte du
fragment courant pour dterminer s'il s'agit d'un champ de type fichier ou non. En l'occurrence notre formulaire n'en contient
qu'un seul - le champ fichier - mais il pourrait tout aussi bien en contenir cinquante, et notre mthode dterminerait toujours
automatiquement le type de chacun des champs.
Je vous donne pour finir des prcisions au sujet de la mthode utilitaire getNomFichier(). Je vous l'ai annonc un peu plus
tt, l'en-tte HTTP lue est de la forme :

www.siteduzero.com

Partie 4 : Une application interactive !

326/345

Code : HTTP - Exemple de content-disposition dans l'en-tte d'une requte HTTP


Content-Disposition: form-data; filename="nomdufichier.ext"

Afin de slectionner uniquement la valeur du paramtre filename, je ralise dans la mthode utilitaire :
un part.getHeader( "content-disposition" ), afin de ne traiter que la ligne de l'en-tte concernant le
content-disposition. Par ailleurs, vous pouvez remarquer que la mthode ne prte aucune attention la casse dans
l'argument que vous lui passez, c'est--dire aux ventuelles majuscules qu'il contient : que vous criviez "contentdisposition", "Content-disposition" ou encore "Content-Disposition", c'est toujours la mme en-tte HTTP qui sera
cible ;
un split( ";" ), afin de distinguer les diffrents lments constituant la ligne, spars comme vous pouvez le
constater dans l'exemple d'en-tte ci-dessus par un ";" ;
un startsWith( "filename" ), afin de ne slectionner que la chane commenant par filename ;
un substring(), afin de ne finalement slectionner que la valeur associe au paramtre filename, contenue aprs le
caractre "=" .
Avec tous ces dtails, vous devriez comprendre parfaitement comment tout cela s'organise.
Modifions alors notre JSP afin d'afficher les valeurs lues et stockes dans les attributs de requtes description et fichier, que j'ai
mis en place dans notre servlet :
Code : JSP - /WEB-INF/upload.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Envoi de fichier</title>
<link type="text/css" rel="stylesheet" href="form.css">
</head>
<body>
<form action="upload" method="post" enctype="multipart/formdata">
<fieldset>
<legend>Envoi de fichier</legend>
fichier</label>

<label for="description">Description du

<input type="text" id="description"


name="description" value="" />
<span class="succes"><c:out value="${description}" /></span>
<br />
<label for="fichier">Emplacement du fichier <span
class="requis">*</span></label>
<input type="file" id="fichier" name="fichier" />
<span class="succes"><c:out value="${fichier}" /></span>
<br />
<input type="submit" value="Envoyer"
class="sansLabel" />
<br />
</fieldset>
</form>
</body>
</html>

Je ne fais ici que r-afficher le contenu des champs, savoir le texte de description et le titre du fichier slectionn par
l'utilisateur. Je n'ai volontairement pas ajout d'tapes de validation sur ces deux champs, afin de ne pas surcharger le code de ce
chapitre inutilement. Aprs tout, vous savez dj comment procder : il suffit de suivre exactement le mme principe que lorsque

www.siteduzero.com

Partie 4 : Une application interactive !

327/345

nous avions mis en place des validations sur les champs de nos formulaires d'inscription et de connexion dans les chapitres
prcdents.
Nous pouvons dornavant tester notre bauche ! J'ai pour ma part prcis ces donnes dans mon formulaire ( adapter votre
cas selon le fichier que vous allez choisir) :

Exemple de donnes dans le formulaire

Et j'ai obtenu ce rsultat :

Rendu aprs envoi

Pour ceux d'entre vous qui utilisent le navigateur Internet Explorer, vous allez obtenir un rendu sensiblement diffrent :

Rendu aprs

envoi sous IE
Vous constatez que :
le nom du fichier a correctement t extrait, mais est entour de guillemets ;
avec Internet Explorer, le nom du fichier contient en ralit le chemin complet du fichier sur la machine du client...
Nous obtenons ici un bel exemple nous prouvant que la tambouille interne ralise dans certains navigateurs peut
imposer certaines spcificits ! La morale de l'histoire, c'est qu'il est primordial de tester le fonctionnement d'une
application web sous diffrents navigateurs afin d'viter ce genre de problmes d'une plate-forme une autre...

Afin de pallier les diffrents petits soucis que nous venons de rencontrer, nous devons apporter quelques modifications notre
servlet.
Dans le bloc if traitant le champ fichier, pour corriger le bug IE :
Code : Java - com.sdzee.servlets.Upload
/*
* Si la mthode a renvoy quelque chose, il s'agit donc d'un champ
* de type fichier (input type="file").
*/
if ( nomFichier != null && !nomFichier.isEmpty() ) {
String nomChamp = part.getName();
/*
* Antibug pour Internet Explorer, qui transmet pour une raison
* mystique le chemin du fichier local la machine du client...
*
* Ex : C:/dossier/sous-dossier/fichier.ext

www.siteduzero.com

Partie 4 : Une application interactive !

328/345

*
* On doit donc faire en sorte de ne slectionner que le nom et
* l'extension du fichier, et de se dbarrasser du superflu.
*/
nomFichier = nomFichier.substring( nomFichier.lastIndexOf( '/' ) + 1
)
.substring( nomFichier.lastIndexOf( '\\' ) + 1 );
}

request.setAttribute( nomChamp, nomFichier );

Et dans la mthode utilitaire, pour retirer les guillemets superflus :


Code : Java - com.sdzee.servlets.Upload
/*
* Mthode utilitaire qui a pour unique but d'analyser l'en-tte
* "content-disposition", et de vrifier si le paramtre "filename"
y est
* prsent. Si oui, alors le champ trait est de type File et la
mthode
* retourne son nom, sinon il s'agit d'un champ de formulaire
classique et
* la mthode retourne null.
*/
private static String getNomFichier( Part part ) {
/* Boucle sur chacun des paramtres de l'en-tte "contentdisposition". */
for ( String contentDisposition : part.getHeader( "contentdisposition" ).split( ";" ) ) {
/* Recherche de l'ventuelle prsence du paramtre
"filename". */
if ( contentDisposition.trim().startsWith( "filename" ) ) {
/*
* Si "filename" est prsent, alors renvoi de sa valeur,
* c'est--dire du nom de fichier sans guillemets.
*/
return contentDisposition.substring( contentDisposition.indexOf( '='
) + 1 ).trim().replace( "\"", "" );
}
}
/* Et pour terminer, si rien n'a t trouv... */
return null;
}

Je vous laisse analyser ces deux petites corrections par vous-mmes, il s'agit uniquement de bricolages sur les String qui
posaient problme !
Vous pouvez maintenant tester, et vrifier que vous obtenez le rsultat suivant, peu importe le navigateur utilis :

La diffrence entre la thorie et la pratique


Dans le code de notre servlet, j'ai utilis la mthode request.getParameter() pour accder au contenu du champ
description, qui est un simple champ de type texte. Logique ! vous dites-vous, nous avons toujours fait comme a

www.siteduzero.com

Partie 4 : Une application interactive !

329/345

auparavant et il n'y a pas de raisons pour que cela change ! Eh bien dtrompez-vous...
Comme je vous l'annonais dans le court passage sur les moyens mettre en place avec l'API servlet en version 2.x, avant la
version 3.0 un appel la mthode request.getParameter() renvoyait null ds lors que le type des donnes envoyes
par un formulaire tait multipart. Depuis la version 3.0, les spcifications ont chang et nous pouvons maintenant y trouver ce
passage au sujet de l'envoi de fichiers :
Citation : Spcifications de l'API servlet 3.0
For parts with form-data as the Content-Disposition, but without a filename, the string value of the part will also be available
via the getParameter / getParameterValues methods on HttpServletRequest, using the name of the part.
Pour les non-anglophones, ce passage explicite noir sur blanc que lors de la rception de donnes issues d'un formulaire
envoyes avec le type multipart, la mthode request.getParameter() doit pouvoir tre utilise pour rcuprer le
contenu des champs qui ne sont pas des fichiers.
Et alors, o est le problme ? C'est bien ce que nous avons fait ici, n'est-ce pas ?

Le problme est ici relativement sournois. En effet, ce que nous avons fait fonctionne, mais uniquement parce que nous utilisons
le serveur d'applications Tomcat 7 ! Alors qu'habituellement, Tomcat souffre de carences en comparaison ses confrres comme
GlassFish ou JBoss, il se distingue cette fois en respectant la lettre ce passage de la norme.
Par contre, le serveur considr comme LA rfrence des serveurs d'applications Java EE - le serveur GlassFish 3 dvelopp par
Oracle - ne remplissait toujours pas cette fonctionnalit il y a quelques mois de a ! En ralit, il se comportait toujours comme
avec les anciennes versions de l'API, ainsi un appel la mthode request.getParameter() retournait null... C'tait
plutt trange, dans la mesure o cette spcification de l'API servlet date tout de mme de 2009 ! Heureusement, plus de deux
ans aprs la premire sortie de GlassFish en version 3, ce problme qui avait depuis t report comme un bug a finalement t
corrig dans la dernire version 3.1.2 du serveur. Bref,
Vous comprenez maintenant mieux le titre de ce paragraphe : en thorie, tout est cens fonctionner correctement, mais dans la
pratique ce n'est pas encore le cas partout, et selon le serveur que vous utilisez il vous faudra parfois ruser pour parvenir vos
fins.
Du coup, comment faire sur un serveur qui ne respecte pas ce passage de la norme ?

Eh bien dans un tel cas, il va falloir que nous rcuprions nous-mmes le contenu binaire de l'lment Part correspondant au
champ de type texte, et le reconstruire sous forme d'un String. Apptissant n'est-ce pas ?
Les explications qui suivent sont uniquement destines vous donner un moyen de rcuprer les donnes contenues
dans les champs classiques d'un formulaire de type multipart dans une application qui tournerait sur un serveur ne
respectant pas le point des spcifications que nous venons d'tudier. Si vous n'tes pas concerns, autrement dit si le
serveur que vous utilisez ne prsente pas ce bug, vous n'avez pas besoin de mettre en place ces modifications dans
votre code, vous pouvez utiliser simplement request.getParameter() comme nous l'avons fait dans l'exemple
jusqu' prsent.

Ne vous inquitez pas, nous avons dj presque tout mis en place dans notre servlet, les modifications vont tre minimes ! Dans
notre code, nous disposons dj d'une mthode utilitaire getNomfichier() qui nous permet de savoir si un lment Part
concerne un champ de type fichier ou un champ classique. Le seul vrai travail va tre de crer la mthode responsable de la
reconstruction dont je viens de vous parler.
Code : Java - com.sdzee.servlets.Upload
...
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException {
...
for ( Part part : request.getParts() ) {
/*

www.siteduzero.com

Partie 4 : Une application interactive !

330/345

* Pour chaque donne issue de la requte, c'est--dire pour chaque


part, il faut
* dterminer s'il s'agit d'un champ classique ou d'un champ de type
fichier : on
* dlgue cette opration une mthode utilitaire getNomFichier().
*/
String nomFichier = getNomFichier( part );
if ( nomFichier == null ) {
/* La mthode a renvoy null, il s'agit donc d'un champ
classique ici (input type="text|radio|checkbox|etc", select, etc).
*/
String nomChamp = part.getName();
/* Rcupration du contenu du champ l'aide de notre
nouvelle mthode */
String valeurChamp = getValeur( part );
request.setAttribute( nomChamp, valeurChamp );
} else if ( !nomFichier.isEmpty() ) {
/* La mthode a renvoy quelque chose, il s'agit donc
d'un champ de type fichier (input type="file"). */
...
}
...
}
}
/*
* Mthode utilitaire qui a pour unique but de lire l'InputStream
contenu
* dans l'objet part, et de le convertir en une banale chane de
caractres.
*/
private String getValeur( Part part ) throws IOException {
BufferedReader reader = new BufferedReader( new
InputStreamReader( part.getInputStream(), "UTF-8" ) );
StringBuilder valeur = new StringBuilder();
char[] buffer = new char[1024];
int longueur = 0;
while ( ( longueur = reader.read( buffer ) ) > 0 ) {
valeur.append( buffer, 0, longueur );
}
return valeur.toString();
}

La modification importante dans le code de la mthode doPost() est la dcomposition de la vrification du retour de la
mthode getNomFichier() en un if / else if. Si la mthode retourne null, alors nous savons que nous avons
affaire un champ classique, et nous devons alors rcuprer son contenu avec la nouvelle mthode utilitaire getValeur()
que nous venons de mettre en place.
En ce qui concerne la mthode utilitaire en elle-mme, encore une fois c'est du bricolage de flux et de String, rien de bien
passionnant... du pur Java comme on l'aime chez nous !
Cette nouvelle solution n'apporte aucune nouvelle fonctionnalit, mais offre l'avantage d'tre multiplateforme, alors que le code
de notre exemple prcdent ne fonctionnait que sous certains serveurs. Au final, vous voyez que ce n'est pas si tordu, mais c'est
quand mme bien moins intuitif et agrable qu'en utilisant directement la mthode request.getParameter() : il est ici
ncessaire de faire appel la mthode getValeur() sur chaque champ de type texte dont les donnes sont envoyes
travers un formulaire de type multipart. Esprons que les quelques serveurs dapplications qui sont encore la trane comblent
ce manque rapidement, afin que les dveloppeurs comme vous et moi puissent se passer de cette tambouille peu ragoutante.

Enregistrement du fichier
Maintenant que nous sommes capables de rcuprer les donnes envoyes depuis notre formulaire, nous pouvons nous
attaquer la gestion du fichier en elle-mme : la lecture du fichier envoy et son criture sur le disque !

Dfinition du chemin physique


www.siteduzero.com

Partie 4 : Une application interactive !

331/345

Commenons par dfinir un nom de rpertoire physique dans lequel nous allons crire nos fichiers sur le disque. Rappelez-vous,
le chemin que nous avons prcis dans le champ <location> de la section <multipart-config> est uniquement utilis
par l'API servlet pour stocker les fichiers de manire temporaire. Ce chemin ne sera pas rcuprable ailleurs, et donc pas
rutilisable.
Il y a plusieurs solutions possibles ici : nous pouvons nous contenter d'crire en dur le chemin dans une constante directement
au sein de notre servlet, ou encore mettre en place un fichier Properties dans lequel nous prciserons le chemin. Dans notre
exemple, nous allons utiliser un autre moyen : nous allons passer le chemin notre servlet via un paramtre dinitialisation. Si
vous vous souvenez d'un de nos tous premiers chapitres, celui o nous avons dcouvert la servlet, vous devez galement vous
souvenir des options de dclaration d'une servlet dans le fichier web.xml, notamment d'un bloc nomm <init-param>. C'est
celui-ci que nous allons ici mettre en place dans la dclaration de notre servlet d'upload :
Code : XML - /WEB-INF/web.xml
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.sdzee.servlets.Upload</servlet-class>
<init-param>
<param-name>chemin</param-name>
<param-value>/fichiers/</param-value>
</init-param>
<multipart-config>
<location>c:/fichiers</location>
<max-file-size>10485760</max-file-size> <!-- 10 Mo -->
<max-request-size>52428800</max-request-size> <!-- 5 x 10Mo -->
<file-size-threshold>1048576</file-size-threshold> <!-- 1 Mo -->
</multipart-config>
</servlet>

En procdant ainsi, notre servlet va pouvoir accder un paramtre nomm chemin, disponible travers la mthode
getInitParameter() de l'objet ServletConfig !

criture du fichier sur le disque


Reprenons maintenant notre servlet pour y rcuprer ce fameux chemin, et mettre en place proprement l'ouverture des flux dans
une mthode ddie l'criture du fichier :
Code : Java - com.sdzee.servlets.Upload
...
public static final String CHEMIN = "chemin";
public static final int TAILLE_TAMPON = 10240; // 10ko
...
public void doPost( HttpServletRequest request, HttpServletResponse
response ) throws ServletException, IOException {
/*
* Lecture du paramtre 'chemin' pass la servlet via la
dclaration
* dans le web.xml
*/
String chemin = this.getServletConfig().getInitParameter( CHEMIN );
/* Rcupration du contenu du champ de description */
String description = request.getParameter( CHAMP_DESCRIPTION );
request.setAttribute( CHAMP_DESCRIPTION, description );
/*
* Les donnes reues sont multipart, on doit donc utiliser la
mthode
* getParts()
*/

www.siteduzero.com

Partie 4 : Une application interactive !

*
*
*
*
*
*/

332/345

for ( Part part : request.getParts() ) {


/*
Pour chaque donne issue de la requte, c'est--dire pour chaque
fragment contenu dans le retour de la mthode getParts(), il faut
dterminer s'il s'agit d'un champ classique ou d'un champ de type
fichier : on dlgue cette opration la mthode utilitaire
getNomFichier().
String nomFichier = getNomFichier( part );

/*
* Si la mthode a renvoy quelque chose, il s'agit donc d'un champ
* de type fichier (input type="file").
*/
if ( nomFichier != null && !nomFichier.isEmpty() ) {
String nomChamp = part.getName();
/*
* Antibug pour Internet Explorer, qui transmet pour une raison
* mystique le chemin du fichier local la machine du client...
*
* Ex : C:/dossier/sous-dossier/fichier.ext
*
* On doit donc faire en sorte de ne slectionner que le nom et
* l'extension du fichier, et de se dbarrasser du superflu.
*/
nomFichier = nomFichier.substring(
nomFichier.lastIndexOf( '/' ) + 1 )
.substring( nomFichier.lastIndexOf( '\\' ) + 1
);
/* Ecriture du fichier sur le disque */
ecrireFichier( part, nomFichier, chemin );

request.setAttribute( nomChamp, nomFichier );

this.getServletContext().getRequestDispatcher( VUE ).forward(


request, response );
}
...
/*
* Mthode utilitaire qui a pour but d'crire le fichier pass en
paramtre
* sur le disque, dans le rpertoire donn et avec le nom donn.
*/
private void ecrireFichier( Part part, String nomFichier, String
chemin ) throws IOException {
/* Prpare les flux. */
BufferedInputStream entree = null;
BufferedOutputStream sortie = null;
try {
/* Ouvre les flux. */
entree = new BufferedInputStream( part.getInputStream(),
TAILLE_TAMPON );
sortie = new BufferedOutputStream( new FileOutputStream( new File(
chemin + nomFichier ) ),
TAILLE_TAMPON );
/* ... */
} finally {
sortie.close();
entree.close();
}
}

www.siteduzero.com

Partie 4 : Une application interactive !

333/345

Nous pourrions ici trs bien utiliser directement les flux de type InputStream et FileOutputStream, mais les objets
BufferedInputStream et BufferedOutputStream permettent via l'utilisation d'une mmoire tampon une gestion plus
souple de la mmoire disponible sur le serveur :
dans le flux entree, il nous suffit de rcuprer le flux directement depuis la mthode getInputStream() de l'objet
Part. Nous dcorons ensuite ce flux avec un BufferedInputStream, avec ici dans l'exemple un tampon de 10ko.
dans le flux sortie, nous devons mettre en place un fichier sur le disque, en vue d'y crire ensuite le contenu de l'entre.
Nous dcorons ensuite ce flux avec un BufferedOutputStream, avec ici dans l'exemple un tampon de 10ko.
Si j'ai pris la peine de vous dtailler l'ouverture des flux, c'est pour que vous remarquiez ici la bonne pratique mise en
place, que je vous recommande de suivre ds lors que vous manipulez des flux : toujours ouvrir les flux dans un bloc
try, et les fermer dans le bloc finally associ. Ainsi, nous nous assurons que quoi qu'il arrive, la fermeture de nos
flux sera bien effectue !
Note propos du chemin utilis : il reprsente le rpertoire du disque local sur lequel les fichiers vont tre crits. Par
exemple, si votre serveur tourne sur le disque C:\ d'une machine sous Windows, alors le chemin /fichiers/ fera
rfrence au rpertoire C:\fichiers\. Ainsi, contrairement au champ <location> abord un peu plus tt dans lequel
vous deviez crire un chemin complet, vous pouvez ici spcifier un chemin relatif au systme. Mme remarque
toutefois, vous devez vous assurer que ce rpertoire existe, sinon Tomcat enverra une java.io.IOException lors
de la tentative d'criture sur le disque.

Ceci fait, il ne nous reste plus qu' mettre en place le tampon et crire notre fichier sur le disque. La mthode complte :
Code : Java - com.sdzee.servlets.Upload
/*
* Mthode utilitaire qui a pour but d'crire le fichier pass en
paramtre
* sur le disque, dans le rpertoire donn et avec le nom donn.
*/
private void ecrireFichier( Part part, String nomFichier, String
chemin ) throws IOException {
/* Prpare les flux. */
BufferedInputStream entree = null;
BufferedOutputStream sortie = null;
try {
/* Ouvre les flux. */
entree = new BufferedInputStream( part.getInputStream(),
TAILLE_TAMPON );
sortie = new BufferedOutputStream( new FileOutputStream( new
File( chemin + nomFichier ) ),
TAILLE_TAMPON );
/*
* Lit le fichier reu et crit son contenu dans un fichier sur le
* disque.
*/
byte[] tampon = new byte[TAILLE_TAMPON];
int longueur;
while ( ( longueur = entree.read( tampon ) ) > 0 ) {
sortie.write( tampon, 0, longueur );
}
} finally {
sortie.close();
entree.close();
}
}

l'aide d'un tableau d'octets jouant le rle de tampon, la boucle ici mise en place parcourt le contenu du fichier reu et l'crit
morceau par morceau dans le fichier cr sur le disque. Si vous n'tes pas familier avec la manipulation de fichiers en Java, ou si
vous avez oubli comment cela fonctionne, vous pouvez jeter un oeil ce chapitre du cours de Java.

www.siteduzero.com

Partie 4 : Une application interactive !

334/345

Test du formulaire d'upload


Il ne nous reste maintenant plus qu' vrifier que tout se droule correctement.
Avec la configuration mise en place sur mon poste, fonctionnant sous Windows et Tomcat tournant sur le disque C:\, si je
reprends les mmes donnes que dans les exemples prcdents :

Alors aprs validation, le rpertoire C:\fichiers de mon disque contient bien une copie du fichier eclipse.ini :

a y est, vous tes maintenant capables de rcuprer des fichiers envoys par vos utilisateurs !

Problmes et limites
Tout cela semble bien joli, mais nous allons un peu vite en besogne. En effet, plusieurs problmatiques importantes se posent
avec la solution mise en place :
1. nous ne grons pas les fichiers de mme nom ;
2. nous ne savons pas viter les doublons ;
3. nous n'avons pas rflchi l'endroit choisi pour le stockage.

Comment grer les fichiers de mme noms ?


Le plus simple, c'est de toujours renommer les fichiers reus avant de les enregistrer sur le disque. Tout un tas de solutions, que
vous pouvez combiner, s'offrent alors vous :
ajouter un suffixe votre fichier si un fichier du mme nom existe dj sur le disque ;
placer vos fichiers dans des rpertoires diffrents selon leur type ou leur extension ;
renommer, prfixer ou suffixer vos fichiers par un timestamp ;
vous baser sur un hashCode du contenu binaire du fichier pour gnrer une arborescence et un nom uniques ;
etc.
vous de dfinir quelle(s) solution(s) convien(nen)t le mieux aux contraintes de votre projet.

Comment viter les doublons ?


L, il s'agit plus d'une optimisation que d'un rel problme. Mais effectivement, si votre application est voue tre massivement
utilise, vous pourriez ventuellement juger intressant d'conomiser un peu d'espace disque sur votre serveur en ne
renregistrant pas un fichier qui existe dj sur le disque. Autrement dit, faire en sorte que si un utilisateur envoie un fichier
qu'un autre utilisateur a dj envoy par le pass, votre application sache le reconnatre rapidement et agir en consquence.

www.siteduzero.com

Partie 4 : Une application interactive !

335/345

Comme vous devez vous en douter, c'est un travail un peu plus ardu que la simple gestion des fichiers de mmes noms que nous
venons d'aborder. Toutefois, une des solutions prcdentes peut convenir : en vous basant sur un hashCode du contenu binaire
du fichier pour gnrer une arborescence et un nom uniques, vous pouvez ainsi la fois vous affranchir du nom que l'utilisateur
a donn son fichier, et vous assurer qu'un contenu identique ne sera pas dupliqu deux endroits diffrents sur votre disque.
Exemple :
1.
2.
3.
4.

un utilisateur envoie un fichier nomm pastque.jpg ;


votre application le reoit, et gnre un hashCode bas sur son contenu, par exemple a8cb45e3d6f1dd5e ;
elle stocke alors le fichier dans l'arborescence /a8cb/45e3/d6f1/dd5e.jpg, construite partir du hashCode ;
un autre utilisateur envoie plus tard un fichier nomm watermelon.jpg, dont le contenu est exactement identique au
prcdent fichier ;
5. votre application le reoit, et gnre alors le mme hashCode que prcdemment, puisque le contenu est identique ;
6. elle se rend alors compte que l'arborescence /a8cb/45e3/d6f1/dd5e.jpg existe dj, et saute l'tape d'criture sur le disque.
Alors bien videmment cela demande un peu de rflexion et d'ajustements. Il faudrait en effet gnrer un hashCode qui soit
absolument unique : si deux contenus diffrents peuvent conduire au mme hashCode, alors ce systme ne fonctionne plus !
Mais c'est une piste srieuse, qui peut si elle est bien dveloppe remplir la mission sans accrocs.

O stocker les fichiers reus ?


C'est en effet une bonne question, qui mrite qu'on s'y attarde un instant. A priori, deux possibilits s'offrent nous :
stocker les fichiers au sein de l'application web, dans un sous-rpertoire du dossier WebContent d'Eclipse par exemple ;
stocker les fichiers en dehors de l'application, dans un rpertoire du disque local.
Vous avez ici aveuglment suivi mes consignes, et ainsi implment la seconde option. En effet, dans l'exemple j'ai bien enregistr
le fichier dans un rpertoire plac la racine de mon disque local. Mais vous devez vous rendre compte que cette solution peut
poser un problme important : tous les fichiers placs en dehors de l'application, un peu la manire des fichiers placs sous son
rpertoire /WEB-INF, sont inaccessibles via une simple URL. Autrement dit, vous ne pourrez pas proposer aux utilisateurs de
tlcharger ces fichiers !
Dans ce cas, pourquoi ne pas avoir opt pour la premire solution ?

Eh bien tout simplement parce que si elle a l'avantage de pouvoir rendre disponibles les fichiers directement aux utilisateurs, elle
prsente un autre inconvnient : en stockant les fichiers directement dans votre conteneur, vous les rendez vulnrables un
crasement lors d'un prochain redmarrage serveur ou d'un prochain redploiement de l'application.
Mais alors, comment faire pour rendre ces fichiers externes disponibles au tlchargement ?

La rponse cette question ncessite un peu de code et d'explications, et vous attend dans le chapitre suivant !

Rendre le tout entirement automatique


Dans le cas d'un petit formulaire comme celui de notre exemple, tout va bien. Nous sommes l pour apprendre, nous avons le
temps de perdre notre temps (
) dvelopper des mthodes utilitaires et rflchir des solutions adaptes. Mais dans une
vraie application, des formulaires qui contiennent des champs de type fichier, vous risquez d'en rencontrer plus d'un ! Et vous
allez vite dchanter quand vous aurez crer toutes les servlets responsables des traitements...
L'idal, a serait de pouvoir continuer utiliser les mthodes request.getParameter() comme si de rien n'tait ! Eh bien
pour cela, pas de miracle, il faut mettre en place un filtre qui va se charger d'effectuer les vrifications et conversions ncessaires,
et qui va rendre disponible le contenu des fichiers simplement. C'est un travail consquent et plutt difficile. Plutt que de vous
faire coder le tout partir de zro, je vais vous laisser admirer la superbe classe prsente dans cet excellent article. C'est en
anglais, mais le code est extrmement clair et professionnel, essayez d'y jeter un oeil et de le comprendre.

Intgration dans MVC


Nous avons dj fourni beaucoup d'efforts, mais il nous reste encore une tape importante franchir : nous devons encore
intgrer ce que nous venons de mettre en place dans notre architecture MVC. Nous l'avons dj fait avec le formulaire

www.siteduzero.com

Partie 4 : Une application interactive !

336/345

dinscription et de connexion, vous devez commencer tre habitus ! Il va nous falloir :


crer un bean reprsentant les donnes manipules, en l'occurrence il s'agit d'un fichier et de sa description ;
crer un objet mtier qui regroupe les traitements jusqu' prsent raliss dans la servlet ;
en profiter pour y ajouter des mthodes de validation de la description et du fichier, et ainsi permettre une gestion fine
des erreurs et exceptions ;
reprendre la servlet pour l'adapter aux objets du modle frachement crs ;
modifier la page JSP pour qu'elle rcupre les nouvelles informations qui lui seront transmises.
Le plus gros du travail va se situer dans l'objet mtier responsable des traitements et validations. C'est l que nous allons devoir
rflchir un petit peu, afin de trouver un moyen efficace pour grer toutes les exceptions possibles lors de la rception de
donnes issues de notre formulaire. Sans plus attendre, voici les codes comments et expliqus...

Cration du bean reprsentant un fichier


Commenons par le plus simple. Un fichier tant reprsent par son nom et sa description, nous avons uniquement besoin d'un
bean que nous allons nommer Fichier, qui contiendra deux proprits et que nous allons placer comme ses confrres dans le
package com.sdzee.beans :
Code : Java - com.sdzee.beans.Fichier
package com.sdzee.beans;
public class Fichier {
private String description;
private String nom;
public String getDescription() {
return description;
}
public void setDescription( String description ) {
this.description = description;
}
public String getNom() {
return nom;
}

public void setNom( String nom ) {


this.nom = nom;
}

Jusque l, a va...

Cration de l'objet mtier en charge du traitement du formulaire


Arrivs l, les choses se compliquent un peu pour nous :
pour assurer la validation des champs, nous allons simplement vrifier que le champ description est renseign et qu'il
contient au moins 15 caractres, et nous allons vrifier que le champ fichier existe bien et contient bien des donnes ;
pour assurer la gestion des erreurs, nous allons comme pour nos systme d'inscription et de connexion nous baser sur le
mme principe : nous allons initialiser une Map d'erreurs et une chane contenant le rsultat final du processus.
La difficult va ici trouver sa source dans la gestion des ventuelles erreurs qui peuvent survenir. la diffrence de simples
champs texte, la manipulation d'un fichier fait intervenir beaucoup de composants diffrents, chacun pouvant causer des
exceptions bien particulires. Je vous donne le code pour commencer, celui de l'objet mtier UploadForm plac dans le package
com.sdzee.forms, et nous en reparlons ensuite. Ne paniquez pas s'il vous semble massif, plus de la moiti des lignes sont

www.siteduzero.com

Partie 4 : Une application interactive !

337/345

des commentaires destins vous en faciliter la comprhension !


Code : Java - com.sdzee.forms.UploadForm
package com.sdzee.forms;
import
import
import
import
import
import
import
import

java.io.BufferedInputStream;
java.io.BufferedOutputStream;
java.io.File;
java.io.FileOutputStream;
java.io.IOException;
java.io.InputStream;
java.util.HashMap;
java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import com.sdzee.beans.Fichier;
public final class
private static
private static
private static
// 10ko

UploadForm {
final String CHAMP_DESCRIPTION = "description";
final String CHAMP_FICHIER
= "fichier";
final int
TAILLE_TAMPON
= 10240;

private String
resultat;
private Map<String, String> erreurs
HashMap<String, String>();

= new

public String getResultat() {


return resultat;
}
public Map<String, String> getErreurs() {
return erreurs;
}
public Fichier enregistrerFichier( HttpServletRequest request,
String chemin ) {
/* Initialisation du bean reprsentant un fichier */
Fichier fichier = new Fichier();
/* Rcupration du champs de description du formulaire */
String description = getValeurChamp( request,
CHAMP_DESCRIPTION );
/*
* Rcupration du contenu du champ fichier du formulaire. Il faut
ici
* utiliser la mthode getPars(), comme nous l'avions fait dans
notre
* servlet auparavant.
*/
String nomFichier = null;
InputStream contenuFichier = null;
try {
for ( Part part : request.getParts() ) {
/*
* Pour chaque donne issue de la requte, c'est--dire pour
* chaque fragment contenu dans le retour de la mthode
* getParts(), il faut dterminer s'il s'agit d'un champ
* classique ou d'un champ de type fichier : on dlgue cette
* opration la mthode utilitaire getNomFichier().
*/
nomFichier = getNomFichier( part );
/*

www.siteduzero.com

Partie 4 : Une application interactive !

338/345

* Si la mthode a renvoy quelque chose, il s'agit donc d'un


* champ de type fichier (input type="file").
*/
if ( nomFichier != null && !nomFichier.isEmpty() ) {
/*
* Antibug pour Internet Explorer, qui transmet pour une
* raison mystique le chemin du fichier local la machine
* du client...
*
* Ex : C:/dossier/sous-dossier/fichier.ext
*
* On doit donc faire en sorte de ne slectionner que le nom
* et l'extension du fichier, et de se dbarrasser du
* superflu.
*/
nomFichier = nomFichier.substring(
nomFichier.lastIndexOf( '/' ) + 1 )
.substring( nomFichier.lastIndexOf( '\\'
) + 1 );
/* Rcupration du contenu du fichier */
contenuFichier = part.getInputStream();
}
}
} catch ( IllegalStateException e ) {
/*
* Exception retourne si la taille des donnes dpasse les limites
* dfinies dans la section <multipart-config> de la dclaration de
* notre servlet d'upload dans le fichier web.xml
*/
setErreur( CHAMP_FICHIER, "Les donnes envoyes sont
trop volumineuses." );
} catch ( IOException e ) {
/*
* Exception retourne si une erreur au niveau des rpertoires de
* stockage survient (rpertoire inexistant, droits d'accs
* insuffisants, etc.)
*/
setErreur( CHAMP_FICHIER, "Erreur de configuration du
serveur." );
} catch ( ServletException e ) {
/*
* Exception retourne si la requte n'est pas de type
* multipart/form-data. Cela ne peut arriver que si l'utilisateur
* essaie de contacter la servlet d'upload par un formulaire
* diffrent de celui qu'on lui propose... pirate ! :|
*/
setErreur( CHAMP_FICHIER,
"Ce type de requte n'est pas support, merci
d'utiliser le formulaire prvu pour envoyer votre fichier." );
}
/* Si aucune erreur n'est survenue jusqu' prsent */
if ( erreurs.isEmpty() ) {
/* Validation du champ de description. */
try {
validationDescription( description );
} catch ( Exception e ) {
setErreur( CHAMP_DESCRIPTION, e.getMessage() );
}
fichier.setDescription( description );
/* Validation du champ fichier. */
try {
validationFichier( nomFichier, contenuFichier );
} catch ( Exception e ) {
setErreur( CHAMP_FICHIER, e.getMessage() );
}
fichier.setNom( nomFichier );

www.siteduzero.com

Partie 4 : Une application interactive !

339/345

}
/* Si aucune erreur n'est survenue jusqu' prsent */
if ( erreurs.isEmpty() ) {
/* Ecriture du fichier sur le disque */
try {
ecrireFichier( contenuFichier, nomFichier, chemin );
} catch ( Exception e ) {
setErreur( CHAMP_FICHIER, "Erreur lors de l'criture
du fichier sur le disque." );
}
}
/* Initialisation du rsultat global de la validation. */
if ( erreurs.isEmpty() ) {
resultat = "Succs de l'envoi du fichier.";
} else {
resultat = "Echec de l'envoi du fichier.";
}
}

return fichier;

/*
* Valide la description saisie.
*/
private void validationDescription( String description ) throws
Exception {
if ( description != null ) {
if ( description.length() < 15 ) {
throw new Exception( "La phrase de description du
fichier doit contenir au moins 15 caractres." );
}
} else {
throw new Exception( "Merci d'entrer une phrase de
description du fichier." );
}
}
/*
* Valide le fichier envoy.
*/
private void validationFichier( String nomFichier, InputStream
contenuFichier ) throws Exception {
if ( nomFichier == null || contenuFichier == null ) {
throw new Exception( "Merci de slectionner un fichier
envoyer." );
}
}
/*
* Ajoute un message correspondant au champ spcifi la map des
erreurs.
*/
private void setErreur( String champ, String message ) {
erreurs.put( champ, message );
}
/*
* Mthode utilitaire qui retourne null si un champ est vide, et son
contenu
* sinon.
*/
private static String getValeurChamp( HttpServletRequest
request, String nomChamp ) {
String valeur = request.getParameter( nomChamp );
if ( valeur == null || valeur.trim().length() == 0 ) {
return null;
} else {
return valeur;

www.siteduzero.com

Partie 4 : Une application interactive !


}

340/345

/*
* Mthode utilitaire qui a pour unique but d'analyser l'en-tte
* "content-disposition", et de vrifier si le paramtre "filename"
y est
* prsent. Si oui, alors le champ trait est de type File et la
mthode
* retourne son nom, sinon il s'agit d'un champ de formulaire
classique et
* la mthode retourne null.
*/
private static String getNomFichier( Part part ) {
/* Boucle sur chacun des paramtres de l'en-tte "contentdisposition". */
for ( String contentDisposition : part.getHeader( "contentdisposition" ).split( ";" ) ) {
/* Recherche de l'ventuelle prsence du paramtre
"filename". */
if ( contentDisposition.trim().startsWith( "filename" )
) {
/*
* Si "filename" est prsent, alors renvoi de sa valeur,
* c'est--dire du nom de fichier sans guillemets.
*/
return contentDisposition.substring(
contentDisposition.indexOf( '=' ) + 1 ).trim().replace( "\"", "" );
}
}
/* Et pour terminer, si rien n'a t trouv... */
return null;
}
/*
* Mthode utilitaire qui a pour but d'crire le fichier pass en
paramtre
* sur le disque, dans le rpertoire donn et avec le nom donn.
*/
private void ecrireFichier( InputStream contenu, String
nomFichier, String chemin ) throws Exception {
/* Prpare les flux. */
BufferedInputStream entree = null;
BufferedOutputStream sortie = null;
try {
/* Ouvre les flux. */
entree = new BufferedInputStream( contenu, TAILLE_TAMPON
);
sortie = new BufferedOutputStream( new FileOutputStream(
new File( chemin + nomFichier ) ),
TAILLE_TAMPON );
/*
* Lit le fichier reu et crit son contenu dans un fichier sur le
* disque.
*/
byte[] tampon = new byte[TAILLE_TAMPON];
int longueur = 0;
while ( ( longueur = entree.read( tampon ) ) > 0 ) {
sortie.write( tampon, 0, longueur );
}
} finally {
sortie.close();
entree.close();
}
}
}

www.siteduzero.com

Partie 4 : Une application interactive !

341/345

Sans surprises, dans ce code vous retrouvez bien :


les mthodes utilitaires ecrireFichier() et getNomFichier(), que nous avions dveloppes dans notre
servlet ;
l'analyse des lments de type Part que nous avions mise en place l encore dans notre servlet, pour retrouver le
champ contenant le fichier ;
l'architecture que nous avions mise en place dans nos anciens objets mtiers dans les systmes d'inscription et de
connexion. Notamment la Map erreurs, la chane resultat, les mthodes getValeurChamp() et setErreur(),
ainsi que la grosse mthode centrale ici nomme enregistrerFichier(), qui correspond la mthode appele
depuis la servlet pour effectuer les traitements.
Comme vous pouvez le constater, la seule diffrence notoire est le nombre de blocs try / catch qui interviennent, et le
nombre de vrifications de la prsence d'erreurs. propos, je ne me suis pas amus vrifier trois fois de suites - aux lignes 109,
128 et 138 - si des erreurs avaient eu lieu au cours du processus ou non. C'est simplement afin d'viter de continuer inutilement le
processus de validation si des problmes surviennent lors des traitements prcdents, et galement afin de pouvoir renvoyer un
message d'erreur prcis l'utilisateur.
Enfin, vous remarquerez pour finir que j'ai modifi lgrement la mthode utilitaire ecrireFichier(), et que je lui passe
dsormais le contenu de type InputStream renvoy par la mthode part.getInputStream(), et non plus directement
l'lment Part. En procdant ainsi je peux m'assurer, en amont de la demande d'criture sur le disque, si le contenu existe et est
bien manipulable par notre mthode utilitaire.

Reprise de la servlet
C'est ici un petit travail de simplification, nous devons nettoyer le code de notre servlet pour qu'elle remplisse uniquement un
rle d'aiguilleur :
Code : Java - com.sdzee.servlets.Upload
package com.sdzee.servlets;
import java.io.IOException;
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import com.sdzee.beans.Fichier;
import com.sdzee.forms.UploadForm;
public class Upload extends HttpServlet {
public static final String CHEMIN

= "chemin";

public static final String ATT_FICHIER = "fichier";


public static final String ATT_FORM
= "form";
public static final String VUE

= "/WEB-INF/upload.jsp";

public void doGet( HttpServletRequest request,


HttpServletResponse response ) throws ServletException, IOException
{
/* Affichage de la page d'upload */
this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
public void doPost( HttpServletRequest request,
HttpServletResponse response ) throws ServletException, IOException
{
/*
* Lecture du paramtre 'chemin' pass la servlet via la
dclaration
* dans le web.xml
*/

www.siteduzero.com

Partie 4 : Une application interactive !

342/345

String chemin = this.getServletConfig().getInitParameter(


CHEMIN );
/* Prparation de l'objet formulaire */
UploadForm form = new UploadForm();
/* Traitement de la requte et rcupration du bean en
rsultant */
Fichier fichier = form.enregistrerFichier( request, chemin );
/* Stockage du formulaire et du bean dans l'objet request
*/
request.setAttribute( ATT_FORM, form );
request.setAttribute( ATT_FICHIER, fichier );
this.getServletContext().getRequestDispatcher( VUE
).forward( request, response );
}
}

L'unique diffrence avec les anciennes servlets d'inscription et de connexion se situe dans l'appel la mthode centrale de l'objet
mtier. Cette fois, nous devons lui passer un argument supplmentaire en plus de l'objet request : le chemin physique de
stockage des fichiers sur le disque local, que nous rcuprons - souvenez-vous - via le paramtre dinitialisation dfini dans le
bloc <init-param> de la dclaration de la servlet.

Adaptation de la page JSP aux nouvelles informations transmises


Pour terminer, il faut modifier lgrement le formulaire pour qu'il affiche les erreurs que nous grons dornavant grce notre
objet mtier. Vous connaissez le principe, cela reprend l encore les mmes concepts que ceux que nous avions mis en place dans
nos systmes d'inscription et de connexion :
Code : JSP - /WEB-INF/upload.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Envoi de fichier</title>
<link type="text/css" rel="stylesheet" href="<c:url
value="/inc/form.css"/>" />
</head>
<body>
<form action="<c:url value="/upload" />" method="post"
enctype="multipart/form-data">
<fieldset>
<legend>Envoi de fichier</legend>
<label for="description">Description du
fichier</label>
<input type="text" id="description" name="description" value="<c:out
value="${fichier.description}"/>" />
<span class="erreur">${form.erreurs['description']}</span>
<br />
<label for="fichier">Emplacement du fichier <span
class="requis">*</span></label>
<input type="file" id="fichier" name="fichier" value="<c:out
value="${fichier.nom}"/>" />
<span class="erreur">${form.erreurs['fichier']}</span>
<br />
<input type="submit" value="Envoyer"

www.siteduzero.com

Partie 4 : Une application interactive !

343/345

class="sansLabel" />
<br />
<p class="${empty form.erreurs ? 'succes' :
'erreur'}">${form.resultat}</p>
</fieldset>
</form>
</body>
</html>

Comportement de la solution finale


Vous pouvez maintenant tester votre formulaire sous toutes ses coutures : envoyez des champs vides ou mal renseigns,
n'envoyez qu'un champ sur deux, envoyez un fichier trop gros, configurez votre servlet pour qu'elle enregistre les fichiers dans
un dossier qui n'existe pas sur votre disque, etc.
Dans le dsordre, voici un aperu de quelques rendus que vous devriez obtenir dans diffrents cas d'checs :

Envoi sans description ni fichier

Envoi d'un fichier trop lourd

Envoi avec une description trop courte et pas de fichier

Ne prenez pas cett