Commençons par nous débarrasser de la page Web. Cette partie ne contient que du HTML pur. La partie gestion de la page est un formulaire, dont la cible (atteinte par un clic sur le bouton Submit Query) est la page JSP tableDisplay.jsp :
<FORM ACTION="tableDisplay.jsp"
METHOD="GET">
<TABLE> table code
here
</TABLE>
<P><INPUT type="submit"></P>
</FORM>
La table à l’intérieur du formulaire sert à collecter un grand nombre de paramètres à transmettre à la page JSP. Comme toutes les lignes de la table sont similaires, examinons simplement la ligne du nom patronymique :
<TR>
<TD>Last Name</TD>
<TD>
<SELECT name="lastNameOp">
<OPTION value="none" selected
"selected">None
<OPTION value="=">Equals
<OPTION value=">">Greater Than
<OPTION value="<">Less Than
<OPTION value="LIKE">Contains
</SELECT>
</TD>
<TD><INPUT type=text"
name="lastName"></TD>
</TR>
Il y a deux paramètres qui seront
transmis au JSP. Le premier est appelé
lastNameOp, représentant l’opérateur
de comparaison pour le champ last
name. Le second, appelé lastName, représente
la valeur à comparer.
Supposons que je recherche des noms
contenant la lettre « L ». Dès que je
clique sur Submit, si j’examine soigneusement
ma ligne d’adresse, enterrée
dans la chaîne de requête après
http://localhost:8080/examples/tableDi
splay.jsp, je vois les paramètres suivants
:
lastNameOp=LIKE&lastName=L
Comme nous le verrons, on y accède
dans le code JSP.
Le JSP est plus complexe et il mérite
une excuse. Il s’inspire d’un programme
RPG et d’un fichier écran monolithiques
avec, pour faire bonne mesure,
quelque chose qui ressemble à
un fichier décrit par programme. Ce
JSP – avec la logique de présentation,
de gestion et de base de données rassemblés
– n’est pas forcément idéal
pour vos applications. Mais je reviendrai
plus loin sur les problèmes de design.
Mon intention pour l’instant est
de montrer la portée et la puissance
des JSP de manière compacte.
Pour l’essentiel, l’exemple JSP est
constitué de deux choses. L’une est le
HTML normal et dans mon JSP, il est
concentré vers la fin. L’autre est le code
Java, toujours délimité par des symboles
spéciaux : <% au début et %> à
la fin. Le symbole de début a des variantes
; parfois vous verrez <% uniquement,
mais vous trouverez aussi
<%@, <%! et <%=. Leur signification
apparaîtra bientôt, mais il convient
tout d'abord de comprendre ce qui se
passe quand on adresse une requête à
un JSP.
Si c’est la première fois que le JSP a
été demandé – ou si le JSP a changé
depuis le dernier accès – le serveur applicatif
effectue les opérations suivantes
:
- Il traduit la page JSP en un fichier
code source Java.
- Il compile le code source Java en
une classe Java (un type de servlet
spécialisé).
- Il charge et exécute le servlet.
- Il envoie la sortie de la page Web du
servlet au navigateur demandeur.
Pour bien comprendre les JSP, il est
intéressant d’examiner le code source
servlet produit. Il se trouve normalement
dans quelques répertoires de travail
dans la structure de répertoires
serveur de votre application. Sachez
toutefois que vous y trouverez (1) tout
le code Java que vous avez imbriqué
dans votre JSP et (2) tout le HTML (lié
dans les instructions « out.write(« … ») »
Java et beaucoup d’autres choses à
côté.
Revenons au source de tableDisplay.
jsp. Près du début, vous verrez
quelques instructions du genre :
<%@ page import="java.sql.*" %>
Le symbole <%@ indique qu’il
s’agit d’une directive. Ici, c’est une directive
adressée au générateur source
Java JSP, de placer une instruction import
à l’endroit approprié dans le code
source :
import java.sql.*;
Ensuite, vous trouverez le premier
de plusieurs groupes de lignes délimitées
par <%! et %>. Cela indique une
déclaration, qui (dans le contexte des
JSP) signifie n’importe quel code
source à placer à l’extérieur de la méthode
« service() ». (La méthode « service()
» du servlet est appelée chaque
fois que l’on accède au JSP.) J’ai mis
une grande variété de choses dans les
déclarations. Elles sont résumées cidessous
(on trouvera des commentaires
plus fournis dans le code
source) :
- Certaines variables d’instance.
Ce peut être une connexion et une
instruction pour l’accès JDBC et un
compteur pour les lignes.
- Une classe interne entière appelée
Employee. Chaque instance
de cela représentera une ligne provenant
de la table EMPLOYEE.
- Une méthode de remplacement
appelée jspInit(). Elle
s’exécutera une fois, au premier
chargement du servlet JSP. J’utilise le
code JDBC pour établir une
connexion à la base de données (qui reste ouverte pour des accès ultérieurs).
4. Une autre méthode de remplacement
appelée jspDestroy().
Cette méthode ferme la connexion
base de données à l’endroit où le
servlet JSP est retiré du service (en
principe, quand le serveur d’application
est fermé).
- Une méthode appelée query-
Database(). Cette méthode sert
pour lire des lignes de la table EMPLOYEE
et pour transformer chacune
d’elles en une instance de la
classe Employee décrite ci-dessus.
Chacune des instances Employee
est placée dans une collection
(ArrayList) pour usage ultérieur. De
plus, un comptage des lignes trouvées
est maintenu et placé dans la
variable d’instance rowCount.
- Une méthode appelée build-
SQLString(). Cette méthode
prend les paramètres retransmis à
partir du formulaire sur la page selection.
html et les traduit en une
clause WHERE appropriée (WHERE
LASTNAME LIKE ‘%L%’).
Les fragments Java restants dans le
du code HTML méritent un
examen plus approfondi. Le premier
contient les lignes suivantes (sans les
commentaires pour des raisons de
brièveté) :
<%
synchronized (connection) {
String sqlString =
buildSQLString(request);
ArrayList empCollection =
queryDatabase(sqlString);
int rows = rowCount;
%>
Premièrement, considérez les <%
et %>. Ces symboles délimitent un
scriptlet : du code Java à placer dans la
méthode service() du servlet de JSP.
Ainsi, ce code sera exécuté chaque fois
qu’on accèdera au JSP.
Deuxièmement, nous avons un
bloc de code synchronisé. L’objet sur
lequel se fait la synchronisation est la
connexion de variable d’instance,
notre passerelle vers l’accès à la base
de données. Pourquoi ? Sans synchronisation,
deux utilisateurs accédant au
JSP en même temps pourraient recevoir
des résultats imprévisibles. Avec la
synchronisation, l’utilisateur qui arrive
juste après est obligé d’attendre la fin
de la requête du premier utilisateur.
Et, bien entendu, les performances en
souffrent. Cette situation peut être gérée
plus élégamment.
Dans le bloc de code, trois choses
se produisent :
- La méthode de construction de la
chaîne SQL est invoquée, renvoyant
le résultat à une variable locale appelée
sqlString. La partie intéressante
de l’appel de la méthode est le
paramètre « request ». D’où est-il
venu ? Il n’est mentionné nulle part
ailleurs dans le code source JSP. La
réponse est que le servlet JSP généré
fournit automatiquement plusieurs
variables locales à la sortie de la
méthode service(). L’une d’elle est
« request », un objet HttpServletRequest,
qui encapsule une requête de
navigateur. Dans ce cas, la requête
contient tous les paramètres commodes
en provenance du formulaire
défini dans selection.html.
- Ensuite, la méthode destinée à interroger
la base de données est invoquée
et la collection des employés
est renvoyée à une variable
locale appelée empCollection.
- Enfin, le comptage de lignes contenues
dans la variable d’instance
rowCount est transféré à une variable
locale appelée rows.
Dès lors que l’information dont
nous avons besoin se trouve dans les
variables locales – empCollection et
rows – on peut fermer le bloc synchronisé
en toute sécurité. Les variables locales
sont par nature « thread safe ».
Comme le code restant ne travaille
qu’avec ces variables locales, l’accès
multi-utilisateurs restera fiable.
Le morceau de Java suivant que
nous rencontrons est imbriqué dans
HTML ; donc :
<P><B><%= rows %></B>
employés ont été trouvés correspondant
à vos critères de sélection.
Le <%= commence une « expression
» en syntaxe JSP. N’importe quelle
expression Java fera l’affaire, pourvu
qu’elle équivale à un morceau de données
que l’on veut visible dans la page
Web. Dans ce cas, l’expression est simplement
la variable locale « rows ».
Juste avant les lignes de données
dans la table HTML, on trouve le scriptlet
suivant :
<%
for (int i = 0;
i <empCollection.size();
i++) {
Employee emp = (Employee)
empCollection.get(i);
%>
C’est le début d’une boucle Java
destinée à produire une ligne de table
pour chaque employé trouvé. A noter
que la parenthèse angulaire de fin de
boucle se trouve dans un scriptlet séparé
après la fin de la ligne de table
(</TR>) :
<% }// end for %>
La fonction de la boucle est de faire
des itérations dans la collection d’employés,
en plaçant l’employé courant
dans une variable locale appelée
« emp », de type Employee (selon
notre déclaration antérieure).
La fonction de la boucle est de faire
des itérations dans la collection d’employés,
en plaçant l’employé courant
dans une variable locale appelée
« emp », de type Employee (selon
notre déclaration antérieure).
<TD><%= emp.getEmployeeNumber() %></TD>
<TD><%= emp.getFirstName() %></TD>
<TD><%= emp.getMiddleInitial() %></TD>
<TD> (etc.)
On accède à chaque attribut d’employé
par une méthode « getter »
simple.