JSP Standard Tag Library (JSTL) est une librairie qui étend les fonctionnalités de JSP en mettant à disposition de nouveaux tags à utiliser en HTML. L'objectif est de permettre d'écrire du code plus facilement et de manière plus cohérente avec le reste du HTML.
Ainsi, un développeur front-end ne sera pas trop perdu dans l'utilisation de ces balises, même si il ne connait rien à Java.
La vidéo suivante présente JSTL et les principales taglibs.
Transparents présentés dans la vidéo
L'implémentation de base fournit différents types de balises regroupées dans différents espaces de nommage XML. Comprenez différents modules dont on identifiera le nom dans le préfixe de la balise. Il existe ainsi les tags "core" (c), les tags "xml" (x), les tags "format" (fmt) et les tags "sql" (sql).
JSTL 1.2 offre également des facilités pour la manipulation et l'affichage des données provenant du "model". Cela va se faire par ce qui est nommé "Expression Language" (EL). Une expression est une chaîne de caractères de type ${expression}
. "expression" peut simplement être le nom d'une variable du modèle ou une fonction plus aboutie fournie par EL.
Pour indiquer à notre compilateur JSP que notre page utilisera JSTL et EL, il suffit de placer cette déclaration de la taglib en haut de notre page JSP.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Ensuite les balises préfixées par "c" seront interprétées par le compilateur et généreront du code Java particulier.
La taglib "core" fournit un ensemble de tags permettant de gérer de l'affichage et affectation de variables, des boucles, des conditions, de la création d'URL en fonction du contexte, des redirections, etc.
Tag | Description |
---|---|
<c:out > | Identique à <%= ... >, mais pour les expressions. |
<c:set > | Affecte le résultat d'une expression à un 'scope' |
<c:remove > | Efface une variable (depuis un scope, si défini). |
<c:catch> | Gère les exceptions 'Throwable' qui surviennent dans le contenu du tag. |
<c:if> | Tag permettant de traiter une condition (if). |
<c:choose> | Tag permettant de gérer un ensemble de conditions exclusives (identique à switch/break). |
<c:when> | Sous-tag de 'choose' pour traiter une condition. |
<c:otherwise > | Sous-tag de 'choose' pour traiter tout autre cas que ceux indiqués dans 'when'. |
<c:import> | Affecte le contenu d'une page pointée par une URL à une variable. |
<c:forEach > | Permet de faire une boucle sur tout ce qui est 'Iterable' ou tableau. |
<c:forTokens> | Boucle sur une chaine possédant un séparateur défini (exemple 'chaine1,chaine2,chaine3'). |
<c:redirect > | Redirige l'utilisateur vers une nouvelle URL. |
<c:url> | Crée une URL absolue en fonction du contexte de la servlet, avec des paramètres ou non. |
<c:param> | Sous-tag de 'URL' permettant d'ajouter (ou remplacer) un paramètre à la Query String. |
Les autres taglibs ne devraient pas vous être utiles dans le cadre de ce cours.
Tous les objets affectés au modèle sont exposés de manière immédiate par les EL.
Pour reprendre l'exemple de la liste des auteurs, si l'on a fait ceci dans notre contrôleur :
List<Author> authors = dao.listAll();
model.addAttribute("authors", authors);
Alors, il sera facile de faire une itération sur nos auteurs dans la vue avec le bout de code :
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<h1>Auteurs</h1>
<c:choose>
<c:when test="${empty authors}">
Liste des auteurs vide
</c:when>
<c:otherwise>
<ul>
<c:forEach items="${authors}" var="author">
<li>${author.firstname} ${author.lastname}</li>
</c:forEach>
</ul>
</c:otherwise>
</c:choose>
Notez qu'il n'y a pas de "else" à la balise <c:if>
. Nous pouvons par contre utiliser "choose
" et "otherwise
" comme ici.${author.firstname}
" fonctionne, il est nécessaire d'avoir un getter sur la propriété "firstname". Par convention les propriétés d'un objet sont résolues selon la norme "javabeans". Donc, il faut créer des getters sur les propriétés que vous voulez exposer dans vos vues.
De nouvelles taglibs peuvent être créées afin d'enrichir les fonctionnalités offertes dans les vues.
Spring fournit une taglib "form" bien pratique pour manipuler les objets Java à éditer dans des formulaires HTML.
Apprenons par l'exemple en observant ce que cela peut donner sur nos auteurs.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<h1>Author</h1>
<form:form modelAttribute="author">
<form:input type="hidden" path="id" /> <br/>
firstname : <form:input path="firstname" /> <br/>
lastname :<form:input path="lastname" /> <br/>
<input type="submit" value="Enregistrer"/>
</form:form>
Vous pouvez consulter la documentation dédiée aux vues Spring et plus particulièrement la section "comment utiliser la taglib form".
Du côté de notre contrôleur, il sera nécessaire de distinguer deux opérations. Une première pour traiter l'affichage du formulaire (en GET) et une deuxième pour gérer l'enregistrement des données du formulaire (en POST) et mettre à jour les données dans la base. Quelques annotations nous seront utiles pour distinguer les deux opérations branchées sur la même URL. Une annotation @PathVariable
nous permettra d'extraire facilement une variable depuis l'URL. L'annotation @ModelAttribute
permettra de créer un objet automatiquement à partir des données du formulaire envoyé en POST. Toutefois, pour que cela fonctionne vous devez exposer des "setter" sur les propriétés de votre model selon la convention "javabeans".
Le code du contrôleur ressemblera au final à cela :
@RequestMapping(value="/author/{id}.html", method=RequestMethod.GET)
public String edit( Model model, @PathVariable("id") int id ) {
Author author = dao.find(id);
model.addAttribute("author", author);
return "author/edit";
}
@RequestMapping(value="/author/{id}.html", method=RequestMethod.POST)
public String save( Model model, @ModelAttribute Author author ) {
dao.update(author);
model.addAttribute("author", author);
return "author/edit";
}
Le screencast suivant vous montre comment utiliser JSTL et la taglib "form" de Spring sur un autre exemple.
Code présenté dans le screencast