CHAPITRE 2
APPLICATIONS WEB :
SERVLETS, JSP
Frédéric MOAL Cours PnT
Université d’Orléans Licence 3 version 01/2019
Plan
Introduction et rappels
Applications Web
http/HTML
Scripts cgi
Servlets
JSP
Tag lib
Ressources IHM
Documentation Apache : [Link] dans la
version des servlets/JSP de tomcat utilisée
Le site officiel de Oracle [Link]
« Cours » en ligne:
Jean Michel DOUDOUX - "Développons en Java" (2599pages)
[Link] Faîtes vous votre propre
Tutos de Vogella [Link] librairie de tutos !
- bookmarks,
Intranet Michel Buffa, MIAGE Nice - [Link]
[Link] - Pocket
[Link] - Zotero
[Link] - …
Blogs :
Xebia, Ippon tech., SQLI, Le touilleur express, Java Posse, Bistro!, ...
Les cast codeurs podcast, [Link] [Devoxx / FR]
Twitter
Rappels
Java [2, 5, 6, 7,8 et 9]
Html[5] :
[Link]
CSS[3] :
[Link]
Eclipse / IntelliJ
Gestion de version (Git)
…
=> Cf ressources et web
Plan
Introduction
Applications Web
http/HTML
Scripts cgi
Servlets
JSP
Tag lib
Applications « Web »
Protocole http :
Repose sur TCP [Au cours Réseaux tu te
réfèreras]
Client http Envoi d’une commande
get "/…/[Link]"
Serveur http
Contenu du fichier
/…/[Link]
Protocole HTTP
Une Piqure de « rappel » tu auras
Le Protocole HTTP
HyperText Transfer Protocol
Protocole d’échanges d’information sur le web
Basé sur TCP
Version courante 1.1
Maintenant 2.0
URL
Unique Resource Location
Identifie les ressources de manière unique sur le Web
5 parties
Protocole (http, ftp, mail, …)
Host ([Link])
Port (8080, 80)
Path (Chemin vers la ressource sur le serveur)
Paramètres
[Link]
[Link]
Protocole Nom du serveur et Chemin de la Paramètres
port ressource
Enchainements Client - Serveur
Requête HTTP
Permet à un client d’envoyer des
messages à un serveur
Format d’un message HTTP
Request Message Header
Request Line
Request Headers [Optional]
Request Message Body
Requête HTTP
Requête envoyée par un client http vers
Ressource/
un serveur Document Version du
demandé! protocole
Image, HTML, utilisée : 1.0
Methode de ou 1.1 ou 2.0
JSON, XML…
la requete
GET, POST,
<Méthode> <URI> HTTP/<version>
PUT…
[<Champ d’en-tête> : <valeur>]
Ligne blanche
[Corps de la requête]
Informations
concernant le
client HTTP, Donnée envoyée
l’utilisateur au serveur, prise
(cookies, en compte pour
localisation) les requêtes de
type POST ou PUT
Réponse HTTP
Réponse du serveur au client :
Response Message Header
Response Line
Response Headers
Response Message [Optional]
Réponse HTTP
Réponse du serveur à une requête du
client Statut de la
réponse Information
caractérisé par des descriptive
Version du
codes prédéfinis sur le
protocole
par le protocole statut
utilisée : 1.0 ou
http : 200/404/500
1.1 ou 2.0
HTTP / <Version> <Statut> <Commentaire>
Content Type : <Type MIME du contenu>
[<Champ d’en tête>: <valeur>]
Ligne blanche
Informations <Contenu> Information sur
concernant le le type MIME du
serveur contenu:
XML/html/JSON
Exemple
Une démo ?
Autre exemple : Request
Request Line
POST /bibliotheque/faces/views/categorie/[Link] HTTP/1.1
Request Headers
Host: localhost:8080
Connection: keep-alive
Content-Length: 176
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/
*;q=0.8
Origin: [Link]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
39.0.2171.65 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: [Link]
Accept-Encoding: gzip, deflate
Accept-Language: fr,fr-FR;q=0.8,en;q=0.6
Cookie: JSESSIONID=d64a9484e61761662575b5d14af1
Autre exemple : Request
Request Message Body
j_idt13:nom:Toto
j_idt13:description:Hello
Response Message Header
Response Line
HTTP/1.1 200 OK
Response Headers
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish
Server Open Source Edition 4.0 Java/Oracle
Corporation/1.8)
Server: GlassFish Server Open Source Edition 4.0
Content-Type: text/html;charset=UTF-8
Date: Sun, 23 Nov 2014 [Link] GMT
Content-Length: 2274
Response Message Body
Response Body
<html xmlns="[Link]
xmlns="[Link]
<head><link
type="text/css" rel="stylesheet"
href="/bibliotheque/faces/[Link]/[Link]?
ln=primefaces-aristo" />
<link type="text/css" rel="stylesheet"
href="/bibliotheque/faces/[Link]/css/[Link]" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Create New Categorie</title></head><body>
<h1>Create New Categorie
</h1>
<p><div id="messagePanel"><table><tr style="color: green"><td>Categorie
was successfully created. </td>
</tr></table></div>
</html>
Retours d’information
Une fiche mémo :
[Link]
nse-codes-and-what-they-mean/
Doivent être interprétés correctement par le
client, et émis correctement par le serveur !!!
De nombreuses autres méthodes…
HTTP définit un ensemble de méthodes qui
permet de caractériser les types de
requêtes
GET : Récupérer des ressources à un serveur
POST : Envoyer des données à un serveur
PUT : Modifier des données
DELETE : Suppression de données
OPTIONS : Demander la liste des méthodes
supportées par un serveur
Autres : HEAD, TRACE, CONNECT, PATCH
Un peu d’histoire : CGI
Dynamique tu seras (ou tu essaieras
au moins)
Première approche : CGI
Normalisation « système » pour
introduire des pages non statiques
Idée simple : lancer un programme à
chaque requête pour générer un contenu
dynamique
Pourquoi pas des Shell ? Bash, perl, …
Run d’un programme et récupération de
la sortie du programme, et on renvoie le
tout au navigateur !
Appli web : les scripts CGI
Formulaire html : submit
Les paramètres saisis dans le formulaire
sont transmis à un script (GET : dans
l’URL, POST : dans le corps)
Le script récupère les paramètres,
effectue son traitement et génère
(imprime) la page html résultat
Pages dynamiques par script CGI
Exemple simple avec un formulaire
<html>
<head>
<title>Mon formulaire</title>
</head>
<body>
<h1>Titre de page</h1>
<form method="get" action="cgi-bin/Enreg">
Nom : <input type="text" name="nom">
<input type="submit" value="OK">
</form>
</body>
</html>
Pages dynamiques par
script CGI
Servlet
Les leçons tu retiendras
Servlets
Programme : pourquoi pas en Java ?
Alternative à la programmation avec CGI
Il s'agit de programmes exécutés sur un
serveur
servent de couche intermédiaire entre
une requête provenant d'un navigateur
Web et un autre service HTTP, comme
des bases de données ou des
applications du serveur HTTP
Servlets
Technologie Servlets : pourquoi
Java ?
indépendant / OS et serveurs Web
Accès aux API de Java
Annotations JEE
mieux que CGI car compilé, prise en
charge connexion des utilisateurs en
multithread…
Scalable sans changer le code source !!!
Servlets
Différences Servlets / scripts CGI
Performances
une seule machine virtuelle Java sur le
serveur
servlet reste placée en mémoire une fois
appelée
servlet modifiée peut être réactivée sans
redémarrage serveur ou application
Modularité
possibilité
d’avoir plusieurs servlets, chacune
pouvant accomplir une tâche spécifique
Servlets : architecture
Servlets
Tâches de la servlet :
1. Lire toutes les données envoyées par l'utilisateur (d’un
formulaire, d'une applet Java ou d'un prog. client HTTP)
2. Chercher d'autres informations sur la requête, à l'intérieur de
la requête HTTP (cookies, nom de l'hôte, …, etc. )
3. Générer des résultats (calculs, communication avec la base de
données, …)
4. Formater le résultat dans un document (incorporation des
informations dans une page HTML)
5. Définir les paramètres de la réponse HTTP appropriés (type de
document, définir les cookies, mémoriser les paramètres…
6. Renvoyer le document au client au format texte (HTML), au
format binaire (images GIF), ou dans un format compressé
comme gzip
Servlet
Bon OK mais en dev ça donne quoi ?
Servlets
L ’API pour les servlets constituée de deux
packages :
[Link]
[Link]
Librairie Servlet avec chaque serveur d’application Java
<<interface>> <<interface>> <<interface>>
GenericServlet
Servlet ServletRequest ServletResponse
<<interface>> <<interface>>
HttpServlet
HttpServletRequest HttpServletResponse
MaServlet
Architecture d’une Servlet
La classe HttpServlet
Rôle = traiter la requête HTTP
Pour chaque méthode HTTP : GET, POST, PUT,
DELETE, etc. il y a une méthode
correspondante :
doGet(…) – répond aux requêtes HTTP GET
doPost(…) – répond aux requêtes HTTP GET
doPut(…), doHead(…), doDelete(…), doTrace(…),
doOptions(…)
Conseil : implémenter au moins les deux
premières méthodes ou redéfinir la méthode
service(…)
Servlet HTTP et servlet générique
G e n e r ic S e r v le t
C lie n t
S erv er
req u est
resp o n se
s e r v ic e ( )
H T T P S e r v le t
B ro w ser
H T T P S erver
req u est
doG et ( )
resp o n se
s e r v ic e ( )
d o P o s t( )
Architecture d’une Servlet (2)
Ces méthodes ont deux paramètres : la requête et
la réponse
L’objet HttpServletRequest
Contient la requête du client
En-tête de la requête HTTP
ParamètresHTTP (données de formulaire ou paramètres
passés avec l’URL)
Autres données (cookies, URL, chemin relatif, etc.)
L’objet HttpServletResponse
Encapsule les données renvoyées au client
En-tête de réponse HTTP (content type, cookies, etc.)
Corps de la réponse (en tant que OutputStream)
Architecture d’une Servlet (3)
La méthode HTTP GET est utilisée quand :
Le traitement de la requête ne modifie pas l’état du
serveur,
Si jamais il s’agit de l’envoi d’un formulaire, taille des
données < 255 caractères,
On veut pouvoir bookmarker l’URL
La méthode HTTP POST est utilisée quand :
Le traitement change l’état du serveur : exemple
classique = un insert dans une base de données.
La quantité de données à envoyer est importante,
On veut cacher dans l’URL les paramètres (ex : mot
de passe)
Servlets API
Fonctions principales d’une Servlet :
Traiter les paramètres HTTP reçus dans la
requête (GET ou POST)
[Link](String)
Récupérer un paramètre de configuration de
l’application web (dans le descripteur [Link])
[Link]()
Récupérer un élément de l’en-tête HTTP
[Link](String)
Servlets API (2)
Spécifier dans le header de réponse le type
[Link](<name>, <value>) /
[Link](String)
Récupérer un Writer pour écrire la réponse
[Link]()
…ou un flux binaire si la réponse est binaire
[Link]()
Rediriger la requête vers un autre URL
[Link]()
Des exemples ?
De nombreux tu testeras
Exemple 0 simple de servlet
import [Link];
import [Link]; Import des classes
import [Link]; de servlets
import [Link];
import Redéfinition
[Link];
Redéfinition
import [Link];
de
de doGet(…)
doGet(…)
Hérite de Request
Request et
et Response
Response ::
public class Premiere extends HttpServlet { HttpServlet contexte
contexte d’appel
d’appel et
et de
de
retour
retour
protected void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException { Propagation
[Link]("text/html"); des exceptions
Réponse
PrintWriter out = [Link]();
[Link]("<HTML>"); en html
[Link]("<HEAD><TITLE>Première servlet</TITLE></HEAD>");
URL
URL d’accès
d’accès
[Link]("<BODY><H1>Ma première servlet</H1></BODY>");
à la servlet
à la servlet
[Link]("</HTML>");
} Le
Le code
code html
html
renvoyé
renvoyé
}
Exemple 1 : « dynamique »
import [Link].*;
import [Link].*;
import [Link].*;
public class DateServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// A éviter, normalement pas de HTML dans une servlet
PrintWriter out = Res [Link]();
[Link]("<HTML>");
[Link]("The time is: " +
new [Link]());
[Link]("</HTML>");
}
}
Exemple 2 : paramètres
Utilisation classique :
enchainement d’un formulaire de saisie
html qui appelle une servlet en cas de
validation (<form>)
Page html [[Link]] -> Servlet
[[Link]]
Servlets
Servlet [Link]
Servlet : exemple de formulaire
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"[Link]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Un formulaire de saisie</title>
</head>
<body>
<form method="get" action="TraiteFormulaire">
Titre : <select name="titre">
<option>Mr</option><option>Mme</option>
</select><br>
Prénom : <input name="prenom"><br>
Nom : <input name="nom"><br>
Mot de passe : <input name="motdepasse" type="password"><br>
<input type="submit"><input type="reset">
</form>
</body>
</html>
Servlet : traitement du formulaire
public class TraiteFormulaire extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
[Link]("text/html");
PrintWriter out = [Link]();
[Link]("<HTML>");
[Link]("<HEAD><TITLE>Deuxième servlet</TITLE></HEAD>");
[Link]("<BODY><H1>Bonjour ");
String titre = [Link]("titre");
if ([Link]("Mr")) {
[Link]("monsieur ");
} else if ([Link]("Mme")) {
[Link]("madame ");
} else throw new RuntimeException("Mauvais titre");
[Link]([Link]("nom")+",<br>");
String motdepasse = [Link]("motdepasse");
[Link]("Votre mot de passe comprend "+[Link]()+ "
caractères.");
[Link]("</H1></BODY>");
[Link]("</HTML>");
}
Servlet qui construit et sert une image
On veut faire une Servlet qui construit une
image avec un texte dedans : un
compteur de vues.
La Servlet maintient un compteur
On l’initialise dans la méthode init() et on
l’incrémente dans la méthode doGet()
La Servlet produit une image binaire
Le Content-type doit être "image/jpeg"
Image Counter Servlet (1)
import [Link].*;
import [Link].*;
...
public class ImageCounterServlet extends HttpServlet {
private String mStartDate;
private int mVisitCounter;
public void init() {
mStartDate = (new Date()).toString();
mVisitCounter = 0;
}
public BufferedImage createImage(String msg) {
... // ici on crée une image, on dessine un texte
// dedans et on renvoie l’image sous forme de
// BufferedImage (buffer binaire)
}
Image Counter Servlet (2)
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
String msg;
// Rappel les servlets sont ré-entrantes !
synchronized(this) {
mVisitCounter++;
msg = "" + mVisitCounter + " visits since" +
mStartDate;
}
BufferedImage image = createImage(msg);
[Link]("image/jpeg");
OutputStream out = [Link]();
// Encode l’image en jpeg et l’écrit sur le flux
// binaire de la réponse
[Link](image, "jpg", out);
}
}
Extrait du code de création de l’image
// Create an image of our counter to be sent to the browser.
BufferedImage buffer = newBufferedImage(50, 20,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = [Link]();
[Link](RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
[Link](new Font("Monospaced", [Link], 14));
[Link]([Link]);
[Link](0, 0, 50, 20);
[Link]([Link]);
[Link](msg, 0, 20);
return buffer;
Résultat
Renvoyer un zip depuis une
Servlet
Exemple de [Link]
protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
try {
String path = getServletContext().getRealPath("data");
File directory = new File(path);
String[] files = [Link]();
if (files != null && [Link] > 0) {
byte[] zip = zipFiles(directory, files);
ServletOutputStream sos = [Link]();
[Link]("application/zip");
[Link]("Content-Disposition", "attachment;
filename=\"[Link]\"");
[Link](zip); [Link]();
}
} catch (Exception e) {
[Link]();
}
}
Servlets : contexte Request
HttpServletRequest hérite de ServletRequest
Cet objet encapsule la requête HTTP et fournit des
méthodes pour accéder aux informations
du client
de l'environnement du serveur
Exemples de méthodes
String getMethod() : retourne le type de requête
String getServerName() : retourne le nom du serveur
String getParameter(String name) : retourne la valeur d'un
paramètre
String[ ] getParameterNames() : retourne le nom des les
paramètres
String getRemoteHost() : retourne l'IP du client
String getServerPort() : retourne le port sur lequel le serveur
écoute
… (voir l'API Servlets pour le reste)
Servlets : exemple de contexte
Récupérer l’URL relatif de la
servlet
Permet d’obtenir des informations depuis le
header de la requête. Ex : chemin relatif
utilisé pour appeler la servlet :
public class ContextPathDemo extends HttpServlet {
protected void doGet(HttpServletRequest req,
HttpServletResponse res) throws ServletException,
IOException {
// [Link]() returns the
// portion of the request URI that indicates the
//context of the request.
String contextPath = [Link]();
}
}
URI relatif à quoi cela sert-il ?
Dans le cas où une même servlet est
mappé sur plusieurs URLs,
Exemple, une Servlet qui streame des
fichiers mp3 dans /mp3/* a besoin de
récupérer le nom des fichiers…
/mp3/toto.mp3, /mp3/titi.mp3, on a
besoin de récupérer toto.mp3 pour
l’ouvrir…
[Link]().substring([Link]
ntextPath().length()) renvoie la fin de
l’URI sans le contexte de déploiement
Servlet : contexte Response
HttpServletResponse hérite de ServletResponse
Cet objet est utilisé pour construire un message de
réponse HTTP renvoyé au client, il contient
les méthodes nécessaires pour définir le type de contenu, en-
tête et code de retour
un flot de sortie pour envoyer des données (par exemple
HTML) au client
Exemples de méthodes
void setStatus(int) : définit le code de retour de la réponse
void setContentType(String) : définit le type de contenu MIME
ServletOutputStream getOutputStream() : flot pour envoyer
des données binaires au client
void sendRedirect(String) : redirige le navigateur vers l'URL
Conteneur de Servlets =
serveur
Une application WEB peut contenir plusieurs
Servlets
Pour tester et déployer une Servlet, il faut un
système d'exécution appelé conteneur de
Servlets
Le conteneur réalise le lien entre la Servlet et le
serveur WEB
Transforme code Java (bytecode) en HTML
Associe à des URL's virtuels une Servlet
Conteneur de Servlet
Plusieurs implémentations possibles :
Apache Httpd
Apache Tomcat
Jetty
Weblogic
Websphere
Wildfly
…
On démarre un serveur puis on déploie une ou plusieurs
applications
Souvent par copie du fichier war dans un répertoire du serveur
La plupart des serveurs proposent une interface web
d’administration qui permet de le faire
Conteneur de Servlets
Une application WEB est contenue dans un
répertoire physique sur le serveur (exploded) ou
dans un WAR [<packaging>war</packaging>]
Une application WEB possède une hiérarchie de
répertoires et de fichiers :
Et pour nous ?
[Link] !
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link] [Link] >
<modelVersion>4.0.0</modelVersion>
<groupId>[Link]</groupId>
<artifactId>monprojet</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
Fichier descripteur [Link]
C’est un fichier XML, standard Java EE
Ce fichier contient un nombre important
d’informations concernant l’application web Java
L’URL de la page ou de la servlet de démarrage,
Les associations classes de servlets -> nom de
servlets et nom de servlet -> URL
Des paramètres d’initialisation (ex : email de
l’admin, server SMTP, activer des traces, etc)
Servlet-filters : association de Servlets à ensemble
d’URLs
Permet de déclarer des classes comme écouteurs de
certains aspects de l’application
Fichier de déploiement
Ce fichier [Link] doit être placé dans
WebContent/WEB-INF
Généré automatiquement (Eclipse…) ou
défini « à la main »
N’est plus obligatoire depuis les Servlet
3.0 [le dire à maven-war-plugin ! Sinon
pas happy il sera]
[Link] : exemple
[Link] : exemple
Chemins virtuels
Maping URL - Servlet
La spécification des Servlets impose l’algo de
recherche : [[Link]
spec/Final/servlet-3_1-[Link]]
Part de l’URL complète et essaie de matcher le
plus spécifique
Essaie récursivement en enlevant la fin (/)
Si il y a une extension (eg .jsp), cherche un match
dessus
Si rien ne match, cherche un servlet par défaut
Attention, restrictions dans les matchs (eg /run/
* ok mais pas /run*)
Et comment qu’on run ?
Les differents « web listeners »
(écouteurs/callbacks)
Par exemple on peut déclarer une classe qui
implémente ServletContextListener et dont
la méthode contextInitialized sera appelée
au déploiement de l’application
Ex : remplir la base de données avec des
données de test, créer des comptes pour
l’admin, etc
Ou encore compter le nombre de session
ouvertes pour afficher combien de personnes
sont « online » sur le site
On va utiliser un SessionListener
Déclaration dans le
[Link]
<listener>
<description>
Classe pour remplir la base au déploiement
</description>
<listener-class>[Link]</listener-class>
</listener>
Classe de remplissage de la BD au
déploiement
public class InitApplication implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
[Link]("##### BASE CREE ######");
[Link]();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
…
}
SessionListener : compter les personnes
online. Dans le [Link]
<listener>
<listener-class>
[Link]
</listener-class>
</listener>
Classe écouteur
public class SessionCounter implements HttpSessionListener {
private List sessions = new ArrayList();
public SessionCounter() { }
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = [Link]();
[Link]([Link]());
[Link]("counter", this);
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = [Link]();
[Link]([Link]());
[Link]("counter", this);
}
public int getActiveSessionsNumber() {
return [Link]();
}
}
Affichage dans une page
JSP
<html>
<head>
<title>Session Counter</title>
</head>
<body>
Nombre de personnes online sur le site :
${activeSessionsNumber}
</body>
</html>
REMARQUE : ${activeSessionsNumber} va
chercher une propriété activeSessionsNumber
dans la page, la requête, la session, le contexte,
jusqu’à la trouver. Appelle
getActiveSessionsNumber()… Si page JSF,
Servlet : paramètres d’init
Possibilité d’utiliser des paramètres
d’initialisation
TRES utile pour la mise en production
Les paramètres d’initialisation sont définis
dans le fichier [Link] de l’application WEB
Exemple de paramètres d’initialisation
<init-param>
<param-name>compressionThreshold</param-name>
<param-value>10</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
Récupération des initParams, ici dans un
écouteur, au déploiement
public void contextInitialized(ServletContextEvent event)
{
[Link] = [Link]();
String comp =
[Link]("compressionThreshold");
log("contextInitialized()");
log("compression= " + comp );
}
Ici dans une Servlet
public void init() {
[Link]("text/html");
PrintWriter writer = [Link]();
ServletContext context = getServletContext();
String logPath = [Link]("[Link]");
[Link]("Log Path: " + logPath + "<br/>");
Enumeration enumeration = [Link]();
while ([Link]()) {
String paramName = (String) [Link]();
String paramValue = [Link](paramName);
[Link]("Context Init Param: [" +
paramName + " = " + paramValue +"]<br/>");
}
}
Servlet : cycle de vie
Entre chaque requête du client les Servlets
persistent sous forme d’instances d’objet
Au moment où le code d’une Servlet est
chargé, le serveur ne crée qu’une seule
instance de classe
L’instance (unique) traite chaque requête
effectuée sur la Servlet
Les avantages (rappels)
L’empreinte mémoire reste petite
Le surcoût en temps lié à la création d’un nouvel
objet pour la Servlet est éliminé
La persistance est possible c’est-à-dire la
possibilité de conserver l’état de l’objet à
chaque requête (un exemple le compteur)
Cycle de vie d’une Servlet
• Le serveur gère ce New Destroyed
cycle,
Running
• Les méthodes init() destroy()
“callback” du cycle de
vie ne doivent jamais ...()
service()
être appelées par le
code qu’on écrit doGet()
doDelete()
doPost() doPut()
On implémente souvent la méthode init
(invoquée lors de la première exécution de la
servlet) pour récupérer des ressources ou
paramètres d’initialisation.
Servlet : cycle de vie
A chaque rechargement d’une Servlet par le
conteneur de Servlet, il y a création d’une
nouvelle instance et donc destruction de
l’ancienne
Le rechargement d’une Servlet a lieu quand il y a :
Modification d’au moins une classe de l’application
WEB
Demande explicite de l’administrateur du serveur
WEB
Redémarrage du conteneur de Servlets
CF problèmes en TP !!!
Servlet : cycle de vie
Un constat : il n’y a pas de
constructeur dans une Servlet
L’initialisation des attributs se fait par
l’intermédiaire de la méthode init()
Elle ne possède pas de paramètre
Définie et implémentée dans la classe
abstraite GenericServlet
La méthode init() peut être appelée à
différents moments
Lorsque le conteneur de Servlets démarre
Lors de la première requête à la Servlet
Sur demande explicite de l’administrateur
du serveur WEB
Servlet : cycle de vie
Une Servlet doit libérer toutes les ressources qu’elle
a acquises et qui ne pourront être passées au
ramasse-miettes
Exemples de ressources
Connexion à une base de données
Ouverture d’un fichier sur le disque serveur
La méthode destroy() donne une dernière chance
d’écrire les informations qui ne sont pas encore
sauvegardées
La méthode destroy() est également utilisées pour
écrire les informations persistantes qui seront lues
lors du prochain appel à init()
Servlets 3.0
Comme on est pas là pour faire du « XML
Sitting », le modèle 3.0 a apporté de
nombreuses annotations qui évitent de
remplir le fichier [Link].
possibilité de ne pas avoir de fichier
[Link] [Tomcat 7, 8…]
Utilisation d’annotations directement
dans le code
Pour des applications simples il est
facultatif
Nécessaire encore pour certaines tâches
Et pour nous ?
Pom !
<dependency>
<groupId>[Link]</groupId>
<artifactId>[Link]-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
Annotations Servlets 3.0
@WebServlet(asyncSupported = false,
name = "HelloAnnotationServlet",
urlPatterns = {"/helloanno"},
initParams = {@WebInitParam(name="param1",
value="value1"),
@WebInitParam(name="param2",
value="value2")} )
public class HelloAnnotationServlet extends HttpServle
{..}
Récupération des init params dans doGet() ou doXXX()
par :
getInitParameter("param1");
Annotations pour file upload
@WebServlet("/[Link]")
@MultipartConfig(location="c:\\tmp", fileSizeThreshold=1024*1024,
maxFileSize=1024*1024*5, maxRequestSize=1024*1024*5*5)
public class FileUploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException
{
[Link]("text/html");
PrintWriter out = [Link]();
Collection<Part> parts = [Link]();
[Link]("<h2> Total parts : "+[Link]()+"</h2>");
for(Part part : parts) {
printPart(part, out);
[Link]("samplefile");
}
}
Code qui créer le fichier
private void printPart(Part part, PrintWriter pw) {
StringBuffer sb = new StringBuffer();
[Link]("<p>");
[Link]("Name : "+[Link]());
[Link]("<br>");
[Link]("Content Type : "+[Link]());
[Link]("<br>");
[Link]("Size : "+[Link]());
[Link]("<br>");
for(String header : [Link]()) {
[Link](header + " : "+[Link](header));
[Link]("<br>");
}
[Link]("</p>");
[Link]([Link]()); }
Code du formulaire d’envoi
<html>
<body>
<p>Commons File Upload Example</p>
<form action="uploadServletl"
enctype="multipart/form-data" method="POST">
<input type="file" name="file1"><br>
<input type="Submit" value="Upload File">
<br>
</form>
</body>
</html>
Compléments sur l’envoi de fichiers en
multipart (1)
Attention, si le formulaire d’envoi possède
des champs classiques ou « hidden » en
plus du ou des fichiers, leurs valeurs ne
seront pas accessible dans la Servlet par
[Link](nomDuParam)
Valeur null renvoyée, faire getPart() à la
place !
A la place :
private String getParamFromMultipartRequest(HttpServletRequest
request, String paramName) throws IOException, ServletException {
Part part= [Link](paramName);
Scanner scanner = new Scanner([Link]());
String myString = [Link]();
return myString;
}
Compléments sur l’envoi de fichiers en
multipart (2)
Si on ne préciser pas le paramètre location
dans l’annotation :
@MultipartConfig(location="…" )
Les fichiers écrits par [Link]() iront dans
le chemin où est exécuté le projet
Si on veut que les fichiers aient un URL
valide (soit affichables dans une page)
Location = un espace visible par le serveur
HTTP, soit le docroot, soit le répertoire web
(ou un sous-répertoire) de votre projet
Annotation ServletFilter
@WebFilter(urlPatterns={"/*"}, description="Request timer filter")
public class TimerFilter implements Filter {
private FilterConfig config = null;
@Override
public void init(FilterConfig config) throws ServletException {
[Link] = config; [Link]().log("TimerFilter
initialized");
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
long before = [Link](); [Link](req, resp);
long after = [Link]();
String path = ((HttpServletRequest)req).getRequestURI();
[Link]().log(path + " : "+(after-before));
}
}
Cookies en Java
[Link]
Un cookie a un nom, une valeur, des attributs : comment, path et
domain, un âge maximum, et un numéro de version.
Une Servlet envoie les cookies au navigateur à l’aide de la
méthode :
[Link]([Link])
Cette méthode ajoute les cookies à la réponse,
Max 20 cookies par site/utilisateur, 300 cookies au total, Ko par
cookie.
Question : et HTML5 local et session storage ?
Le navigateur envoie les cookies au serveur via les requêtes HTTP
(dans le header)
Les Cookies sont récupérées à l’aide de la méthode
[Link]( ). Plusieurs cookies peuvent avoir
le même nom mais un “path” différent.
Méthodes de manipulation
Un cookie est une instance de la classe
[Link].
public Cookie(String name, String value): créée
un cookie avec la paire nom-valeur.
Cookie c = new Cookie(“id”,”12345”);
public string getName( ) : renvoie le nom
public string getValue( ) : renvoie la valeur
public void setValue(String val) : change la
valeur
public void setMaxAge(int expiry) : permet de
donner la durée de vie maximum du cookie en
secondes.
Méthodes de manipulation (2)
public void setPath([Link] uri) : Spécifie le
chemin pour lequel le client doit renvoyer le cookie.
Le cookie sera visible pour toutes les pages dans le
chemin ou dans le sous-chemin
Le chemin d’un cookie doit inclure la servlet qui a
créé le cookie, par exemple, /catalog, ce qui rend le
cookie visible pour toutes les pages sous /catalog.
public [Link] getPath() : Renvoie le chemin
d’un cookie
public String getDomain( ) : renvoie le domaine
if [Link](“.[Link]”)
… // faire un traitement
public void setDomain(String _domain): change le
domaine
Méthode doGet utilisant les
cookies
public void doGet(HttpServletResponse req,
HttpServletResponse res)
throws ServletException, IOExceiption{
[Link](“text/html”);
PrintWriter out = [Link]( );
[Link] (“<H1>Contents of your shopping
cart:</H1>”);
Cookie cookies[ ];
cookies = [Link]( );
if (cookies != null) {
for ( int i = 0; i < [Link]; i++ ) {
if (cookies[i].getName( ).startWith(“Item”))
[Link]( cookies[i].getName( ) + “: “ +
cookies[i].getValue( ));
Rappel : Session HTTP ?
Une session permet de conserver l’état de ce que
fait l’utilisateur
Le contenu d’une session est persistant entre
plusieurs requêtes HTTP
Une session est individuelle et dépend du
navigateur, de l’URL (ou famille d’URLs) qu’on
consulte
Ex : gestion de Login / password (état dans la
session : connecté ou pas)
Formulaires multi-page (Wizards… next next ok)
Paniers virtuels
Préférences utilisateurs, etc.
Gestion de sessions dans les
Servlets
Il existe une « Servlet session API »
Permet de récupérer un objet HttpSession
à partir de la requête
(HTTPServletRequest)
L’objet HTTPSession est une HashMap Java.
Gestion des objets dans la session : ajout,
modification, retrait, recherche, etc.
Gestion des méta-information à propos de
la session elle-même : date de création, id
de la session, etc.
Récupérer l’objet session
Utiliser cette méthode :
[Link]()
Exemple:
HttpSession session = [Link](true);
Retourne la session en cours, en crée une
(true) si il n’en existe pas.
Pour savoir si il s’agit d’une nouvelle session
utiliser la méthode isNew() de la session
Il existe des écouteurs du cycle de vie de la
session (on verra plus tard).
En coulisse…
Quand on appelle getSession(true) chaque
utilisateur se voit attribuer un Session ID
Le Session ID est communiqué au client
Option 1: si le navigateur supporte les cookies,
la Servlet créée un cookie avec le session ID,
dans Tomcat, ce cookie est appelé JSESSIONID
Option 2: si le navigateur ne supporte pas
les cookies, la servlet va essayer de
récupérer le session ID depuis l’URL
Récupérer des données de la
session
L’objet session fonctionne comme une HashMap
Peut stocker n’importe quel type d’objet,
Les objets ont une « clé d’accès » comme dans les
Maps Java
Exemple de récupération :
Integer accessCount =
(Integer) [Link]("accessCount");
Récupérer toutes les « clés » de tous les objets
dans la session :
Enumeration attributes =
[Link]();
Mettre des données dans la
session
Les objets que l’on met dans la sessions
sont des “attributs” :
HttpSession session = [Link]();
[Link]("nom", "Pierre Dupond");
Et on peut les supprimer :
[Link]("name");
Autres informations de session
Récupérer le session ID, par exemple : gj9xswvw9p
public String getId();
Voir si la session vient juste d’être créée :
public boolean isNew();
Récupérer la date de création :
public long getCreationTime();
Dernière fois que la session a été activée (ex
dernière date de connexion)
public long getLastAccessedTime();
Session Timeout
Récupérer le plus grand temps (secondes)
d’inactivité de la session (ex : on veut la fermer
si pendant 5mns on ne fait rien)
public int getMaxInactiveInterval();
Si on spécifie cet intervalle, la session sera fermée
(invalidée) automatiquement lorsqu’un utilisateur
ne fait rien pendant un temps plus long:
public void setMaxInactiveInterval (int seconds);
Si la valeur est négative : jamais d’interruption
Terminer une session
Pour terminer (invalider) une session :
public void invalidate();
Typiquement, on fait ça au logout, ou au
passage d’une commande sur un site de
e-commerce
Les sessions peuvent se terminer
automatiquement lors de périodes
d’inactivité
Login / Logout – Exemple
Une appli web protégée par login /
password
On utilise la session pour stocker
l’utilisateur loggué
On utilise la clé "username"
Lorsqu’elle est présente, la valeur = le nom de
l’utilisateur loggué
Lors de l’authentification on rajoute la clé si
les login/password sont valides
Cliquer sur logout invalide la session
La servlet principale vérifie que l’utilisateur
courant est loggué
Formulaire de login
[Link]
<html>
<head><title>Login</title></head>
<body>
<form method="POST" action="LoginServlet">
Please login:<br>
Username:
<input type="text" name="username"><br>
Password:
<input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
LoginServlet
[Link]
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest req,
HttpServletResponse resp)
throws IOException, ServletException {
String username = [Link]("username");
String password = [Link]("password");
PrintWriter out = [Link]();
if (isLoginValid(username, password)) {
HttpSession session = [Link]();
[Link]("USER", username);
[Link]("MainServlet");
} else {
[Link]("[Link]");
}
MainServlet
[Link]
public class MainServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse resp)
throws ServletException, IOException {
HttpSession session = [Link]();
String userName = (String)
[Link]("USER");
if (userName != null) {
[Link]("text/html");
ServletOutputStream out = [Link]();
[Link]("<html><body><h1>");
[Link]("Hello, " + userName + "! ");
[Link]("</h1></body></html>");
} else {
[Link]("[Link]");
}
}
LogoutServlet
[Link]
public class LogoutServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = [Link]();
[Link]();
[Link]("text/html");
ServletOutputStream out =
[Link]();
[Link]("<html><head>");
[Link]("<title>Logout</title></head>");
[Link]("<body>");
[Link]("<h1>Logout successfull.</h1>");
[Link]("</body></html>");
}
Page [Link]
[Link]
<html>
<head>
<title>Error</title>
</head>
<body>
<h1>Invalid login!</h1>
Please <a href="[Link]">try again</a>.
</body>
</html>
Problèmes avec le cache du navigateur
La plupart des navigateurs utilisent un cache
pour les pages et les images
L’utilisateur peut voir “l’ancien état d’une page”
Peut paraitre pour un bug, surtout dans le cas d’une
page de login
Pour éviter cela, il faut désactiver le cache
dans la réponse HTTP :
[Link]("Pragma", "No-cache");
[Link]("Expires", 0);
[Link]("Cache-Control", "no-cache");
Servlets
Limitations importante des servlets
MAINTENANCE DES PAGES !
Par exemple pour un graphiste…
=> Introduction des JSP
Ressources web
Tutorial Java EE 6, section Servlets :
http://
[Link]/javaee/6/tutorial/doc/bn
[Link]
[Link] :
nombreux tutoriaux et exemples
[Link] :
idem, nombreux exemples de Servlets
LES JSP
La joie retrouvée
JSP
Séparation contenu statique/dynamique
Manipulation des composants JavaBeans
Extension standard aux Servlets
Portabilité
Equivalent JAVA de
ASP (Application Server Pages de
Microsoft)
et de PHP
Fonctionnement
JSP = Servlet !
JSP = Servlet !
Tags JSP
Trois types de tags
<%@ … %>
Tags de directives
contrôlent la structure de la servlet générée
<% … %>
Tags de scripting
insertion de code java dans la servlet
<jsp:… >
Tags d’actions
facilitent l’utilisation de composants
Les directives
Syntaxe :
<%@directive attribut="valeur" …>
Permettent de spécifier des
informations globales sur la page
3 types de directives
page options de configuration de la page
include inclusions de fichiers statiques
taglib pour définir des tags d’actions
personnalisées
La directive Page
Principaux attributs de la directive page
<%@page import="[Link].*,[Link]" %>
<%@page contentType="text/html;charset=ISO-8859-1" %>
<%@page session="true|false" %>
Indique si la page est incluse ou non dans une session. Par défaut true, ce qui
permet d’utiliser un objet de type HttpSession pour gérer des données de
session
<%@page errorPage="relativeURL" %>
Précise la JSP appelée au cas où une exception est levée , URL relative par
rapport au répertoire qui contient la page JSP ou relative par rapport au
contexte de l’application Web si elle débute par /
<%@page isErrorPage=" true|false" %>
Précise si la page JSP est une page de gestion d’erreur (dans ce cas l’objet
exception peut être utilisée dans la page), false par défaut.
<%@page isThreadSafe=" true|false" %>
Précise si la servlet générée est multithreadée ou non.
…
La directive include
Syntaxe :
<%@include file="chemin relatif du fichier" %>
chemin relatif par rapport au répertoire qui contient la page JSP ou
relatif par rapport au contexte de l’application Web si il débute par /
Inclus le fichier dans le source JSP avant que celui-ci ne soit
interprété (traduit en servlet) par le moteur JSP
Le fichier peut être un fragment de code JSP, HTML ou Java
Tag utile pour insérer un élément commun à plusieurs
pages (en-tête, pied de page)
Insertion à la compilation et non pas à l’exécution
un changement du fichier inclus ne provoque pas une
régénération de la servlet
Tags de scripting
Permettent d’insérer du code Java qui sera
inclus dans la servlet générée
Trois formes de tags
<%! …%> tag de déclaration
Code inclus dans le corps de la servlet (déclaration de
membres, variables ou méthodes)
<%=expression%> tag d’expression
L’évaluation de l’expression est insérée dans le flot de
sortie dans la méthode service() de la servlet
<==> [Link](expression)
<%...%> tag de scriptlet
Le code Java est inclus dans la méthode service() de
la servlet
Variables implicites
Les spécifications des JSP définissent plusieurs objets
implicite utilisables directement dans le code Java
out : [Link]
Flux en sortie de la page HTML générée
request : [Link]
Contient les informations de la requête
response :
[Link] Contient
les informations de la réponse
session : [Link]
Gère la session
exception : [Link]
L'objet exception pour une page d'erreur
Exemple de page JSP
<%@ page language="java" contentType="text/html;
charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"[Link]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-
8859-1">
<title>JSP simple : date</title>
</head>
<body>
<%[Link] df = new
[Link]("dd/MM/yyyy"); %>
<h1>Date: <%= [Link](new [Link]()) %>
</h1>
</body>
</html>
Exemple de page JSP
Résultat
Tags de scripting
Exemple de page JSP avec formulaire
Tags de scripting
Exemple de page JSP avec formulaire
Commentaires
<!-- ... -->
Commentaires HTML
Intégralement reconduits dans le fichier
HTML généré
<%-- ... --%>
Commentaires cachés
Contenu ignoré par le moteur JSP
Gestion des erreurs
Si une exception est levée dans une
page JSP et n'est pas capturée
Si pas de page d'erreur associée à la JSP :
affichage de la pile d'exécution
Gestion des erreurs
Si une exception est levée dans une page JSP et
n'est pas capturée
Si une page d'erreur est associée : redirection vers cette
page
Bonnes pratiques
Vilain tu ne seras pas !
JSP et Java Beans
Un des objectif des JSP / Servlets : ne pas
mélanger du code HTML au code Java des
Servlets
D’un autre coté si c’est pour mettre du
code Java dans le code JSP qu’est ce qu’on y
gagne ?
Un point important dans la conception de
pages JSP est de minimiser le code Java
embarqué dans les pages
JSP et Java Beans
Idée : déporter la logique métier dans des
composants objets qui seront accédés
depuis les pages JSP
Simplification des traitements inclus dans la
JSP
Possibilité de réutilisation des composants
depuis d’autres JSP ou d’autres composants
Les spécifications JSP définissent une
manière standard d’intérargir avec des
composants Java Beans
Java Bean
Un composant Java Bean c’est AU MOINS :
Classe publique
Possède un constructeur public sans
arguments
Regroupe un ensemble de propriétés
accessibles par des méthode de la forme
getXXX() où XXX est le nom de la propriété
éventuellement modifiables par une méthode
setXXX() où XXX est le nom de la propriété
Implémente (en option) l’interface
[Link]
Java Bean : exemple
public class Personne {
private String nom;
private String prenom;
private int age;
public Personne() { // instanciation par défaut
[Link] = "X";
[Link] = "x";
[Link] = 0;
}
public String getNom() {
return ([Link]);
}
public void setNom(String nom) {
[Link] = nom;
}
...
public int getAge () {
return ([Link]);
}
public void setAge(int age) {
[Link] = age;
}
Utiliser un Bean dans les JSP
Le tag <jsp:useBean> permet de localiser
une instance ou bien d’instancier un bean
pour l’utiliser dans la JSP
Syntaxe
<jsp:useBean
id="beanInstanceName"
class="[Link]"
type="[Link]"
scope="page|request|session|application"
/>
Utiliser un Bean dans les JSP
L’attribut scope :
page [valeur par défaut] : bean utilisable dans
toute la page JSP ainsi que dans les fichiers statiques
inclus.
request : bean accessible durant la durée de vie de la
requête. La méthode getAttribute() de l'objet request
permet d'obtenir une référence sur le bean.
session : bean utilisable par toutes les JSP de la même
session que la JSP qui a instanciée le bean. Le bean est
utilisable tout au long de la session par toutes les pages
qui y participent. La JSP qui créé le bean doit avoir
l'attribut session = "true" dans sa directive page
application : bean utilisable par toutes les JSP qui
appartiennent à la même application que la JSP qui a
instanciée le bean. Le bean n'est instancié que lors du
rechargement de l'application
Utiliser un Bean dans les JSP
Exemple :
Avec TOMCAT, les beans doivent être
nécessairement définis dans des packages
Accès aux propriétés
Le tag <jsp:getProperty> permet
d’obtenir la valeur d’un attribut d’un bean
Syntaxe
<jsp:getProperty name="beanInstanceName"
property="propertyName" />
Fixer des propriétés
Le tag <jsp:setProperty> permet de
mettre à jour la valeur de un ou
plusieurs attributs d’un bean
Syntaxe
<jsp:setProperty
name="beanInstanceName"
property="propertyName"
value="string|<%=expression%>"
/>
Fixer des propriétés
Exemple :
<jsp:useBean id="utilisateur"
class="[Link]" scope="session"/>
...
<jsp:setProperty name="utilisateur"
property="nom" value="Toto"/>
<jsp:setProperty name="utilisateur"
property="age" value="34"/>
Quand le type de la propriété du Bean n'est pas String
une conversion automatique est effectuée en
utilisant la méthode valueOf de la classe enveloppe :
<%[Link]([Link]("34"));%>
Tag de redirection
Le tag <jsp:forward> permet de rediriger la
requête vers un fichier HTML, une autre page JSP
ou une Servlet
Syntaxe
<jsp:forward page="relativeURL|<%=expression%>"/>
Si URL commence par un / elle est absolue (contexte de
l'application) sinon elle est relative à la JSP
Ce qui suit l'action forward est ignoré, et tout ce
qui a été généré dans cette page JSP est perdu
Tag de redirection
Possibilité de passer un ou plusieurs
paramètres vers la ressource appelée
<jsp:forward page="relativeURL|<
%=expression%>">
<jsp:param name="parametre"
value="string|<%=expression%>">
...
</jsp:forward>
Tag d’inclusion
Le tag <jsp:include> permet d'intégrer
dynamiquement un contenu généré par une
autre page JSP ou une autre servlet.
Comme pour <jsp:forward> possibilité de passer
un ou plusieurs paramètres vers la ressource
incluse en utilisant le tag <jsp:param>
Syntaxe
<jsp:include page="relativeURL" flush="true|
false"/>
(flush spécifie si le tampon doit être envoyé au
client et vidé)
Tags personnalisés
Possibilité de définir ses propres tags basés sur
XML :
tags personnalisés (custom tags)
regroupés dans des bibliothèques de tags (taglibs)
Objectifs
Déporter dans des classes dédiées le code java contenu
dans les scriptlets de la JSP et appeler ce code en
utilisant des tags particuliers
Améliorer la séparation des rôles :
page JSP : présentation – concepteur de pages Web
scriplets / code Java – développeur Java
Tags personnalisés / Java Beans
"philosophie" similaire
Java Beans : objets métier pour stocker et échanger des
données
Tag personnalisé : interagit directement avec
environnement JSP dans lequel il s'exécute
Tags personnalisés
Les Tags personnalisés son regroupés en
bibliothèques de Tag (Tag Lib). Définit par :
Une classe Java (Gestionnaire de balise : Tag
Handler)
code exécuté par le conteneur de JSP lorsque ce Tag
est invoqué dans une page JSP
implémente interface [Link]
Accède à un objet [Link] pour
générer une réponse
Une entrée dans le fichier de description de la
bibliothèque à laquelle il est associé (document
XML TLD Tag Library Descriptor)
la syntaxe du tags – Nom, attributs ….
La classe du Tag Handler associé
Tags personnalisés
Utilisation :
Pour pouvoir être utilisée dans une page JSP, une
bibliothèque de Tags doit être déclarée avec la
directive <%@ taglib>
<%@taglib uri="/WEB-INF/tlds/[Link]" prefix="maTagLib" %>
Exemple :
<%@taglib uri="/laTagLib" prefix="maTagLib" %>
…
<h1><maTagLib:HelloTag/></h1>
Tags personnalisés
Deux manières de déployer des bibliothèques de
Tags :
Sans les packager
Le fichier .tld de description doit se trouver
dans /WEB-INF où un de ses sous répertoire
(/WEB-INF/tlds)
Les classes (bytecode) des tag handlers
doivent se trouver dans /WEB-INF/classes
En les "packageant" dans un fichier jar
Le fichier jar doit être placé dans
/WEB-INF/lib
Tags personnalisés
Nombreuses bibliothèques de tags existantes
(Libres, Commerciales)
JSTL : Java Standard Tag Library for
JavaServer Pages
Bibliothèque standard développée par JSR
052
Tags de structure (itération, conditions)
Internationalisation
Requêtes SQL
…
Nécessite conteneur Web implémentant
au moins API 2.3 des servlets et l'API JSP
1.2
JSP : des librairies
La roue tu ne ré-inveteras pas
JSTL
Fonctionnalités de JSTL regroupées dans 5
bibliothèques de tags
Rôle Tag Lib Descriptor
Fonctions de base [Link]
Internationalisation [Link]
Traitements SQL [Link]
Traitements XML [Link]
Fonctions [Link]
En plus JSTL propose un langage d'expression
(EL) permettant de référencer facilement les
objets java accessibles dans le contexte de la JSP
JSTL
Anciennement Jakarta Tag Lib, maintenant
Tomcat/Apache :
[Link]
Utilisation :
Déclaration dans [Link] :
<taglib>
<taglib-uri>[Link]
<taglib-location>/WEB-INF/{library}.tld</taglib-location>
</taglib>
Définition dans entête de chaque JSP :
<%@ taglib uri="[Link] prefix="x" %>
Utilisation dans la JSP :
<x:magic id="beanName" name="xyz">
... Some body text and/or nested tags ...
</x:magic>
JSTL
Définition dépendance maven :
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
JSTL : Core
Exemple : appel avec paramètres :
[Link]?sayHello=true&name=Fred
<%@taglib uri=" [Link] prefix="c"%>
...
<html>
<body>
<h1>
<c:if test="${[Link]}">
<!-- Let's welcome the user ${[Link]} -->
Hello ${[Link]}!
</c:if>
</h1>
</body>
</html>
[Link]
JSTL : Core
Exemple classique : itération de collection
<body>
<table>
<tbody>
<tr><th>ID</th><th>Name</th><th>Role</th></tr>
<c:forEach items="${[Link]}" var="emp">
<tr><td><c:out value="${[Link]}"></c:out></td>
<td><c:out value="${[Link]}"></c:out></td>
<td><c:out value="${[Link]}"></c:out></td></tr>
</c:forEach>
</tbody>
</table>
Templating et JSP/JSTL
On peut faire du templating dans des pages
JSPs pour définir des zones « standards »
(header, footer, menu à gauche, etc).
Templating et JSP/JSTL (1)
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib uri="[Link]
prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"[Link]
<html>
<c:import url="[Link]"/>
<body>
<c:import url="[Link]"/>
<c:import url="[Link]"/>
<c:import url="[Link]"/>
</body>
</html>
Exemple : [Link]
<head>
<title>DOS NDAO BANK</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1" />
<meta http-equiv="content-language" content="fr" />
… CSS
<link href="[Link]" title="Défaut"
rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="[Link]"/>
</script>
… autres scripts
</head>
Autre exemple : Struts Tag Lib
Exemple : Les tags HTML Struts prennent en
charge l’initialisation des éléments du formulaire
<%@ taglib uri="[Link] prefix="ht
<html>
<head>
<title>Formulaire de saisie</title>
</head>
<body>
<H1>Histogramme des notes</H1>
<HR>
<html:form action="[Link]">
Année : <html:text property="annee" size="6"/>
…
[Link]
EL (Expression Language)
langage particulier constitué d'expressions qui
permet en particulier d'utiliser et de faire référence
à des objets java accessibles dans les différents
contextes (page, requête, session ou application)
d'une JSP
Initialement introduit avec la JSTL
Supporté de manière standard à partir de la version
1.4 J2EE (Servlets 2.4, JSP 2.0) =>[Link] en
2.3 !!
une expression EL peut être utilisée directement
dans n'importe quelle page JSP (à la place d'une
expression <%=expressionJava%> )
EL (Expression Language)
... public class Utilisateur {
Exemple : accès à un attribut
[Link] u = new private String nom;
private String prenom;
[Link]();
[Link]("DUPONT"); public User() {
[Link]("Jean"); }
[Link]("utilisateur public String getNom() {
",u); return nom;
getServletContext().getRequestDis }
public void setNom(String
patcher("/ name) {
[Link]").forward(request, [Link] = nom;
response); }
... public String getPrenom() {
return prenom;
... }
<jsp:useBean id="utilisateur" type="[Link]"
public void setPrenom(String
scope="session"/> prenom)
... EL recherche
{
l'attribut suivant l'ordre :
<H1
<H1align="center">Au
align="center">Au revoir<BR>
revoir<BR>
- portée [Link]
la page = prenom;
<%=[Link]()%> <%=[Link]()%>
${[Link]} ${[Link]} - portée de la requête </H1>
</H1>
...
... - portée de la session
- portée de l'application
EL (Expression Language)
Accéder à une propriété d'un JavaBean
${[Link]}
Accéder à une propriété imbriquée
${[Link]} ${[Link]}
Accéder à une map
${map.a} ${[Link]}
Accéder à un tableau ou une liste
${array[3]} ${liste[5]}
Les [ ] utilisables à la place du point
${user["prenom"]} ${map["a"]}
EL (Expression Language)
Variables implicites EL
pageContext objet PageContext de la page JSP
pageScope Map pour accéder aux attributs définis dans la portée de la page (PageContext
requestScope Map pour accéder aux attributs définis dans la portée de la requête
(HttpServletRequest)
sessionScope Map pour accéder aux attributs définis dans la portée de la session
(HttpSession)
applicationScope Map pour accéder aux attributs définis dans la portée de l'application
(ServletContext)
param Map pour accéder aux paramètres de la requête http sous forme de String
paramValues Map pour accéder aux paramètres de la requête http sous la forme de tableau
de String
header Map pour accéder aux valeurs de l'en-tête de la requête
headerValues Map pour accéder aux valeurs de l'en-tête de la requête sous la forme de
tableau de String
initParam Map pour accéder aux paramètres d'initialisation (init-params du [Link])
cookie Map pour accéder aux cookies
EL (Expression Language)
Opérateurs EL
EL : exemples
EL Expression Result
${1 > (4/2)} false
${4.0 >= 3} true
${100.0 == 100} true
${(10*10) ne 100} false
${'a' < 'b'} true
${!empty [Link]} Falseif the request parameter named Add is null or an
empty string.
${[Link]} The context path.
${[Link]} The value of the numberOfItems property of the session-
scoped attribute named cart.
${param['[Link]']} The value of the request parameter named
[Link].
${header["host"]} The host.
${departments[deptName]} The value of the entry named deptName in the
departments map.
#{[Link]} Gets the value of the property lName from the customer
bean during an initial request. Sets the value of lName
during a postback.
#{[Link]} The return value of the method calcTotal of the
customer bean.
Exemple de gestion de login / password,
session, la page [Link]
<%@taglib uri="[Link] prefix="c"%>
<html>
<body>
<c:import url="[Link]"/>
<c:if test="${connecte}">
<h2 align="center">Page d'accueil</h2>
<p>Bonjour, vous êtes actuellement sur un site de gestion
d'utilisateurs.
Sur ce site, vous pourrez :<br/>
<ul>
<li>Créer des utilisateurs test</li>
...
</ul>
</c:if>
<c:if test="${!connecte}">
Pour pouvoir effectuer toutes ces actions, il suffit de vous connecter!
</c:if>
</body>
</html>
Exemple de gestion de login / password :
avec session HTTP/JSTL/EL
Exemple de gestion de login / password :
avec session HTTP/JSTL/EL
Exemple de gestion de login / password,
la page [Link]
<%@taglib uri="[Link] prefix="c"%>
…
<c:if test="${!connecte}">
<form action="ServletConnexion" method="get" id="formconnexion">
Connexion : <input type="text" name="log"><br/>
<input type="text" name="pass"><br/>
<input type="hidden" name="action" value="checkConnexion">
<input type="submit" name="submit" value="Connexion">
</form>
</c:if>
<c:if test="${connecte}">
<a href="ServletConnexion?action=deconnexion">Déconnexion</a>
</c:if>
Exemple de gestion de login / password,
la Servlet
protected void processRequest(HttpServletRequest request,
HttpServletResponse response) … {
String action = [Link]("action");
HttpSession session = [Link](true);
if([Link]("checkConnexion")){
if([Link]("log").equals("toto") &&
[Link]("pass").equals("toto")) {
[Link]("login", "toto");
[Link]("mdp", "toto");
[Link]("connecte", true);
} else {
[Link]("connecte", false);
}
} else if([Link]("deconnexion")) {
[Link]("connecte", false);
}
// Redirection vers la page d’accueil
RequestDispatcher dp = [Link]("[Link]");
[Link](request, response);
}
Rappels sur ce chapitre
Dans les JSP
Tags de déclaration seulement
AUCUN tag de script <% <%=
Taglib SYSTEMATIQUE [contexte : JSTL,
Struts, Spring…]
${} EL partout (ou #)
Aucun appel direct à une JSP [=> dans
WEB-INF]
Pas de action = "*.jsp" dans les form