L'API JSP définit un moyen de définir ses propres tags, et de leur associés des traitement écrits dans des classes Java. S'en est suivi le développement de bibliothèques de tags appelées taglibs, dont certaines sont standardisées dans l'API. Des frameworks entiers, tels que Struts, sont construits en partie sur ces taglibs, qui permettent des traitement très puissants.
Techniquement, une bibliothèque de tags est composée deux deux éléments :
un descripteur au format XML, appelé "fichier TLD", et qui porte l'extension
.tld
;
une ou plusieurs archives Java, au format JAR. Ces fichiers doivent être rangés dans le
répertoire WEB-INF/lib
de l'application web.
Il est bien sûr possible de créer ses propres bibliothèques de tags, et ce processus, bien qu'un peu technique n'est pas beaucoup plus complexe que de créer une servlet. Cela dit nous ne le décrirons pas ici, nous nous bornerons à décrire quelques éléments de la JSTL, Java Standard Tags Library.
La JSTL se compose de quatre librairies :
Une librairie core
, qui expose tous les tags de base de la JSTL. Les autres librairies
s'appuient sur cette librairie.
Une librairie fmt
, qui expose toutes les fonctionnalités d'affichage de données
non triviales : les dates formatées, les nombres formatés, les messages internationalisés.
Une librairie x
, qui permet de manipuler le XML. Cette librairie permet par exemple
de lire des flux XML via HTTP, de les analyser, de les transformer par XSLT, puis de les
afficher sous différentes formes.
Enfin une librairie sql
, qui permet d'interagir directement avec les bases de
données.
JSTL apporte une nouveauté aux JSP : l'utilisation de l'expression language, qui permet de s'affranchir de la syntaxe lourde des scriplets originels. Ce langage n'est pas un langage complet : il permet essentiellement de lire des variables, d'accéder à leurs propriétés, et de contruire des expressions.
En combinant l'utilisation de l'EL et celle des taglibs, on peut construire des pages complexes, avec de l'internationalisation, du contrôle de flux, de l'accès aux bases de données et des éléments XML.
L'exemple qui suit nous montre comment tester si une variable est non nulle en utilisant EL, puis afficher une valeur ou une autre en fonction du résultat de ce test.
Exemple 5.16. Afficher une variable non nulle en JSTL
<%@page contentType="text/html" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <c:choose> <c:when test="${marin != null}"> <p>Bonjour <c:out value="${marin.nom}"/></p> </c:when> <c:otherwise> <p>Bonjour le monde !</p> </c:otherwise> </c:choose> </body> </html>
Analysons ce premier exemple en détails.
Tout d'abord, on indique que l'on va utiliser une librairie de tags par la déclaration
<%@taglib prefix="..." uri="..."%>
. Cet élément comporte deux attributs :
prefix
: précise le préfixe au sens XML utilisé pour les éléments de cette page.
Le choix de ce préfixe est libre, on utilise conventionnellement c
pour la
librairie core
.
uri
: le nom de cette librairie. Ce nom est fixé, et déclaré dans le descripteur
de librairie (fichier TLD). Pour la librairie core
, l'uri est
http://java.sun.com/jsp/jstl/core
.
Cette déclaration ressemble à celle d'un espace de noms pour un fichier XML. Si l'on développe sa propre librairie de tags, on veillera à la nommer de façon unique.
Une librairie de tags déclare un certain nombre d'éléments XML utilisables dans un page JSP. Ces éléments sont définis dans le standard JSTL, et c'est là qu'ils sont documentés.
On peut paramétrer un tag de deux façon : en lui ajoutant des attributs, ou en lui ajoutant du contenu. Notons que les uns et les autres sont facultatifs
Dans notre exemple, l'élément choose
ne prend pas d'attributs, et il possède un contenu
fixé. Ce contenu est composé d'autant de sous-éléments when
que l'on veut, et d'un unique
élément otherwise
. Il ne peut pas y avoir de contenu textuel.
De même, l'élément when
ne comporte qu'un unique attribut test
, obligatoire,
et d'un contenu qui peut mélanger du texte et des éléments JSP (donc d'autres tags).
Enfin, l'élément otherwise
ne comporte pas d'attribut, et du contenu JSP, tout comme
l'élément when
.
Chacun de ces éléments est associé à une sémantique très précise. L'élément choose
englode une série d'élément when
. Chacun de ces éléments est pris un par un par
le moteur de JSP. Le premier de ces éléments pour lequel l'argument de son attribut
test
est true
voit son contenu s'afficher. Si aucun élément
when
ne répond à ce critère, alors c'est le contenu de l'élément otherwise
qui est affiché, s'il est présent.
Le choose
agit donc un peu comme un switch
, en n'affichant qu'un seul
élément de contenu parmi une liste.
On notera également l'utilisation de l'élément out
, qui affiche la valeur de son
attribut value
.
Cet exemple nous permet de présenter le fonctionnement général des bibliothèques de tags.
La librairie core
expose d'autres éléments.
L'élément if
fonctionne comme le if
classique de tout langage. Si
la condition qui lui est associée est vraie, alors le contenu du if
est exécuté.
Dans le cas contraire, elle ne l'est pas.
JSTL nous offre une subtilité supplémentaire : la possibilité de sauvegarder le résultat du test dans une variable, en précisant son nom et le contexte dans lequel elle vit. De cette façon, il est possible d'utiliser a nouveau le résultat de ce test plus loin dans la page, sans avoir à le recalculer.
Ce tag permet d'itérer sur une collection d'objets. Cette collection peut être une plage d'entiers, dont on précise la borne inférieure et la borne supérieure. Elle peut être aussi une vraie collection, déclarée plus haut dans la page JSP.
Exemple 5.18. Utilisation de forEach
sur une plage d'entiers
<table> <tr> <th>Entier</th> <th>Deux foix cet entier</th> </tr> <c:forEach var="i" begin="0" end="10" step="2"> <tr> <td><c:out value="${i}"/></td> <td><c:out value="${2*x}"/></td> </tr> </c:forEach> </table>
Sur ce premier exemple, l'attribut var
donne le nom de la variable d'itération,
begin
et end
les bornes de l'intervalle d'itération. L'attribut
optionnel step
précisé l'incrément d'une itération à l'autre.
Exemple 5.19. Utilisation de forEach
sur une collection
<table> <tr> <th>Nom</th> <th>Prénom</th> </tr> <c:forEach var="marin" items="${marinList}"> <tr> <td><c:out value="${marin.nom}"/></td> <td><c:out value="${marin.prenom}"/></td> </tr> </c:forEach> </table>
Sur ce deuxième exemple, l'itération a lieu sur les éléments d'une collection définie par ailleurs
marinList
. La variable d'itération est définie par l'attribut var
.
On accède ensuite aux champs de l'objet marin
comme pour un bean normal.
L'élément URL permet de générer des URL de façon déclarative, sans passer par une quelconque concaténation de chaînes de caractères, ce qui reste un processus fragile, et à éviter. L'élément URL permet différentes chose.
D'ajouter automatiquement le préfixe associé à la web application dans laquelle la page se trouve. Ce préfixe, propre au déploiement, peut varier, et n'est a priori pas connu au moment du développement de l'application.
Il supporte l'ajout du cookie JSESSIONID
à l'URL si cela est nécessaire.
Il supporte l'encodage des paramètres dans l'URL, dans le cas d'une requête de type GET.
Exemple 5.20. Utilisation du tag url
<c:url value="/articles/search.jsp"> <c:param name="keyword" value="${word}"/> <c:param name="date" value="10/10/2010"/> </c:url>
La déclaration de cette URL peut se traduire par deux URL différentes. Si le système détecte que le navigateur accepte les cookies, l'URL généré aura la forme suivante :
/blogspot/articles/search.jsp?keyword=cours+paumard&month=10%2F10%2F2003
Si le navigateur client n'accepte pas les cookies, alors le JSESSIONID
doit être
ajouté à l'URL, qui aura donc la forme suivante.
/blogspot/articles/search.jsp;jsessionid=123123456765AEF345ED7689F42983EE? \ keyword=cours+paumard&month=10%2F10%2F2003
Un ordre redirect
est une commande HTTP qui indique au navigateur client de
générer une nouvelle requête sur l'URL passée en paramètre de l'ordre redirect
. Il
existe plusieurs formes de redirect
, correspondant aux codes HTTP 3xx.
La classe HttpServletResponse
expose une méthode sendRedirect(String)
qui envoie ce code avec comme URL la chaîne passée en paramètre. Le tag redirect
correspond à cette méthode.
Le premier attribut, obligatoire, que prend cet élément est url
. Cette URL peut être
absolue ou relative. Une URL absolue est transmise sans modification au client. Une URL relative
peut être de deux formes. Une URL qui commence par un /
doit correspondre à une
ressource disponible au sein de cette web application, et le moteur JSP ajoute l'URL de base
de cette application web en préfixe. Si elle ne commence pas par ce caractère, alors le moteur
de JSP l'interprète comme une URL relative, et la complète avant de l'envoyer au navigateur.
Un deuxième attribut, optionnel, peut être ajouté : context
. S'il est présent, alors
une URL commençant par un /
sera interpètée comme étant définie dans ce context
plutôt que dans le contexte courant.
Exemple 5.21. Syntaxe de l'élément redirect
<c:redirect url="url" context="context"> <c:param name="name" value="value"/> ... </c:redirect>
Notons que tous les attributs utilisés peuvent être exprimés par des variables.