JSP Javaserver Pages
JSP Javaserver Pages
JSP Javaserver Pages
JavaServer
Pages
Duane Fields
Éditions Eyrolles
ISBN : 2-212-09228-8
2000
5
Les pages JSP :
une approche orientée
composants
Dans ce chapitre :
• Le modèle JSP basé sur les composants
• Concepts de base des composants JavaBeans
• Interaction avec les composants depuis une page JSP
Les scriptlets et les expressions JSP permettent aux développeurs d’ajouter des éléments
dynamiques aux pages web en intercalant du code Java dans des pages HTML. Bien que ce
soit une approche très probante pour les programmeurs Java qui souhaitent créer des applica-
tions web et des sites attractifs, on peut néanmoins y observer une absence de séparation claire
entre la présentation et l’implémentation. En outre, elle nécessite de la part du développeur
une maîtrise parfaite du langage de programmation Java. Les JSP, hormis les scripts, fournis-
sent une autre approche centrée sur les composants pour la conception de pages dynamiques.
Cette dernière permet aux développeurs d’interagir avec des composants Java, non seulement
via du code Java, mais également en utilisant des balises de style HTML. Cette approche a
pour autre avantage de faciliter le partage clair du travail entre les développeurs d’application
et ceux qui s’occupent du contenu web.
Figure 5-1
Une application Interface Module
basée sur utilisateur de Composant
du guichet gestion d'accès à la
les composants Base de
automatique des base de
données
comptes données
Les composants sont donc des éléments logiciels réutilisables qui peuvent être reliés pour
construire une application. Un bon modèle de composants minimise le travail de codage des
relations entre les différents éléments de l’application. Le principe des architectures de
composants consiste à utiliser une interface commune pour manipuler des objets avec des
outils de développement, la seule nécessité qui incombe à l’outil étant de prendre en charge
l’interface.
ainsi remplacer cet appareil par un nouveau modèle plus performant, et ce sans qu’il doive
reconstruire toute la maison. La normalisation des environnements et des méthodes de
conception a permis d’obtenir des systèmes souples, faciles à maintenir. Les composants logi-
ciels ont été conçus pour opérer dans ces environnements spécifiques. L’existence de règles
prédéfinies qui régissent leur interaction avec les autres composants augmente d’autant leur
interchangeabilité.
Développement de composants
En général, une application basée sur des composants fait intervenir une combinaison de
composants génériques et de composants spécifiques aux besoins de l’application. Les avan-
tages de la réutilisation des composants se font sentir, non seulement parce que différentes
applications peuvent partager des composants, mais également parce qu’ils peuvent être réuti-
lisés, par la même application ou par des applications différentes.
Considérons par exemple une application bancaire qui compte plusieurs interfaces client, un
module d’accès aux employés et une console d’administration. Chacun de ces modules peut
recourir à un même composant, commun, pour accéder à toutes les données nécessaires à
l’affichage d’un compte bancaire. Si ce composant est suffisamment bien conçu, avec toute
l’anticipation nécessaire, il peut être développé de façon à servir dans toute application de
gestion financière.
Une fois que le composant est conçu, son concepteur peut dans une certaine mesure en modi-
fier le fonctionnement interne sans qu’il doive en prévenir tous ses utilisateurs. Pour parvenir
à un tel niveau d’abstraction, il faut définir une interface qui protège l’application des détails
d’implémentation du composant.
Figure 5-2
Partage des efforts Domaine des développeurs Java
dans le développement
d’applications web
Présentation Logique
des données applicative
Accès aux
données Base de
données
Domaine des
concepteurs web
pose certains problèmes pour des applications telles que celle dont on traite. L’intégration
directe de scripts JSP fait que les codes de conception de page HTML et de logique applica-
tive se mélangent. Tant les concepteurs web que les développeurs applicatifs devront
comprendre par le menu détail les autres parties du projet. Dans ce cas, soit on confie aux
développeurs une tâche d’implémentation réduite à l’essentiel, en demandant alors aux desi-
gners de la peaufiner, soit on demande aux designers de développer de jolis formats de pages,
mais qui ne contiennent pas la logique de l’application, pour ensuite laisser le soin aux déve-
loppeurs de s’occuper du code qui permette de calculer le prix des taxes et de la livraison.
Aucune de ces deux solutions n’est satisfaisante en termes de partage équitable des efforts.
Le problème que pose cette approche apparaît clairement lorsqu’on aborde les questions du
déploiement et des mises à jour éventuelles de l’application. Par exemple, que se passe-t-il si
l’application de ventes sur catalogue développée initialement pour un seul site doit être élargie
(pour cause de succès) à l’ensemble des vingt-huit filiales de la société. Bien entendu, les
taxes diffèrent d’une filiale à une autre. Il faut alors faire vingt-huit copies de la page et trouver
un développeur qui en connaît bien le code pour modifier les scripts JSP. Ensuite, il faut que
les développeurs web modifient le code HTML de chaque page pour faire les adaptations
nécessaires dans chaque filiale et régler les problèmes liés à la marque. Tout au long du cycle
de vie de l’application, il faut donc « bricoler » les calculs, repérer les bogues, augmenter les
délais de livraison, mettre à jour le design et ajouter de nouvelles fonctionnalités. Et ce pour
chacune des vingt-huit versions du code.
Voilà pourquoi on privilégiera l’approche par composants pour développer une application web.
Les pages JSP offrent justement la possibilité d’utiliser des composants dans des pages HTML.
En l’occurrence, on développera des composants pour calculer le montant des taxes et des frais
de livraison, configurables à l’exécution avec des paramètres tels que le taux des taxes locales.
Ces composants serviront alors de base aux développeurs de pages web, sans que ceux-ci aient
à faire appel aux autres développeurs pour modifier le code HTML ou créer une nouvelle
version de la page. Réciproquement, les découvertes de bogues ou les mises à jour du côté
applicatif peuvent se faire indépendamment, sans conséquences sur les activités des concep-
teurs de pages web. Voyons maintenant comment les composants s’intègrent dans les pages JSP,
et plus précisément comment les JSP intègrent le modèle des composants JavaBeans.
d’accéder à leurs données et à leurs méthodes. Les applications qui se servent directement des
composants JavaBeans sont exclusivement écrites en Java mais les conteneurs permettent de
les utiliser à des niveaux conceptuels plus élevés. Pour cela, les composants JavaBeans expo-
sent leurs fonctionnalités et leur comportement au conteneur. Le développeur peut ainsi les
manipuler d’une façon plus intuitive. Le conteneur JavaBeans définit ses propres critères de
présentation et d’interaction avec le composant et écrit lui-même le code Java qui en résulte.
Si vous avez déjà utilisé les outils visuels Bean Box de Sun, Visual Age pour Java d’IBM,
Visual Café de WebGain ou d’autres outils de développement Java, vous avez donc déjà mani-
pulé des composants. Ces ateliers de développement fonctionnent avec des conteneurs Java-
Beans qui permettent de manipuler visuellement les composants. Ainsi peut-on par le simple
déplacement d’icônes définir les caractéristiques des composants Java, leur comportement,
leur lien avec d’autres objets, et bâtir une application entière. L’application ainsi définie
génère tout le code Java nécessaire. Les conteneurs de JSP, d’une façon similaire, permettent
aux développeurs de créer des applications Java basées sur le web sans récriture de code Java.
L’interaction avec les composants dans les JSP se fait par l’intermédiaire de balises qui
peuvent se mêler à du code HTML classique.
d’une région dont on souhaite connaître la météo, il serait normal de permettre aux déve-
loppeurs de le spécifier. Une telle propriété serait accessible en lecture/écriture.
REMARQUE Les composants JavaBeans sont en fait de simples objets Java, comme cela sera détaillé au chapitre 6.
Les propriétés d’un composant JavaBeans sont reliées à des méthodes d’un objet Java qui gère son état.
Par conséquent, lorsqu’on initialise la propriété d’un JavaBeans, c’est comme si on faisait un raccourci
pour l’appel des méthodes des objets à travers Java. De même, visualiser la valeur courante d’une
propriété d’un JavaBeans revient pour l’essentiel à un appel d’une méthode d’un objet qui retourne cette
valeur comme résultat. On verra au chapitre suivant comment faire correspondre les méthodes d’un objet
Java et les propriétés d’un JavaBeans.
Les feuilles de propriétés permettent aux concepteurs de JavaBeans de décrire les caractéris-
tiques d’un composant à l’intention des utilisateurs, tels que les développeurs de JSP, les
programmeurs de servlets, etc. Le développeur peut, à partir d’une telle feuille, déterminer
quel type d’information le JavaBeans peut contenir et quel type de comportement il offre.
Bien entendu, la feuille peut ne pas suffire pour bien expliquer à un utilisateur le comporte-
ment du JavaBeans. Dans ce cas, des informations supplémentaires sont disponibles dans la
documentation qui est dédiée au composant.
le comportement du JavaBeans, pour ensuite lire les résultats de la requête via d’autres
propriétés. Par exemple, un JavaBeans conçu pour accéder à une base de données qui
comporte les numéros de téléphone des employés pourrait avoir une propriété appelée
employee à laquelle on attribuera comme valeur le nom de l’employé dont on souhaite
connaître le numéro de téléphone. L’initialisation de cette propriété déclenche une recherche
dans la base de données et attribue des valeurs aux propriétés phone et email du JavaBeans
correspondant aux informations demandées.
Tous les JavaBeans de services ne vont pas rechercher des informations sur un serveur.
Certains renferment simplement la logique nécessaire pour effectuer des calculs, des conver-
sions ou des opérations. Par exemple, un composant StatistiquesBean pourrait calculer des
moyennes, des valeurs médianes et des écarts types, tandis qu’un composant ConversionMesu-
reBean pourrait permettre aux concepteurs de pages de spécifier une longueur en pouces pour
la convertir en centimètres, par exemple.
Certains JavaBeans de services ne renvoient aucune information. Leur rôle consiste par
exemple à enregistrer des informations dans une base de données ou dans un fichier d’enregis-
trement. Dans ce cas, on peut initialiser la valeur d’une propriété, non pas pour obtenir un
résultat du service, mais simplement pour son effet de bord, c’est-à-dire pour ce qui se passe
sur le serveur. Les JavaBeans de service permettent de séparer clairement les responsabilités
de chacun et, pour chaque équipe, d’avoir des domaines de connaissances propres. Le concep-
teur web n’a pas besoin de comprendre les estimations statistiques et le programmeur n’a pas
besoin de maîtriser les subtilités des formats de page. Une modification dans la présentation
ou dans le programme n’affectera pas les autres présentations ou programmes si l’interface du
JavaBeans n’a pas changé.
composants dans des documents HTML sans que l’auteur de la page n’ait besoin de connaître
un langage de programmation ou de comprendre des concepts de programmation avancés.
Comme on le sait, un langage puissant devient vite complexe. Les concepteurs de JSP ont
donc choisi de s’appuyer sur un ensemble de fonctionnalités principales très simples, en ne
définissant que quelques balises qui utilisent des JavaBeans et en offrant la possibilité de
développer de nouvelles balises personnalisées qui résolvent des problèmes spécifiques. Les
balises classiques permettent de créer des références aux JavaBeans que l’on souhaite utiliser,
d’initialiser les valeurs de n’importe quelle propriété configurable qu’ils pourraient avoir et de
lire des informations à partir des propriétés des JavaBeans. Des balises personnalisées aux
fonctionnalités plus complexes peuvent être développées par des personnes ou des organisa-
tions, et intégrées dans n’importe quel environnement JSP via un mécanisme d’extension
connu sous le nom de bibliothèques de balises personnalisées. Grâce à ce type de balises, le
langage JSP peut être étendu pour supporter des constructions de programmation supplémen-
taires, telles que les conditions et les boucles, ainsi que de nouvelles fonctionnalités comme
l’accès direct aux bases de données. On examinera ces balises personnalisées et les bibliothè-
ques de balises aux chapitres 13 et 14.
La balise <jsp:useBean>
<jsp:useBean> informe la page que l’on souhaite mettre à sa disposition un JavaBeans. Cette
balise est utilisée pour créer un composant ou pour en obtenir un du serveur. Les attributs de
la balise spécifient le type du composant que l’on veut utiliser et lui affectent un nom qui peut
être utilisé pour le référencer. La balise <jsp:useBean> se présente sous deux formes : une
balise vide unique et un couple de balises de début et de fin contenant le corps qui peut être
utilisé pour spécifier des informations de configuration supplémentaires. Dans sa forme la
plus simple, cette balise ne nécessite que deux attributs, id et class. Comme pour toutes les
balises de JSP, on doit entourer chaque valeur d’attribut par des guillemets. Voici la syntaxe de
base pour les deux formes de la balise :
<jsp:useBean id="bean name" class="class name"/>
L’attribut ID
L’attribut id spécifie le nom du composant, une valeur unique qui le désignera dans la page et
au cours de son existence (on verra comment prolonger l’existence d’un JavaBeans par-delà
son utilisation sur la page courante). On peut utiliser des balises <jsp:useBean> pour définir
plus d’un JavaBeans dans une page, voire des instances multiples de la même classe de
composant JavaBeans, tant que chaque composant possède un identificateur unique. Le nom
Les pages JSP : une approche orientée composants
CHAPITRE 5
13
que nous avons choisi pour notre JavaBeans est arbitraire, mais on doit en la matière suivre
quelques règles simples :
• Il doit être unique pour la page.
• Il est tenu compte de la casse.
• Le premier caractère est une lettre.
• Seuls les lettres, les nombres et les soulignés (_) sont autorisés (les espaces ne le sont pas !).
L’attribut class
La valeur de l’attribut class spécifie le nom de la classe du JavaBeans. Les classes Java sont
souvent structurées en paquetages. Ces derniers sont des collections de fichiers de classes
Java, organisées dans un répertoire unique. Les noms des paquetages sont habituellement
composés de plusieurs noms séparés par des points où chaque nom représente un répertoire
dans la hiérarchie du paquetage. À moins que l’on n’ait utilisé la balise <%@ page %> pour
permettre à notre page d’accéder au paquetage du JavaBeans via son attribut import, on doit
spécifier le nom de la classe du composant dans son intégralité. Le nom intégral d’une classe
est constitué du nom du paquetage de la classe et du nom de la classe elle-même. Par conven-
tion, les noms des paquetages commencent par le nom du domaine Internet de leur créateur et
comportent généralement plusieurs niveaux de hiérarchies pour permettre une meilleure orga-
nisation des collections de classes dans des regroupements logiques. Le développeur du
composant va déterminer son paquetage et le nom de sa classe. Certains des noms complets
de classe de JavaBeans ont la forme suivante :
com.manning.RegisteredUserBean
com.deepmagic.beans.database.logging.LogBean
com.blokware.MagicPizzaBean
com.taglib.wdjsp.arch.EmployeeBean
Le nom de la classe à proprement parler est la dernière partie du nom complet. Dans le
premier exemple, il s’agit donc de la classe RegisteredUserBean qui se trouve dans le paque-
tage com.manning. On peut incorporer ce composant sans le nom du paquetage à condition
d’avoir auparavant importé toutes les classes du paquetage :
<%@page import="com.manning.*" %>
<jsp:useBean name="user" class="RegisteredUserBean" />
ou bien :
<jsp:useBean name="user" class="com.manning.RegisteredUserBean" />
L’attribut type
On utilisera rarement cet attribut dans la pratique. L’attribut class de la balise <jsp:useBean>
détermine la classe Java utilisée pour créer le composant JavaBeans. JSP permet toutefois au
conteneur de JSP d’avoir une interprétation plus fine du type du composant, ce qui s’avère
parfois nécessaire lorsque les JavaBeans existent au niveau du serveur mais qu’ils ne sont pas
instanciés par la page courante. Par défaut, le JavaBeans est référencé par le type de classe
correspondant directement à la classe d’objets sous-jacente. Cependant, si l’on doit faire réfé-
rence au composant sous un autre type, par exemple une classe de base ou une interface qu’il
implémente, on peut utiliser l’attribut type de la balise <jsp:useBean>. Le type de classe que
l’on spécifie représente l’objet JavaBeans dans le code Java qui résulte de la phase de compi-
lation de la page JSP. La classe réelle du composant doit, bien entendu, être compatible avec
JSP – Java Server Pages
14
le type de classe spécifié. Si l’on utilise l’attribut class et type à la fois, le JavaBeans va être
créé en utilisant la classe donnée, puis va subir une modification de type (cast) vers le type
spécifié. L’attribut type ne peut être utilisé seul (sans l’attribut class correspondant) que dans
les cas où le composant JavaBeans existe déjà au niveau du serveur – comme on le verra dans
la dernière section de ce chapitre consacrée à la portée des composants.
Ces balises créent deux objets JavaBeans indépendants ; chacun possède son propre nom :
clock1 et clock2. Ce sont des instances de la même classe, mais tout changement dans l’un est
sans effet sur l’autre. Plus bas dans ce chapitre, on verra comment d’autres attributs de la
balise <jsp:useBean> peuvent permettre de réutiliser un composant JavaBeans entre plusieurs
accès à la même page ou depuis plusieurs pages du site. Dans les exemples précédents, les
composants JavaBeans n’étaient que présents dans le code. Nous allons maintenant montrer
comment les utiliser avec la balise <jsp:getProperty>, qui permet d’extraire les informations
contenues dans les JavaBeans.
Accès aux propriétés des composants via <jsp:getProperty>
Pour accéder aux propriétés d’un JavaBeans depuis les JSP, on peut tout d’abord utiliser la
balise <jsp:getProperty>. Contrairement à la balise <jsp:useBean> qui effectue une tâche en
arrière-plan mais ne produit aucune sortie, la balise <jsp:getProperty> produit un contenu
visible dans le code HTML généré par la page. <jsp:getProperty> est vide et en attente de
deux attributs, name et property. Sa syntaxe est la suivante :
<jsp:getProperty name="nm du Bean" property="nom de la propriété" />
L’attribut name désigne le composant que l’on est en train d’évaluer. Il doit correspondre au
nom que l’on a choisi d’attribuer à ce dernier dans l’attribut id de la balise <jsp:useBean>. Il
faut bien garder à l’esprit que la balise <jsp:useBean> fait référence à un composant avec
l’attribut id, tandis que les autres balises y font référence par le nom qui apparaît dans
l’attribut name. C’est une convention JSP qui stipule que l’attribut id doit être utilisé pour
définir un nouvel objet, alors que l’attribut name est utilisé pour faire référence à un objet exis-
tant. Il faut veiller à ne pas confondre les deux utilisations.
Dans le code HTML résultant qui est affiché à l’exécution, la balise est remplacée par la
valeur de la propriété du JavaBeans demandé. Bien entendu, comme on est en train de créer
un document HTML, la propriété est d’abord convertie en texte par le conteneur de JSP. Cette
balise est facile à utiliser. Reprenons l’exemple du composant ClockBean, mais utilisons cette
fois-ci la balise <jsp:getProperty> pour en extraire l’heure courante :
<jsp:useBean id="myclock" class="com.manning.jsp.ClockBean"/>
<html>
<body>
Le composant Java précise qu’il est :
<jsp:getProperty name="myclock" property="time"/>
</body>
</html>
Cela a pour effet d’afficher du code HTML qui a la forme suivante :
<html>
<body>
Le Bean précise qu’il est : 12:33 pm
</body>
</html>
Dans la mesure où cette balise est l’élément central de la génération par les JSP des sorties
dynamiques basées sur les composants, on fera beaucoup faire appel à la <jsp:getProperty>.
On peut utiliser autant de balises <jsp:getProperty> qu’on le souhaite. Il est possible de les
agrémenter de code HTML, non seulement pour générer des valeurs élémentaires et des blocs
JSP – Java Server Pages
16
de texte, mais aussi pour contrôler les attributs de ce code HTML. En effet, il est parfaitement
correct d’adjoindre des balises JSP aux attributs HTML. La propriété d’un composant peut
tout à fait être utilisée pour contrôler la couleur du fond de la page, la largeur d’un tableau ou
la source d’une image. Par exemple, un JavaBeans représentant la charte graphique d’une
entreprise peut faire appel à une propriété qui indique l’emplacement de la dernière version du
logo et la structure des couleurs de l’entreprise. On peut afficher cette image dans du code
HTML sans coder la valeur de l’URL dans chaque page, de la façon suivante :
<jsp:useBean id="style" class="beans.CorporateStyleBean"/>
<html>
<body bgcolor="<jsp:getProperty name="style" property="color"/>">
<center>
<img src="<jsp:getProperty name="style" property="logo"/>">
Bienvenue !
</center>
</body>
</html>
Ce qui va générer le code HTML suivant :
<html>
<body bgcolor="pink"><center>
<img src="http://imageserver/logo.gif">
Bienvenue!
</center>
</body>
</html>
Si le logo doit être modifié la semaine suivante parce que la société a remplacé le directeur du
groupe ou a été rachetée, toutes les pages vont systématiquement afficher la nouvelle valeur
conçue dans CorporateStyleBean. Autre avantage, les programmeurs d’application peuvent
faire appel au même composant pour afficher la marque dans leurs interfaces graphiques et
que toute modification est immédiatement visible.
ASTUCE Conformément aux spécifications, les espaces dans un document ne sont pas prises en charge par
l’analyseur JSP, mais seront préservées par le processeur de JSP. Cependant, dans certaines des implé-
mentations rencontrées, l’analyseur ne conservait pas correctement les caractères d’espacements entre
les balises JavaBeans de JSP s’il n’y avait pas d’autres caractères. Par exemple, le code JSP suivant
devrait afficher « Prénom Nom » alors qu’il peut arriver que l’on obtienne « PrénomNom » :
<jsp:getProperty name="user" property="prenom"/>
<jsp:getProperty name="user" property="nom"/>
Cela se produit souvent parce que l’analyseur JSP ignore le saut de ligne, qui d’ordinaire est traité comme
un caractère d’espacement. Si tel est le cas, ajouter des lignes blanches n’est pas la solution car l’analy-
seur va tout simplement les ignorer, en supposant qu’il n’y a aucun contenu pertinent entre les deux bali-
ses de composant.
Si un conteneur de JSP présente cette anomalie, on peut contourner le problème en insérant des conte-
nus significatifs mais vides, comme un commentaire HTML, qui vont le forcer à préserver le saut de page
dans les sorties.
<jsp:getProperty name="user" property="prenom"/>
<!-- insert a space -->
<jsp:getProperty name="user" property="nom"/>
Les pages JSP : une approche orientée composants
CHAPITRE 5
17
La balise <jsp:setProperty>
La balise <jsp:setProperty> permet de modifier les propriétés d’un composant. Cette balise
peut être utilisée n’importe où dans la page, à condition que le développeur du composant ait
autorisé l’accès en écriture à cette propriété. La modification des valeurs d’une propriété de
composant sert soit à paramétrer son opération, soit à accéder à ses services. Le comportement
qui résulte d’une modification de la valeur d’une propriété est spécifique au composant
concerné. À titre d’exemple, on pourrait trouver un composant doté d’une propriété query
spécifiant une requête vers une base de données, et dont le résultat est enregistré dans d’autres
propriétés. Dans ce cas, on peut appeler <jsp:setProperty> à plusieurs reprises dans la page
et consulter plusieurs fois les propriétés des résultats puisqu’elles vont retourner de nouvelles
valeurs après chaque modification de la propriété query.
La plupart des JavaBeans de service doivent être dotés de propriétés configurables à l’exécution,
pour que leur comportement puisse dépendre de l’utilisateur. Ainsi, on pourra utiliser le même
JavaBeans pour consulter des types d’information différents. Par exemple, si un développeur
crée un JavaBeans pour fournir des informations sur un utilisateur du système, celui-là peut être
réutilisé pour chaque utilisateur, plutôt que d’être décliné un grand nombre de fois (BobBean,
SueBean, JoeBean, etc). Le développeur va plutôt concevoir les propriétés du composant pour
qu’il fasse référence d’une façon abstraite aux caractéristiques de chaque utilisateur, et ensuite
faire en sorte qu’une de ses propriétés stocke ces informations en fonction de l’utilisateur.
La balise <jsp:setProperty> est d’usage simple. Elle nécessite trois attributs : name, property
et value. Comme la balise <jsp:getProperty>, l’attribut name désigne le JavaBeans concerné,
l’attribut property indique les propriétés que l’on souhaite initialiser et l’attribut value est le
texte que l’on veut affecter à la propriété.
<jsp:setProperty name ="nom du Bean" property="nom de la propriété" />
La balise <jsp:setProperty> peut être utilisée n’importe où dans le document JSP après que
le composant a été défini avec la balise <jsp:useBean>. À l’exécution, la page JSP évalue les
balises dans leur ordre d’apparition. Toute valeur de propriété que l’on initialise n’est prise en
compte que dans les balises qui suivent la balise <jsp:setProperty>. L’attribut value peut être
spécifié sous la forme d’un texte ou calculé à l’exécution au moyen d’expressions JSP. Voici
deux façons d’initialiser les jours depuis la dernière visite d’un utilisateur en mettant à jour la
valeur de la propriété. Les deux exemples sont fonctionnellement équivalents, ils affectent la
valeur 30 à la propriété daysLeft :
<jsp:setProperty name="user" property="daysLeft" value="30"/>
<jsp:setProperty name="user" property="daysLeft" value="<%= 15 * 2 %>"/>
indexée au moyen d’une expression ou d’une scriptlet JSP en faisant simplement appel à sa
méthode d’accès et en lui transmettant une valeur d’indice. Pour consulter une propriété
indexée, il faut la préfixer par le mot get. On peut la modifier en utilisant le préfixe set (on
verra au chapitre 6 comment associer des propriétés aux noms de méthodes). Pour lire la
propriété forecasts, on devra appeler la méthode getForecasts(). Par exemple :
<B>Prévisions pour demain </B>: <%= weather.getForecasts(0) %> <BR>
<B>Pour le reste de la semaine </B>
<UL>
<% for (int index=1; index < 5; index++) { %>
<LI><%= weather.getForecasts(index) %> (peut être)
<% } %>
</UL>
Dans cet exemple, on utilise des scriptlets et des expressions JSP pour accéder à la propriété
forecasts de WeatherBean, qui a été chargée dans la page avec un id d’objet météo. Pour affi-
cher les prévisions météo du lendemain, on utilise une expression JSP pour obtenir le premier
élément de la propriété forecasts en faisant appel à sa méthode d’accès getForecasts() avec
0 comme argument. Ensuite, on utilise une scriptlet pour itérer sur les éléments 1, 2, 3 et 4 afin
de visualiser les prévisions météo du reste de la semaine.
Les JavaBeans dotés de propriétés indexées peuvent être conçus de façon qu’ils soient plus
facilement utilisables avec les pages JSP en évitant au développeur d’avoir recours à des
scriptlets pour y accéder. Un JavaBeans peut contenir une propriété pratique qui permette de
traiter une propriété indexée comme une valeur de texte unique en séparant chaque valeur par
un point-virgule ou un autre délimiteur.
Toute commande à l’intérieur du corps est traitée immédiatement après que l’instanciation du
JavaBeans et avant qu’il ne soit mis à la disposition du restant de la page. Par exemple :
<jsp:useBean id="clock" class="com.manning.jsp.ClockBean">
<jsp:setProperty name="clock" property="timezone" value="CST"/>
</jsp:useBean>
On peut considérer les éléments présents dans le corps de la balise <jsp:useBean> comme
faisant partie d’une phase de configuration qui ne s’exécute qu’une seule fois. C’est un moyen
commode pour configurer le JavaBeans avec des données spécifiques à la page ou pour le
préparer à son utilisation future dans la page. Il est même possible d’affecter des valeurs aux
propriétés d’autres composants si ceux-ci ont été créés plus haut dans la page.
Le corps de la balise <jsp:useBean> peut également contenir des scriptlets JSP et des balises
HTML. Cet HTML ne va être affiché comme partie intégrante de la page que si le JavaBeans
doit être instancié (assurez-vous de placer un tel texte après la balise HTML ouvrante !). Si le
JavaBeans existe déjà dans l’environnement, les demandes de pages ultérieures ne vont pas
afficher cet HTML d’initialisation. Par exemple :
<html>
<body>
<jsp:useBean id="clock" class="com.manning.jsp.ClockBean">
Le <b>ClockBean</b> est en cours d’initialisation...
</jsp:useBean>
La page principale suit…
</body>
</html>
La propriété futureValue est liée aux autres propriétés. Sa valeur est calculée à partir des
propriétés principal, interestRate et years. Par conséquent, pour utiliser ce composant, on
doit attribuer des valeurs à ces trois propriétés, puis lire les résultats dans la propriété future-
Value. Consultons la page JSP qui va prendre en charge le formulaire. On doit tout d’abord
créer une référence au composant CompoundInterestBean.
<%@page import="com.taglib.wdjsp.components.*"%>
<jsp:useBean id="calculator" class="CompoundInterestBean"/>
Dans le corps de la balise <jsp:useBean>, on doit faire correspondre chacune des propriétés de
configuration aux données appropriées des champs du formulaire. La balise <jsp:setPro-
perty> recherche un paramètre de requête qui est apparentée à la valeur spécifiée dans
l’attribut param de la balise. Si elle en trouve un, elle demande au JavaBeans d’affecter cette
valeur à la propriété correspondante, via l’attribut property, en effectuant les conversions
nécessaires. On ajoute alors les trois lignes suivantes à la balise <jsp:useBean> :
<jsp:setProperty name="calculator" property="principal" param="principal"/>
<jsp:setProperty name="calculator" property="interestRate"
param="interestRate"/>
<jsp:setProperty name="calculator" property="years" param="years"/>
L’attribut param de la balise <jsp:setProperty> est l’équivalent de la scriptlet JSP
<%request.getParameter("truc") %>. Le bloc de code précédent est donc fonctionnellement
Les pages JSP : une approche orientée composants
CHAPITRE 5
21
équivalent au bloc suivant qui utilise les scriptlets au lieu de l’attribut param pour initialiser les
valeurs du composant :
<jsp:setProperty name="calculator" property="principal"
value='<%= request.getParameter("principal") %>'/>
<jsp:setProperty name="calculator" property="interestRate"
value='<%= request.getParameter("interestRate") %>'/>
<jsp:setProperty name="calculator" property="years"
value='<%= request.getParameter("years") %>'/>
Lorsqu’une requête provient du formulaire, les valeurs spécifiées par l’utilisateur vont être
affectées aux propriétés du composant. Comme c’est là le moyen usuel de les configurer dans
les JSP, des raccourcis ont été fournis. Ainsi, si le nom de la propriété est le même que celui
du paramètre transmis au moyen du formulaire, on peut supprimer l’attribut param. Par consé-
quent, le corps de la balise <jsp:useBean> peut être simplifié de la façon suivante :
<jsp:setProperty name="calculator" property="principal"/>
<jsp:setProperty name="calculator" property="interestRate"/>
<jsp:setProperty name="calculator" property="years"/>
Lorsque plusieurs noms de champs du formulaire correspondent directement aux propriétés
du composant, on peut également utiliser le caractère de remplacement « * » au lieu du nom
de la propriété. L’utilisation d’un caractère de remplacement indique que l’on souhaite attri-
buer une valeur à toute propriété du composant dont le nom correspond à celui du paramètre
de la requête. Les noms doivent parfaitement correspondre pour éviter que les paramètres ne
soient reliés à des propriétés de noms différents lorsque le caractère de remplacement est
utilisé. Un paramètre de requête est recherché pour chaque propriété. Les paramètres super-
flus sont ignorés, bien qu’ils soient accessibles par les scriptlets et l’objet implicite request.
Bien entendu, on peut faire usage de commandes <jsp:setProperty> pour accéder à n’importe
quel paramètre de la requête dont le nom ne correspond pas directement à une propriété du
composant. On ne dispose d’aucun moyen pour déterminer ou spécifier l’ordre dans lequel les
propriétés sont modifiées. S’il y a des interdépendances, on préfère leur affecter explicitement
des valeurs en spécifiant une balise <jsp:setProperty> pour chacune des propriétés. Si l’on
fait soigneusement correspondre tous les noms de champ du formulaire avec les noms de
propriétés du composant, on va pouvoir configurer toutes les propriétés avec une seule
instruction en utilisant un caractère de remplacement :
<jsp:setProperty name="calculator" property="*"/>
Une fois que le JavaBeans est configuré, on peut lire les résultats des calculs du composant
dans la propriété futureValue. On peut également vérifier les données d’entrée en consultant
les valeurs des propriétés que l’on vient de configurer.
Si vous investissez $<jsp:getProperty name="calculator" property="principal"/>
pour <jsp:getProperty name="calculator" property="years"/> années
à un taux d’intérêt de
<jsp:getProperty name="calculator" property="interestRate"/>%
mensuellement composé, vous obtiendrez
$<jsp:getProperty name="calculator" property="futureValue"/>
Les sorties du programme JSP de prise en charge du formulaire vont produire les résultats
suivants :
JSP – Java Server Pages
22
AVERTISSEMENT On ne peut pas utiliser des paramètres de requête commençant par java, javax et com.sun. Ils sont
réservés à l’utilisation propre du conteneur de JSP et peuvent entrer en conflit avec les paramètres affec-
tés aux requêtes par le conteneur.
Dans cet exemple, la valeur dix pour cent est affectée à la propriété interestRate, mais elle
peut être écrasée par la valeur du paramètre de requête interestRate s’il existe. On peut ainsi
fournir des valeurs par défaut pour les propriétés critiques et créer des pages flexibles, accessibles
de plusieurs façons différentes.
La sécurité
La notation utilisant les caractères de remplacement introduite auparavant, <jsp:setProperty
property="*">, est un raccourci très puissant pour initialiser les propriétés d’un composant à
partir d’une requête, en particulier pour faire correspondre des valeurs entrées dans un formu-
laire aux propriétés correspondantes d’un composant. Mais il faut utiliser ces abréviations
avec prudence lorsque les propriétés du composant contiennent des informations sensibles,
car il est très facile à un utilisateur de construire ses propres requêtes.
Considérons par exemple une application bancaire en ligne qui manipule des informations sur
les comptes via une classe JavaBeans nommée AccountBean. Cette classe fournit des
propriétés pour accéder à des informations qui concernent le compte, telles que le numéro du
compte (accountNumber) et le solde (balance), ainsi que des propriétés correspondant aux
transactions sur ces comptes, telles que le retrait d’une somme d’argent (withdrawalAmount) et
le transfert d’une somme d’argent (transferAmount). Comme le formulaire permet à un utili-
sateur de spécifier un retrait, il va pointer sur la page JSP, comme cela est illustré ci-après, qui
effectue la transaction (par effet de bord de l’affectation de valeurs aux propriétés) et retourne
le résultat :
<jsp:useBean id="myAccount" class="AccountBean">
<jsp:setProperty name="myAccount" property="*"/>
</jsp:useBean>
<html>
<head><title>retrait d’argent</title></head> <body>
<p>
un retrait de $<jsp:getProperty name="myAccount" property="withdrawalAmount"/>
a été effectué sur le compte
#<jsp:getProperty name="myAccount" property="withdrawalAmount"/>.
Le solde actuel de votre compte est $<jsp:getProperty name="myAccount"
➥property="balance"/>.
Nous vous remercions de votre confiance.
Au premier abord, le code semble ordinaire. Cependant, supposons que l’accès aux propriétés
du composant soit autorisé en lecture et en écriture, ce qui est proche de la réalité. Soit
retrait.jsp, l’URL de cette page. Examinons l’effet produit par la requête utilisateur suivante :
http://server/account/withdraw.jsp?accountNumber=Phil31N&balance=1000000
En principe, on va accéder à cette page en tant qu’élément cible d’un formulaire, mais rien
n’empêche l’utilisateur de construire manuellement sa propre requête. Le montant du retrait
n’est pas spécifié dans cette URL, ce n’est probablement pas un problème, mais la présence
d’un paramètre de requête appelé solde est très ennuyeux. Lorsque le conteneur de JSP traite
la balise <jsp:setProperty>, il va associer ce paramètre à une propriété du JavaBeans portant
le même nom et va essayer de lui affecter la valeur $1 000 000 !
Il faut espérer que le développeur Java, responsable de l’implémentation de AccountBean, a
mis des protections pour empêcher ce type de falsification, mais cette vigilance doit être plus
importante lorsque des caractères de remplacement sont utilisés. Si le JavaBeans possède des
JSP – Java Server Pages
24
propriétés accessibles en écriture et dont l’accès doit être contrôlé (le solde d’un compte
bancaire, par exemple), alors ce JavaBeans doit effectuer lui-même les contrôles d’accès. En
l’absence d’un tel contrôle, le JavaBeans peut se laisser abuser par des requêtes malveillantes
comme celle que l’on vient de décrire, surtout lorsqu’elles sont combinées avec des balises
<jsp:setProperty> utilisant des raccourcis tels que les caractères de remplacement.
Lorsqu’un JavaBeans est créé au niveau du serveur afin qu’il soit réutilisé dans plusieurs
pages, il est identifié par un nom spécifié par l’attribut id de la balise <jsp:useBean>. Chaque
fois que l’on essaie de créer un JavaBeans avec la balise <jsp:useBean>, le serveur va recher-
cher dans sa mémoire un JavaBeans qui porte le même id que celui qui est spécifié dans la
balise. S’il en trouve un, et qu’il est accessible depuis la requête courante, alors, plutôt que
d’en créer un autre, le JavaBeans est utilisé. Si des commandes de configuration ont été spéci-
fiées dans la balise, elles vont être ignorées parce que le JavaBeans a déjà été initialisé. La
Les pages JSP : une approche orientée composants
CHAPITRE 5
25
syntaxe de l’attribut scope est présentée ci-après. Un JavaBeans ne peut avoir qu’une seule
valeur de portée. On ne peut pas les combiner dans la mesure où elles sont par définition
mutuellement exclusives.
<jsp:useBean id="beanName" class="class"
scope="page|request|session|application"/>
Considérons par exemple une situation où l’on introduit un pied de page via la balise
<jsp:include> et dans laquelle on souhaite introduire des données spécifiques à chaque page.
Si on place les données dans la portée page, elles ne seront pas accessibles par le pied de page
qui a été inclus. Pour y parvenir, il faut enregistrer nos informations dans un JavaBeans qui a
une portée request, ce qui permet à nos données d’être visibles par le pied de page et par la
page courante. Dans cet exemple, on associe, à chaque page, le nom d’une personne à
contacter qui apparaît dans le pied de page.
<jsp:useBean id="contact" class="jsp.ContactBean" scope="request">
<jsp:setProperty name="contact" property="name" value="Kris DeHart"/>
</jsp:useBean>
<html>
<body>
Bienvenue dans votre site!
<jsp:include file="/footers/standardFooter.jsp" flush="true"/>
</body>
</html>
Dans cet exemple, contact est accessible par la page courante et par standardFooter.jsp, qui
est un extrait de HTML ressemblant à ceci :
<HR>
Pour toute modification de requête, contactez
<jsp:getProperty name="contact" property="name"/>
Cet exemple de conception d’une page par introduction de petites pages de composants pour
en construire une, composée, plus grande, est une technique très utile pour la conception de
pages complexes. On détaillera ce procédé au chapitre 8.
comportement. Il est donc déconseiller de faire cette hypothèse. Si l’on a besoin d’enregistrer
des informations pour un temps indéterminé, ou bien si la session est utilisée pour mémoriser
des données sensibles, mieux vaut enregistrer ses données dans une base de données. En effet,
la plupart des conteneurs mettent fin aux données de session si on n’y a pas accédé au bout de
quelques heures.
ASTUCE Si on a utilisé <%@ page session="false" %> pour indiquer que la page ne s'exécute pas dans un
contexte de session, on sera dans l'incapacité de rendre des composants JavaBeans persistants en utili-
sant la session courante. La valeur par défaut de l'attribut de session est true, activant ainsi le support
de session. Cependant, si ce support ne vous est d'aucune utilité, il faut affecter à cet attribut la valeur
false pour éviter que le conteneur de servlets ne crée des objets de session inutiles et gourmands en
mémoire.
Les sessions sont importantes quand il s’agit d’enregistrer des informations collectées
pendant la visite du site par un utilisateur et de récupérer des informations souvent utiles au
niveau de la page. Elles peuvent être utilisées pour transférer des informations d’une page à
une autre, sans que chacune d’elle ne doive inclure un programme ou un temps de traitement
supplémentaire pour accéder à des informations enregistrées dans une base de données ou une
source externe. Le caddie des achats est un bon exemple de données orientées session. L’utili-
sateur va souhaiter que le contenu du caddie soit accessible tout au long de l’application. On
va donc créer le JavaBeans ShoppingCartBean qui représente le caddie des achats, et l’enregis-
trer dans la session de l’utilisateur. Dans chaque page, on peut introduire une référence au
caddie qui permet d’afficher le total des achats en cours si on le souhaite.
On va voir, de la façon la plus simple qui soit, comment on peut utiliser le JavaBeans Timer-
Bean pour savoir pendant combien de temps une session utilisateur a été active. On peut
utiliser un tel JavaBeans pour déconnecter un individu qui est resté inactif pendant une
certaine période, ou pour enregistrer des visites pour lesquelles la durée est un paramètre
important, comme la réalisation en ligne d’une synthèse ou d’un examen. Notre TimerBean
possède une fonction de base : rendre compte du temps passé entre le moment de sa création
et le temps courant. Ce JavaBeans, que l’on approfondira au chapitre 6, possède les propriétés
présentées dans le tableau 5-5.
La propriété startTime est supposée fournir un moyen pour affecter la valeur de la date au
démarrage du JavaBeans, soit en lui attribuant une valeur de date particulière (exprimée en
millisecondes depuis la date 0), soit la date courante en lui transmettant une valeur nulle ou
négative.
JSP – Java Server Pages
28
ASTUCE La durée de vie par défaut d’une session est déterminée par le conteneur de JSP (ou plus précisément,
par le conteneur de servlets). Nouvellement introduites dans la version 2..2 de Servlet API, les méthodes
getMaxInactiveInterval() et setMaxInactiveInterval() de l’interface HttpSession peuvent être
utilisées pour visualiser ou mettre à jour les variables d’expiration. La méthode getLastAccessdTime()
de cette interface permet de connaître le temps écoulé depuis le dernier accès aux données de la
session.
Les pages JSP : une approche orientée composants
CHAPITRE 5
29
chacune des pages des utilisateurs, on va probablement s’enquérir d’une autre solution. Tout
d’abord, on peut utiliser des JavaBeans spécifiques aux applications qui ne nécessitent pas de
configuration particulière ou dont les constructeurs collectent les informations de configura-
tion à partir d’une autre source (un fichier de propriétés, par exemple). Ensuite, on peut
procéder par étapes pour s’assurer que le JavaBeans en question est bien placé dans une portée
d’application avant que les pages qui en dépendent ne veuillent y accéder. Ou encore, on peut
organiser une suite de JavaBeans préconfigurés sur disque et les restaurer quand cela est
nécessaire.