4.7.Les balises personnalisées
(Taglib)
4.7.1.Présentation
Comme nous
l’avons expliqué précédemment, une page
JSP est une page de code qui peut contenir du HTML et du code JAVA.
Malgré la puissance offerte par le langage Java, il arrive
souvent que l’on réécrive plusieurs fois la même
chose au sein d'une même page JSP (boucles, tests, récupération
d'objets en session).
Afin
d’éviter ce type de perte de temps, un mécanisme
permettant d'effectuer ces tâches répétitives à
l'aide de balises personnalisées a été mis en
place. Ce mécanisme qui définit le fonctionnement de
nouvelles balises s'appelle taglib.
Permettant
d'isoler le code Java dans un fichier .java plutôt que dans un
fichier .jsp, ces taglib ont pour but de faciliter
l’organisation d’une réalisation d’un site
Web en JSP. Ceci est en effet fondamental pour le développement
et surtout la maintenance puisqu’on va permettre d'isoler
le travail des Web designers de celui des développeurs.
Ainsi, on
va avoir un fichier TLD qui va décrire les attributs de la
balise et un fichier JAVA qui va décrire les actions de la
balise.
4.7.1.1.Rôle du descripteur de
déploiement
Le
descripteur de déploiement est un fichier XML qui va permettre
au container de JSP l’accès au fichier TLD (en lui
indiquant le nom, l’emplacement dans le répertoire...).
Il est possible d’éliminer le rôle du descripteur
de déploiement en ajoutant des informations sur le nom et
l’emplacement du fichier TLD directement dans la page JSP.
Toutefois cela diminue la flexibilité, car lors de
changements, il convient de modifier tous les fichiers JSP utilisant
les customs Tags.
4.7.1.2.Rôle et format du
fichier TLD(Tag Librairy Descriptor)
Le fichier
TLD est un fichier XML qui va permettre de définir les
différentes balises personnalisées.
Syntaxe
d’un fichier TLD :
Balise
|
rôle
de la balise
|
<taglib>
|
Constitue
l’élément racine du fichier
|
<tlibversion>
|
version de la librairie de balise
|
<jspversion>
|
version des spécifications
JSP dont dépend la librairie de balise
|
<shortname>
|
nom court pour la librairie
|
<info>
|
informations pour la documentation
|
<uri>
|
lien vers une source additionnelle
de documentation identifiant de manière unique la librairie
|
<tag>
|
englobe la définition d’une
balise personnalisée
|
L’élément
tag
L’élément
tag va permettre de définir les différentes
caractéristiques de notre balise personnalisée à
l’aide des éléments suivants :
Nom
de l’élément
|
Rôle
de d’élément
|
name(obligatoire)
|
identifiant pour le tag
|
tagclass(obligatoire)
|
Nom de la classe correspondant à
la balise
|
teiclass
|
Nom de la classe d’info
concernant la tagclass
|
bodycontent
- Empty :pas
de contenu pour le tag
- JSP :
le corps peut être constitué d’éléments
JSP
- tagdependent : le corps
doit être interprété par ce tag
|
type de contenu
|
info
|
descriptions, infos
|
attribute
- name(obligatoire) :identifiant
- required :
(true,false)
- rtextprvalue:la valeur de cet
attribut peut être déterminé au moment de la
requête(true,false)
|
|
Exemple de fichier TLD
Dans cet
exemple, nous avons une classe JAVA que UpperTag.java qui va
permettre de mettre un texte en majuscule. Nous souhaitons donc
définir la balise correspondante dans notre fichier Desc.tld.
Fichier
Desc.tld :
<?xml version="1.0" encoding="iso-8859-1"
standalone="yes" ?>
<taglib>
<tlibversion>1.0</tlibversion>
<jsp-version>1.2</jsp-version>
<short-name>mesTags</short-name>
<description>Mes premiers Tags</description>
<tag>
<name>Majuscule</name>
<tag-class>UpperTag</tag-class>
</tag>
</taglib>
4.7.2.L’API JSP Custom Tag
La balise
personnalisée doit être reliée à un tag
handler qui va définir ses actions. Un tag handler est
une classe Java appelée chaque fois que le container de JSP
rencontre une balise personnalisée.
Cette
classe doit implémenter une interface du package
javax.servlet.jsp.tagext où dériver de l’une
des classes de ce package.
Les 3
interfaces les plus importantes sont Tag, IterationTag
et BodyTag.
4.7.2.1.L’interface Tag
public
interface Tag {
int
doEndTag();
int
doStartTag();
Tag
getParent();
void
release();
void
setPageContext(PageContext pc);
void
setParent(Tag t);
}
4.7.2.2.L’interface
IterationTag
L’interface IterationTag étend l’interface
Tag permet d’afficher plusieurs fois le contenu d’un
tag.
public
interface IterationTag {
int
doAfterBody();
}
La méthode doAfterBody() est appelée
après la méthode doStartTag() et peut
retourner Tag.SKIP_BODY ou Tag.EVAL_BODYAGAIN.
4.7.2.3.L’interface BodyTag
public
interface BodyTag {
void
doInitBody();
void
setBodyContent(BodyContent b)
}
L’interface
BodyTag étend l’interface IterationTag.
4.7.2.4.Le cycle de vie d’un
Tag Handler
Le cycle
de vie d’un tag handler est contrôlé par le
container de JSP :
- Dans
un premier temps, le container de JSP obtient une instance du tag
handler à partir du pool, ou en crée une nouvelle.
- Il
appelle ensuite la méthode setPageContext() à
laquelle il passe un objet PageContext
représentant la page JSP qui contient le custom tag.
- Le
container appelle ensuite la méthode setParent()
à laquelle il passe un objet Tag
(tag du parent) ou un objet null.
- Le
container de JSP définit ensuite tous les attributs du custom
tag. Les attributs sont traités comme les propriétés
dans un javabean (getters, setters)
- Le
container appelle ensuite la méthode doStartTag().
Celle-ci peut retourner les valeurs :
- Tag.SKIP_BODY
: Le tag ne renvoie rien, (Ex : Offre promotionnelle affichée
seulement pour les personnes abonnées)
- Tag.EVAL_BODY_INCLUDE
: Le container traite le corps du tag en tant que JSP et il est
affiché dans la page JSP (ce corps peut être constitué
de JSP, de HTML, et même d’autres tags)
- Quelle
que soit la valeur retournée précédemment, le
container appelle ensuite la méthode doEndTag().Cette
méthode retourne la valeur
- Tag.SKIP_PAGE
: pas de traitement pour le reste de la page JSP
- Tag.EVAL_PAGE
: reste de la page JSP traitée normalement.
- La
dernière méthode appelée est la méthode
release(). C’est au sein de cette méthode
qu’il est possible d’écrire du code de libération
de la mémoire (fermeture des connexions …).
- Enfin,
le container de JSP retourne une instance du tag handler dans le
pool.
4.7.2.5.Création d’un
custom tag
On peut
diviser les customs Tags en deux catégories ;
- Les
balises sans traitement de corps
Il s’agit
des balises comme les sauts de ligne (balise <br> en html) qui
ne vont pas nécessiter de modification de contenu.
Pour créer
une balise ne nécessitant pas de modification de contenu, on
va créer une classe étendant la classe TagSupport
qui elle-même implémente l’interface IterationTag:
public
class TagSupport {
int
doEndTag();
int
doStartTag();
static
Tag findAncestorWithClass(Tag from, Class classe);
String
getId();
Tag
getParent();
Object
getValue(String k);
Enumeration
getValues();
void
removeValue(String k);
void
setId(String id);
void
setPageContext(PageContext pageContext);
void
setParent(Tag t) ;
void
setValue(String k, Object o);
}
- Les
balises avec traitement de corps
Il s’agit
des balises comme des mises en gras ou en couleur (balises <b></b>
ou bien <font color></font> en html) qui vont modifier un
contenu.
Pour ce
type de balises, on va créer une classe étendant la
classe BodyTagSupport qui elle-même étend
la classe TagSupport et implémente l’interface
BodyTag :
public
class BodyTagSupport {
int
doAfterBody();
int
doEndTag();
void
doInitBody();
int
doStartTag();
BodyContent
getBodyContent();
JspWriter
getPreviousOut() ;
void
release() ;
void
setBodyContent(BodyContent b);
}
4.7.2.6.Syntaxe et utilisation d’un
custom tag
Lorsque
vous voudrez intégrer votre balise personnalisée dans
une page JSP, il suffira de tout d’abord de ‘déclarer’
la balise en début de page comme suit :
<%@ taglib
uri= ‘‘CheminBalisePerso’’ prefix=
‘‘PrefixeDuTag’’ %>
L’attribut
uri permet de spécifier le chemin où se trouve
le fichier TLD qui décrit la syntaxe de la balise, tandis que
l’attribut prefix permet de définir une instance
du custom tag.
Pour
utiliser votre balise personnalisée, il suffit alors
d’utiliser les expressions suivantes :
<
PrefixeDuTag:NomTag attribut1= ‘‘valeur’’/>
<
PrefixeDuTag:NomTag> body </tagprefix :Nomtag>
4.7.2.7.La classe BodyContent
Cette
classe hérite de javax.servlet.jsp.JspWriter. Elle
représente le corps du custom tag (lorsqu’il existe).
Le
BodyContent d’un custom tag peut être récupéré
à partir de la méthode setBodyContent(BodyContent
b) de l’interface bodytag à partir du paramètre
en argument de la méthode.
La
récupération du body se fait à l’aide de
la méthode getBodyContent()
String
content = bodyContent.getString() ;
Enfin,
l’écriture vers la page JSP se fait à l’aide
d’un PrintWriter joint au corps du tag
JspWriter
out = bodyContent.getEnclosingWriter() ;
4.7.3.La richesse des CustomTag
Les
CustomTag présentent une grande richesse dans la programmation
JSP. Là où l’on va pouvoir réellement
profiter de leur puissance, c’est en réutilisant des
taglibs prédéfinies, très complètes et
parfaitement réutilisables.
Les JSTL
(JavaServer Pages Standard Tag Library) sont des librairies de
référence. Elles contiennent toute une série de
balises personnalisées qui vont permettre, par exemple,
d’itérer, exécuter des requêtes SQL,
utiliser des documents XML.
Il existe,
par ailleurs de nombreuses autres librairies toutes aussi puissantes
les unes que les autres.
Voici
quelques liens où vous trouverez les plus connues :
http://jakarta.apache.org/taglibs/index.html
http://displaytag.sourceforge.net/install.html
http://struts.apache.org/userGuide/index.html
4.7.3.1.Les JavaServer Pages Server
TagLib
Les JSTL
présentent donc de nombreuses fonctionnalités. Nous
allons présenter quelques exemples d’utilisation.
Tout
d’abord, pour utiliser des balises de cette librairie, il faut
utiliser un conteneur d’application implémentant au
moins l’API servlet 2.3 et l’API JSP 1.2.
Tous les
fichiers nécessaires à leur utilisation se trouvent
dans le pack Java
Web Services Developer Pack v1.4.
Une fois
le dossier concerné(/jstl/) récupéré, il
faudra placer :
-les TLD (présents dans /jstl/tld/) dans le répertoire
/WEB-INF/tlds/
-les fichiers jstl.jar et standard.jar (présents dans
/jstl/tld) dans le répertoire /WEB-INF/lib
Les JSTL
présentent 4 librairies différentes :
- La
librairie Core représente les fonctions de base et est
associée au fichier TLD c.tld.
- La
librairie XML représente les traitements XML et est
associée au fichier TLD x.tld
- La
librairie I18n représente les fonctions
d’internationalisation de la page JSP et est associée
au fichier TLD fmt.tld
- La
librairie Database représente les traitements SQL est
associée au fichier TLD sql.tld
La
librairie Core
Cette
librairie concerne les balises de base telles que des balises de
condition, de gestion d’url ou d’itération.
- Les
balises d’expression de langage : out, set,
remove et catch.
La balise
out permet d’envoyer un flux de sortie à la page
JSP contenu dans l’attribut value. Elle prend, de plus
pour attributs default(valeur par défaut si value
est nulle) et escapeXml(booléen indiquant si les
caractères particuliers -<,>,&,é…-
doivent être convertis en leur équivalent HTML -<,
>,…-, true par défaut).
On notera
que cette balise doit contenir au moins l’attribut value
et ne doit pas contenir de corps.
Exemple :
<coreTag :
out value = « Hello ! »
default= « default value » escapeXml=
« true » />
La balise
set permet de stocker une variable dont on va définir
la portée de visibilité.
Elle
permet d’ « instancier » une
variable, à l’aide des attributs var(nom de la
variable) et value(valeur à stocker) ou bien de
modifier les valeurs d’un objet bean, à l’aide des
attributs target(nom de la variable contenant le bean),
property(nom de la propriété du bean) et value.
C’est ensuite l’attribut scope qui va permettre de
spécifier la portée de visibilité de la
variable. Il peut prendre en paramètre les valeurs suivantes :
page, request, session et application.
Exemple 1:
<coreTag :
set value = « Hello ! »
var = « mess » scope=
« page »/>
Exemple 2:
<coreTag :
set value = « Hello ! »
target= « monBean » property=
« nomB » scope= « page »/>
Pour
récupérer la valeur de la variable, on va pouvoir
utiliser la balise out vue précédemment en
utilisant la syntaxe suivante ${nomvariable}:
Exemple :
<coreTag :
out value = « ${pageScope.mess} »
default= « default value » es
capeXml= « true » />
Si on ne
précise pas la portée de la variable dans l’attribut
value (value= « ${mess} »), elle
sera , par défaut recherchée dans la page, puis dans la
requête, la session , et enfin dans l’application.
La balise
remove permet de supprimer une variable. Il suffit pour cela
de spécifier le nom de la variable dans l’attribut var
et la portée de cette variable dans l’attribut scope.
La balise
catch, comme son nom l’indique, permet d’attraper
les exceptions. Le code risquant de lever une exception doit être
encapsulé entre les balises catch. L’attribut var
qui contient les informations concernant l’exception levée
possède une propriété message qui va
permettre d’afficher un message d’erreur.
Exemple :
<coreTag :
catch var = « Erreur » >
<%--code
risquant de lever une exception
</coreTag :catch>
<coreTag :
out value= « ${Erreur.message} »/>
- Les
balises de condition et d’itération : if,
choose, forEach, forTokens.
- Les
balises de gestion d’url : import, url,
redirect.
|