Java pour le développement
d’applications Web : Java EE
Servlets
Mickaël BARON - 2007 (Rév. Mars 2010)
mailto:
[email protected] ou mailto:
[email protected] Licence
Creative Commons
Contrat Paternité
Partage des Conditions Initiales à l'Identique
2.0 France
keulkeul.blogspot.com
http://creativecommons.org/licenses/by-sa/2.0/fr
Servlets - M. Baron - Page 2
Organisation du cours sur les Servlets
Servlets et API
Traitement des données de formulaires
Architecture de développement
Cycle de vie
Suivi de session
Collaboration de Servlets
keulkeul.blogspot.com
Sécurité : authentification
Accès aux BD avec JDBC
Servlets - M. Baron - Page 3
Qu’est ce qu’une Servlet
Composant logiciel écrit en Java fonctionnant du coté serveur
Au même titre nous trouvons
CGI (Common Gateway Interface)
Langages de script coté serveur PHP, ASP (Active Server Pages)
Permet de gérer des requêtes HTTP et de fournir au client
une réponse HTTP
Une Servlet s’exécute dans un moteur de Servlet ou
conteneur de Servlet permettant d’établir le lien entre la
keulkeul.blogspot.com
Servlet et le serveur Web
Une Servlet s’exécute par l'intermédiaire d'une machine
virtuelle Servlets - M. Baron - Page 4
Architecture Servlets
Processus principal
Réponse HTTP
Requête HTTP
Conteneur de Servlets
Servlet
Servlet11
Servlet
Servlet22
Client WEB
Servlet
Servlet33
Serveur Machine virtuelle Java
Web
keulkeul.blogspot.com
Thread
Les Servlets peuvent être toutes
gérées par des thread séparés au
sein d’un même processus de
machine virtuelle
Servlets - M. Baron - Page 5
Ok, mais à quoi ça sert ?
Créer des pages HTML dynamiques, générer des images, ...
Effectuer des tâches de type CGI qui sont des traitements
applicatifs coté serveur WEB
Manipulation d’une base de données
Gestion d’un système de surveillance, ...
Respecter les principes d’une architecture : écrire une
application en Java dont l’interface utilisateur est dans le
client
keulkeul.blogspot.com
Applet (SWING)
Téléphone portable (WAP)
Navigateur (HTML)
Servlets - M. Baron - Page 6
Puissance des Servlets
Portabilité
Technologie indépendante de la plate-forme et du serveur
Un langage (Java) et plusieurs plate-forme (.NET plusieurs langages
et une plate-forme)
Puissance
Disponibilité de l’API de Java
Manipulation d’images, connectivité aux bases de données (JDBC), …
Efficacité et endurance
Une Servlet est chargée une seule fois (CGI chargée puis déchargée
après utilisation)
keulkeul.blogspot.com
Une Servlet conserve son état (connexions à des bases de données)
Sûreté
Typage fort de Java
Gestion des erreurs par exception Servlets - M. Baron - Page 7
Première Servlet : HelloWorld
Ne pas oublier d'importer la HelloWorld est un objet Redéfinition de la méthode
bibliothèque Java des Servlets de type HttpServlet doGet (traitement d'une
requête GET)
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/hrml");
PrintWriter out = res.getWriter();
out.println("<HTML>");
out.println("<HEAD><TITLE>Bonjour tout le monde</TITLE></HEAD>");
out.println("<BODY>");
out.println("<BIG>Bonjour tout le monde</BIG>");
keulkeul.blogspot.com
out.println("</BODY></HTML>");
}
}
Réponse sous HelloWorld.java du
projet
format HTML
HelloWorldServlet
Le résultat sur le client Servlets - M. Baron - Page 8
L'API Servlet : du générique à l'HTTP
Une Servlet doit implémenter l'interface javax.servlet.Servlet
et javax.servlet.ServletConfig
Servlet << Interface >> ServletConfig << Interface >>
+ init(…) + getInitParameter(String) : String
+ service(…) + getServletName() : String
+ destroy() + ...
Plus simplement l'API Servlet fournit deux classes qui pro-
posent déjà une implémentation
keulkeul.blogspot.com
GenericServlet : pour la conception de Servlets indépendantes du
protocole
HttpServlet : pour la conception de Servlets spécifiques au
protocole HTTP Servlets - M. Baron - Page 9
L'API Servlet : du générique à l'HTTP
Servlet << Interface >> ServletConfig << Interface >>
+ init(…) + getInitParameter(String) : String
+ service(…) + getServletName() : String
+ destroy() + ...
Étendre cette classe GenericServlet {abstraite}
pour construire des + service(...) {abstraite}
+ ...
Servlets "génériques"
keulkeul.blogspot.com
Étendre cette classe HttpServlet
pour construire des + service(…)
Servlets propre au + doXXX (…)
protocole HTTP
Servlets - M. Baron - Page 10
L'API Servlet : la classe GenericServlet
Une Servlet qui hérite GenericServlet {abstraite}
de GenericServlet est une Servlet + service(…) {abstraite}
+ ...
indépendante du protocole
Obligation d'implémenter la méthode service(…) qui reste le
principal point d'entrée du client vers le serveur
Besoin de vérifier explicitement le type de protocole
requête
keulkeul.blogspot.com
service(...)
réponse
Serveur Web Conteneur de Servlets :
sous-classe de GenericServlet
Servlets - M. Baron - Page 11
L'API Servlet : la classe HttpServlet
Dans la suite du cours nous allons utiliser uniquement des
Servlets qui réagissent au protocole HTTP d'où l'utilisation de
la classe HttpServlet
HttpServlet redéfinit la méthode service(…)
service(…) lit la méthode (GET, POST, …) à partir de la requête
Elle transmet la requête à une méthode appropriée de HttpServlet
destinée à traiter le type de requête (GET, POST, …)
réponse
requête GET doGet(...)
keulkeul.blogspot.com
service(...)
réponse doPost(...)
requête POST
Serveur Web Conteneur de Servlets : sous-classe de HttpServlet
Servlets - M. Baron - Page 12
HttpServlet : méthodes de traitement de requêtes
Plusieurs méthodes sont fournies pour traiter les différents
types de requêtes (GET, POST, …).
Elles sont appelées méthodes de traitement de requêtes
Elles ont un en-tête identique doXXX(…) où XXX correspond
au type de requête
doPost(…) est la méthode pour traiter les requêtes de type POST
doGet(…) est la méthode pour traiter les requêtes de type GET
doHead(…), doTrace(…), …
Selon le type de requête (GET ou POST) le concepteur
keulkeul.blogspot.com
redéfinit la méthode concernée
Pour les besoins du cours nous
utiliserons essentiellement les
méthodes doPost(…) et doGet(…)
Servlets - M. Baron - Page 13
HttpServlet : méthodes de traitement de requêtes
L'implémentation par défaut des méthodes doXXX(…) renvoie
une erreur de type HTTP 405 Appel du code doGet(…)
Type de requête non supporté par l'URL de la super-classe
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorldError extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
super.doGet(req, res);
}
}
HelloWorldError.java
du projet
keulkeul.blogspot.com
HelloWorldServlet
Ne vous trompez pas de
méthode à redéfinir selon
le type de requête Servlets - M. Baron - Page 14
HttpServlet : requête et réponse
La méthode service(…) et par conséquent les méthodes de
traitement de requêtes (ex : doPost(…)) sont appelées
un objet requête
un objet réponse Objet de requête Objet de réponse
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SampleServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
}
keulkeul.blogspot.com
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
}
}
Servlets - M. Baron - Page 15
HttpServlet : objet requête HttpServletRequest
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 getServeurName() : 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
keulkeul.blogspot.com
String getRemoteHost() : retourne l'IP du client
String getServerPort() : retourne le port sur lequel le serveur écoute
String getQueryString() : retourne la chaîne d’interrogation
… (voir l'API Servlets pour le reste) Servlets - M. Baron - Page 16
HttpServlet : objet requête HttpServletRequest
Exemple : Servlet qui affiche un certains nombre d'informa-
tions issues de HttpServletRequest
public class InfosServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
response.setContentType("text/plain");
PrintWriter out= response.getWriter();
out.println("Protocol: " + request.getProtocol());
out.println("Scheme: " + request.getScheme());
out.println("ServerName: " + request.getServerName());
out.println("ServerPort: " + request.getServerPort());
out.println("RemoteAddr: " + request.getRemoteAddr());
out.println("RemoteHost: " + request.getRemoteHost());
out.println("Method: " + request.getMethod());
...
}}
keulkeul.blogspot.com
InfosServlet.java du
projet InfosServlet
Servlets - M. Baron - Page 17
HttpServlet : objet réponse HttpServletResponse
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
keulkeul.blogspot.com
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 navigateurServlets
vers l'URL
- M. Baron - Page 18
HttpServlet : objet réponse HttpServletResponse
Exemple 1 : écrit un message de type TEXT au client
Utilisation de la méthode PrintWriter getWriter()
public class HelloWorldPrintWriter extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
out.println("Premier Message");
out.println("Coucou voilà comment écrire un message");
out.println("Second Message");
}
}
keulkeul.blogspot.com
HelloWorldPrintWriter.java
du projet HelloWorld
Servlets - M. Baron - Page 19
HttpServlet : objet réponse HttpServletResponse
Exemple 2 : effectue une re-direction vers un site web
Utilisation de la méthode sendRedirect(String)
public class SendRedirect extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.sendRedirect("http://www.google.fr");
}}
SendRedirect.java du
projet HelloWorld
keulkeul.blogspot.com
Servlets - M. Baron - Page 20
HttpServlet : objet réponse HttpServletResponse
Exemple 3 : effectue un téléchargement de fichier sur le
client
public class DownloadFileServlet extends HttpServlet {
protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
Le fichier à télécharger se
try { trouve sur le serveur
InputStream is = new FileInputStream("c:/dd.txt");
OutputStream os = arg1.getOutputStream();
Flux de sortie = client
arg1.setContentType("text/plain");
arg1.setHeader("Content-Disposition","attachment;filename=toto.txt");
int count;
byte buf[] = new byte[4096];
while ((count = is.read(buf)) > -1)
os.write(buf, 0, count);
keulkeul.blogspot.com
is.close();
os.close(); En-tête de la réponse
} catch (Exception e) { adaptée pour retourner
// Y a un problème. un fichier
}
} DownloadFileServlet.java du
} projet DownloadFileServlet
Servlets - M. Baron - Page 21
HttpServlet : objet réponse HttpServletResponse
Exemple 4 : effectue un pull client
public class PullClientServlet extends HttpServlet {
private int count = 10;
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
if (count > 0) {
resp.setHeader("Refresh","1"); Toutes les 1 seconde
count-- la page est rechargée
out.println(count + "...");
et cela 10 fois de suite
} else {
out.println("Fin");
}
}
keulkeul.blogspot.com
PullClientServlet.java du projet
PullClient
Servlets - M. Baron - Page 22
HttpServlet : objet réponse HttpServletResponse
Exemple 5 : effectue un push serveur
public class PushServerServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
ServletOutpuStream out = res.getOutputStream();
res.setContentType("multipart/x-mixed-replace;boundary=End");
out.println();
out.println("--End");
Utilisation de
for (int i = 10; i > 0; i--) { « multipart/mixed »
out.println("Content-Type: text/plain");
out.println();
pour coder le pushing
out.println(i + "..."); serveur
out.println();
out.println("--End");
out.flush();
try { Connexion non fermée
Thread.sleep(1000); mais réponse envoyée
} catch (InterruptedException e) {
e.printStackTrace(); au client
}
keulkeul.blogspot.com
}
out.println("Content-Type: text/plain");
out.println(); Connexion fermée
out.println("Fin"); réponse envoyée au
out.println("--End--");
out.flush(); client
}
} PushServerServlet.java du
projet PushServer Servlets - M. Baron - Page 23
Servlets et formulaires : du coté HTML
Utilisation de la balise <FORM> </FORM>
Option METHOD : type de requête GET ou POST
Option ACTION : l’URL où envoyer les données
Utilisation de composants IHM pour saisir des informations
Contenu à l’intérieur de la balise FORM
Chaque composant est défini au moyen d’une balise particulière
SELECT, INPUT, TEXTAREA, …
keulkeul.blogspot.com
A l’intérieur de chaque balise du composant (SELECT par exemple)
plusieurs options et notamment une (NAME) qui permet d’identifier
le composant : NAME="mon_composant"
Les données sont envoyées quand l’utilisateur clique sur un bouton
de type SUBMIT Servlets - M. Baron - Page 24
Servlets et formulaires : du coté HTML
<body>
<p>Formulaire de satisfaction du cours Servlet/JSP </p> Le formulaire appelle
<form name="form1" method="get" action="form.html">
<p> une Servlet avec une
Nom : <input type="text" name="nom">
Prénom : <input type="text" name="prenom"> requête de type GET
</p>
<p>
Sexe :
<input type="radio" name="radio1" value="sexe" checked>masculin
<input type="radio" name="radio1" value="sexe">féminin
</p>
<p>Commentaire :<br>
<textarea name="textarea" cols="50" rows="10"> </textarea><br>
<input type="submit" name="Submit" rows="5" value="Soumettre">
</p>
</form>
index.html du projet
UIForm
keulkeul.blogspot.com
Il se peut que des composants
portent le même identifiant.
Exemple : composant bouton radio
Servlets - M. Baron - Page 25
Servlets et formulaires : du coté Servlet
Pour lire les données du formulaire : traiter la requête
Accéder par l’intermédiaire de l’objet HttpServletRequest aux
paramètres
String getParameter(String p) : retourne la valeur du paramètre p
String[] getParamterValues(String p) : retourne les valeurs du
paramètre p Cette méthode est utile
public class UIFormServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
lorsque dans un
throws ServletException, IOException {
res.setContentType("text/plain");
formulaire vous avez
PrintWriter out = res.getWriter(); plusieurs composants qui
out.println("Nom : " + req.getParameter("nom"));
out.println("Prénom : " + req.getParameter("prenom")); portent le même nom
if (req.getParameterValues("radio1")[0].equals("mas")) {
out.print("C'est un homme. Il");
keulkeul.blogspot.com
} else {
out.print("C'est une femme. Elle");
}
out.print(" a écrit sur ce magnifique cours que ");
out.println(req.getParameter("textarea"));
}
}
UIFormServlet.java du projet
UIForm Servlets - M. Baron - Page 26
Architecture de développement d'une application WEB
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 ou moteur 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
/HelloWorldServlet/* Servlet
Servlet 11
requête
keulkeul.blogspot.com
réponse /*.html
Servlet
/FormulaireServlet/*.htm Servlet 22
Conteneur de Servlets
Serveur Web
Il existe de nombreux conteneurs de
Servlets présentés dans la partie suivante
Servlets - M. Baron - Page 27
Architecture de développement d'une application WEB
Une application WEB est contenue dans un répertoire phy-
sique sur le serveur
Une application WEB possède une hiérarchie de répertoires
et de fichiers Respecter scrupuleusement la
hiérarchie des répertoires et
*.html, *.jsp, ... le nom des fichiers
Fichiers pour la présentation
WEB-INF web.xml
Fichiers de configuration de
l'application WEB au format XML
*.class
keulkeul.blogspot.com
classes
Classes (bytecode) des Servlets
lib *.jar, *.class
Fichiers bibliothèques sous
différents formats
Servlets - M. Baron - Page 28
Les contextes ...
Un contexte constitue une vue sur le fonctionnement d’une
même application web
Possibilité d’accéder à chacune des ressources de
l’application web correspondant au contexte
Servlets Étudier à la fin de cette partie
« Collaboration de Servlets »
Pages JSP
Approfondissement sur la partie JSP
... « Collaboration JSP Servlets : MVC »
keulkeul.blogspot.com
Utilisation du fichier web.xml pour la description de déploie-
ment du contexte Une application WEB ne
contient qu’un seul
contexte
Servlets - M. Baron - Page 29
Le fichier web.xml : c’est quoi ?
Le fichier web.xml regroupe les informations de fonctionne-
ment de l'application WEB (description de déploiement du contexte)
Utilisation du format XML
eXtensible Markup Language
Syntaxe universelle pour la structuration des données créée par le
World Wide Web Consortium (W3C) en 1996
Langage basé sur des balises permettant de donner une signification
au document (HTML s'intéresse essentiellement à l'affichage)
Extensible par la possibilité de créer de nouvelles balises
Balises XML sensibles à la case et à la rigueur (balise ouvrante =
obligation d'une balise fermante)
keulkeul.blogspot.com
La structure du document est défini par un fichier XSD (XML Schema
Description)
Des informations sur le format
XML peuvent être trouvées à
www.w3.org/XML Servlets - M. Baron - Page 30
Le fichier web.xml : c’est quoi ?
Fichier web.xml typique La présence du fichier
web.xml est obligatoire
En-tête du fichier web.xml
pour que vos servlets WEB
Balise principale
fonctionnent
<?xml version="1.0" encoding="UTF-8"?>
Balise de description de <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
l'application WEB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
Balise de description version="2.4">
<display-name>Application WEB affichant HelloWorld</display-name>
d'une Servlet
<servlet>
Nom de la Servlet <servlet-name>HelloWorldServlet</servlet-name>
"Identification" <servlet-class>HelloWorld</servlet-class>
</servlet>
Classe de la Servlet
keulkeul.blogspot.com
Définition d'un chemin
virtuel
<servlet-mapping>
Nom de la Servlet considéré <servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/msg.hello</url-pattern>
"Identification" </servlet-mapping>
</web-app>
Définition du chemin virtuel
Servlets - M. Baron - Page 31
Le fichier web.xml : c’est quoi ?
Possibilité de décrire dans le fichier web.xml le fonctionne-
ment de plusieurs Servlets
<?xml version="1.0" encoding="UTF-8"?>
web.xml du projet <web-app ...>
HelloWorld
<display-name>Servlets affichant différemment le message
HelloWorld
L’application WEB est </display-name>
ici composée de deux <servlet>
<servlet-name>HelloWorldServlet</servlet-name>
Servlets <servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet>
<servlet-name>HelloWorldPrintWriter</servlet-name>
Deux façon différentes <servlet-class>HelloWorldPrintWriter</servlet-class>
</servlet>
d’appeler la Servlet
HelloWorldServlet <servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>*.toutpourservlet</url-pattern>
keulkeul.blogspot.com
</servlet-mapping>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/msg.hello</url-pattern>
</servlet-mapping>
Une seule façon d’appeler <servlet-mapping>
<servlet-name>HelloWorldPrintWriter</servlet-name>
la Servlet <url-pattern>/printwriter.html</url-pattern>
HelloWorldPrintWriter </servlet-mapping>
</web-app>
Servlets - M. Baron - Page 32
Le fichier web.xml : c’est quoi ?
Le fichier web.xml permet la définition de chemin virtuel :
mais comment sont-ils utilisés pour appeler les Servlets ?
...
web.xml du projet <servlet-mapping>
HelloWorld <servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/HelloWorldServlet/msg.hello</url-pattern>
Trois chemins virtuels ont </servlet-mapping>
<servlet-mapping>
été définis pour exécuter la <servlet-name>HelloWorldServlet</servlet-name>
Servlet HelloWorldServlet <url-pattern>*.toutpourservlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
Contexte de <servlet-name>HelloWorldServlet</servlet-name>
Adresse du <url-pattern>/index.html</url-pattern>
Port l'application </servlet-mapping>
Serveur
WEB ...
http://localhost:8080/HelloWorldServlet
http://localhost:8080/HelloWorldServlet/bonjour.toutpourservlet
keulkeul.blogspot.com
http://localhost:8080/HelloWorldServlet/hello.toutpourservlet
http://localhost:8080/HelloWorldServlet/HelloWorldServlet/msg.hello
La définition du contexte d’une application
WEB sera présentée dans la partie suivante Servlets - M. Baron - Page 33
Cycle de vie d'une Servlet
Création et initialisation de la Servlet
Utilisation de paramètres initiaux
Traitement des services demandés par les clients (au travers
de la méthode service(…) notamment), le cas échéant
Persistance d’instance
Destruction de la Servlet et passage au ramasse-miettes de la
machine virtuelle
keulkeul.blogspot.com
Déconnexion avec une base de données
Au contraire les applications serveur de
type CGI sont créées à chaque requête et
détruites après le traitement des réponses
Servlets - M. Baron - Page 34
Cycle de vie d'une Servlet : persistance d’instance
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
keulkeul.blogspot.com
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)
Servlets - M. Baron - Page 35
Cycle de vie d'une Servlet : persistance d’instance
Exemple : Servlet qui incrémente un compteur à chaque
requête du client
public class SimpleCounterServlet extends HttpServlet {
private int count = 0;
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
count++;
out.println("Depuis son chargement, on a accédé à cette Servlet " +
count " fois.");
}
}
keulkeul.blogspot.com
Pensez à prévoir des accès SimpleCounterServlet.java du
projet Counter
synchronisés au cas où plus
d’une requête est traitée en
même temps par le Serveur
Servlets - M. Baron - Page 36
Cycle de vie d'une Servlet : rechargement d’une Servlet
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
keulkeul.blogspot.com
Le conteneur de Servlets ne s’intéresse qu’au
Servlet et par conséquent si vous modifiez
autre chose que des classes il n’y aura aucun
rechargement implicite de Servlets
Servlets - M. Baron - Page 37
Cycle de vie d'une Servlet : méthodes init()
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
keulkeul.blogspot.com
Sur demande explicite de l’administrateur du serveur WEB
N’essayez pas de placer des
constructeurs à la mode
POO ça ne sert à rien
Servlets - M. Baron - Page 38
Cycle de vie d'une Servlet : méthode init()
Exemple : Servlet qui incrémente un compteur à chaque
requête du client avec une valeur initiale de 6
public class InitCounterServlet extends HttpServlet {
private int count;
public void init() throws ServletException {
count = 6;
}
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
count++;
keulkeul.blogspot.com
out.println("Depuis son chargement, on a accédé à cette Servlet " +
count " fois.");
}
}
InitCounterServlet.java du
projet Counter Servlets - M. Baron - Page 39
Cycle de vie d'une Servlet : méthode init()
Possibilité d’utiliser des paramètres d’initialisation exploités
exclusivement par la méthode init()
Les paramètres d’initialisation sont définis dans le fichier
web.xml de l’application WEB
...
Balise qui détermine <web-app ...>
le nom du paramètre <display-name>Servlet simulant un compteur</display-name>
<servlet>
<servlet-name>InitConfigFileCounterServlet</servlet-name>
Balise qui détermine la <servlet-class>InitConfigFileCounterServlet</servlet-class>
valeur du paramètre <init-param>
<param-name>initial_counter_value</param-name>
<param-value>50</param-value>
<description>Valeur initiale du compteur</description>
keulkeul.blogspot.com
</init-param>
Balise qui explique
</servlet>
le rôle du paramètre ...
(optionnelle) </web-app>
Plusieurs paramètres peuvent être définis web.xml du projet
Counter
mais attention à l’ordre des balises !!
Servlets - M. Baron - Page 40
Cycle de vie d'une Servlet : méthode init()
Exemple : Servlet qui incrémente un compteur et qui est
initialisée par le fichier web.xml
public class InitConfigFileCounterServlet extends HttpServlet {
private int count;
public void init() throws ServletException {
String initial = this.getInitParameter("initial_counter_value");
try {
count = Integer.parseInt(initial);
} catch(NumberFormatException e) {
count = 0;
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
keulkeul.blogspot.com
count++;
out.println("Depuis son chargement, on a accédé à cette Servlet " +
count " fois.");
}
}
InitConfigFileCounterServlet.java
du projet Counter Servlets - M. Baron - Page 41
Cycle de vie d'une Servlet : méthode destroy()
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
keulkeul.blogspot.com
La méthode destroy() est également utilisées pour écrire les
informations persistantes qui seront lues lors du prochain
appel à init()
Servlets - M. Baron - Page 42
Cycle de vie d'une Servlet : méthode destroy()
Exemple : Servlet qui incrémente un compteur qui sauve-
garde l’état avec destroy() et qui recharge avec init()
public class InitDestroyCounterServlet extends HttpServlet {
private int count;
public void destroy() {
FileWriter fileWriter = null; PrintWriter printWriter = null;
try {
fileWriter = new FileWriter("InitCounter.initial");
printWriter = new PrintWriter(fileWriter);
printWriter.println(count);
} catch (IOException e) {
...
} finally {
if (printWriter != null) printWriter.close();
}
keulkeul.blogspot.com
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
}
} InitDestoryCounterServlet.java
du projet Counter
Servlets - M. Baron - Page 43
Cycle de vie d'une Servlet : méthode destroy()
Exemple (suite) : Servlet qui incrémente un compteur qui
sauvegarde l’état avec destroy() et qui recharge avec init()
...
public void destroy() {
// Voir transparent précédent
}
public void init() throws ServletException {
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader("InitCounter.initial");
bufferedReader = new BufferedReader(fileReader);
String initial = bufferedReader.readLine();
count = Integer.parseInt(initial);
} catch (IOException e) {
keulkeul.blogspot.com
...
} finally {
if (bufferedReader != null)
bufferedReader.close();
}
}
} InitDestoryCounterServlet.java
du projet Counter
Servlets - M. Baron - Page 44
Envoyer un contenu multimédia
Pour l’instant nous avons écrit des Servlets qui retournaient
des contenus HTML
Besoin de retourner des contenus différents :
Protocole WAP et langage WML utilisés par les téléphones portables
Génération de contenus multimédias (création de graphes, manipula-
tion d’images)
L’API Java facilite la gestion des contenus multimédias en
keulkeul.blogspot.com
proposant des bibliothèques
Encodage d’images sous différents formats (GIF, JPEG)
Manipulation et traitement d’images Servlets - M. Baron - Page 45
Envoyer un contenu multimédia
Exemple : Servlet qui génère et retourne une image JPEG
affichant le message « Bonjour tout le monde »
public class GenerateImageServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
ServletOutputStream out = res.getOutputStream();
Frame frame = null; Graphics2D g = null; BufferedImage bim;
frame = new Frame(); frame.addNotify();
buffer_image = new BufferedImage(620, 60, BufferedImage.TYPE_3BYTE_BGR);
g = buffer_image.createGraphics();
g.setFont(new Font("Serif", Font.ITALIC, 48));
g.drawString("Bonjour tout le monde !", 10,50);
JPEGImageEncoder encode = JPEGCodec.createJPEGEncoder(out);
keulkeul.blogspot.com
encode.encode(buffer_image);
out.close();
}
}
GenerateImageServlet.java du
projet Multimedia
Servlets - M. Baron - Page 46
Suivi de session
Le protocole HTTP est un protocole sans état
Impossibilité alors de garder des informations d’une requê-
te à l’autre (identifier un client d’un autre)
Obligation d’utiliser différentes solutions pour remédier au
problème d’état
Authentifier l’utilisateur
Champs de formulaire cachés
keulkeul.blogspot.com
Réécriture d’URL
Cookies persistants
Suivi de session
Servlets - M. Baron - Page 47
Cookies persistants : Cookie
Un cookie est une information envoyée au navigateur
(client) par un serveur WEB qui peut ensuite être relue par
le client
Lorsqu’un client reçoit un cookie, il le sauve et le renvoie
ensuite au serveur chaque fois qu’il accède à une page sur
ce serveur
La valeur d’un cookie pouvant identifier de façon unique un
client, ils sont souvent utilisés pour le suivi de session
keulkeul.blogspot.com
Les cookies ont été introduits par la première fois dans
Netscape Navigator
home.netscape.com/newsref/std/cookie_spec.html
www.cookie-central.com Servlets - M. Baron - Page 48
Cookies persistants : Cookie
L’API Servlet fournit la classe javax.servlet.http.Cookie pour
travailler avec les Cookies
Cookie(String name, String value) : construit un cookie
String getName() : retourne le nom du cookie
String getValue() : retourne la valeur du cookie
setValue(String new_value) : donne une nouvelle valeur au cookie
setMaxAge(int expiry) : spécifie l’âge maximum du cookie
Pour la création d’un nouveau cookie, il faut l’ajouter à la
réponse (HttpServletResponse)
addCookie(Cookie mon_cook) : ajoute à la réponse un cookie
keulkeul.blogspot.com
La Servlet récupère les cookies du client en exploitant la
réponse (HttpServletRequest)
Cookie[] getCookies() : récupère l’ensemble des cookies du site
Servlets - M. Baron - Page 49
Cookies persistants : Cookie
Code pour créer un cookie et l’ajouter au client
Cookie cookie = new Cookie("Id", "123");
res.addCookie(cookie);
Code pour récupérer les cookies
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
String name = cookies[i].getName();
String value = cookies[i].getValue();
}
}
keulkeul.blogspot.com
Il n’existe pas dans l’API Servlet
de méthode permettant de récupérer
la valeur d’un cookie par son nom
Servlets - M. Baron - Page 50
Cookies persistants : Cookie
Exemple : gestion de session (identifier un client d’un autre)
par l’intermédiaire des cookies persistants
public class CookiesServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
String sessionId = null;
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals("sessionid")) {
sessionId = cookies[i].getValue();
}}}
if (sessionId == null) {
sessionId = new java.rmi.server.UID().toString();
Cookie c = new Cookie("sessionid", sessionId);
keulkeul.blogspot.com
res.addCookie(c);
out.println("Bonjour le nouveau");
Génère un identifiant
} else {
out.println("Encore vous"); ... } unique pour chaque client
}
}
CookiesServlet.java du projet
Cookies Servlets - M. Baron - Page 51
Suivi de session : HttpSession
Le plus gros problème des cookies est que les navigateurs
ne les acceptent pas toujours
L’utilisateur peut
configurer son
navigateur pour qu’il
refuse ou pas les
cookies
keulkeul.blogspot.com
Les navigateurs n’acceptent que 20 cookies par site, 300 par
utilisateur et la taille d’un cookie peut être limitée à 4096
octets
Servlets - M. Baron - Page 52
Suivi de session : HttpSession
Solutions : utilisation de l’API de suivi de session HttpSession
Méthodes de création liées à la requête (HttpServletRequest)
HttpSession getSession() : retourne la session associée à l’utilisateur
HttpSession getSession(boolean p) : création selon la valeur de p
Gestion d’association (HttpSession)
Enumeration getAttributNames() : retourne les noms de tous les
attributs
Object getAttribut(String name) : retourne l’objet associé au nom
setAttribut(String na, Object va) : modifie na par la valeur va
keulkeul.blogspot.com
removeAttribut(String na) : supprime l’attribut associé à na
Destruction (HttpSession) Mécanisme très puissant
permettant de stocker des objets et
invalidate() : expire la session non de simples chaînes de
caractères comme les cookies
logout() : termine la session Servlets - M. Baron - Page 53
Suivi de session : HttpSession
Exemple : suivi de session pour un compteur
public class HttpSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain"); PrintWriter out = res.getWriter();
HttpSession session = req.getSession();
Integer count = (Integer)session.getAttribute("count");
if (count == null)
count = new Integer(1);
else
count = new Integer(count.intValue() + 1);
session.setAttribute("count", count);
out.println("Vous avez visité cette page " + count + " fois.");
}
}
HttpSessionServlet.java
du projet HttpSession
keulkeul.blogspot.com
Client n°2
Client n°1 Servlets - M. Baron - Page 54
Collaboration de Servlets
Les Servlets s’exécutant dans le même serveur peuvent
dialoguer entre elles
Deux principaux styles de collaboration
Partage d’information : un état ou une ressource.
Exemple : un magasin en ligne pourrait partager les informations sur
le stock des produits ou une connexion à une base de données
Partage du contrôle : une requête.
Réception d’une requête par une Servlet et laisser l’autre Servlet une
keulkeul.blogspot.com
partie ou toute la responsabilité du traitement
N’essayez pas de communiquer avec
des Servlets de serveurs différents
cette solution ne fonctionnera pas
Servlets - M. Baron - Page 55
Collaboration de Servlets : partage d’information
La collaboration est obtenue par l’interface ServletContext
L’utilisation de ServletContext permet aux applications web
de disposer de son propre conteneur d’informations unique
Une Servlet retrouve le ServletContext de son application web
par un appel à getServletContext()
Exemples de méthodes
void setAttribute(String name, Object o) : lie un objet sous le nom
indiqué
Object getAttribute(String name) : retrouve l’objet sous le nom indiqué
keulkeul.blogspot.com
Enumeration getAttributeNames() : retourne l’ensemble des noms de
tous les attributs liés
void removeAttribute(String name) : supprime l’objet lié sous le nom
indiqué Servlets - M. Baron - Page 56
Partage d’information
Exemple : Servlets qui vendent des pizzas et partagent une
spécialité du jour Création de deux
public class PizzasAdmin extends HttpServlet { attributs
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
ServletContext context = this.getServletContext();
context.setAttribute("Specialite", "Jambon Fromage");
context.setAttribute("Date", new Date());
out.println("La pizza du jour a été définie.");
}
} PizzasAdmin.java du projet
ServletContext
public class PizzasClient extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
... Lecture des
attributs
keulkeul.blogspot.com
ServletContext context = this.getServletContext();
String pizza_spec = (String)context.getAttribute("Specialite");
Date day = (Date)context.getAttribute("Date");
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
String today = df.format(day);
out.println("Aujourd'hui (" + today + "), notre specialite est : " + pizza_spec);
}}
PizzasClient.java du projet
ServletContext Servlets - M. Baron - Page 57
Partage d’information
Possibilité de partager des informations entre contextes web
Première solution : utilisation d’un conteneur d’informations
externes (une base de données par exemple)
Seconde solution : la Servlet recherche un autre contexte à
partir de son propre contexte
ServletContext getContext(String uripath) : obtient le contexte à partir
d’un chemin URI (uripath = chemin absolu)
Contextes WEB
Conteneur de Servlets
Servlet
Servlet11
keulkeul.blogspot.com
Servlet
Servlet22
Servlet
Servlet33
Ne fonctionne
que dans le Servlet
Servlet44
Communication
par le contexte
même serveur
Serveur Web
WEB Servlets - M. Baron - Page 58
Partage d’information
Exemple : permet d’afficher la spécialité du jour de l’applica-
tion web précédente
public class ReadSharePizzas extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html"); Contextes de l’application
PrintWriter out = res.getWriter(); web précédente
ServletContext my_context = this.getServletContext();
ServletContext pizzas_context = my_context.getContext("/ServletContext");
String pizza_spec = (String)pizzas_context.getAttribute("Specialite");
Date day = (Date)pizzas_context.getAttribute("Date");
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
String today = df.format(day);
out.println("Aujourd'hui (" + today + "), notre specialite est : " + pizza_spec);
}
keulkeul.blogspot.com
ReadSharePizzas.java du projet
Pour communiquer entre contextes, CrossServletContext
il faut autoriser la communication
inter-contextes (voir partie suivante)
Servlets - M. Baron - Page 59
Collaboration de Servlets : partage du contrôle
Les Servlets peuvent partager ou distribuer le contrôle de la
requête
Deux types de distribution
Distribuer un renvoi : une Servlet peut renvoyer une requête entière
Distribuer une inclusion : une Servlet peut inclure du contenu généré
Les avantages sont
La délégation de compétences
keulkeul.blogspot.com
Une meilleure abstraction et une plus grande souplesse
Architecture logicielle MVC (Servlet = contrôle et JSP = présentation)
Collaboration entre Servlets /
JSP dans la partie JSP
Servlets - M. Baron - Page 60
Collaboration de Servlets : partage du contrôle
Le support de la délégation de requête est obtenu par l’inter-
face RequestDispatcher
Une Servlet obtient une instance sur la requête
RequestDispatcher getRequestDispatcher(String path) : retourne une
instance de type RequestDispatcher par rapport à un composant
Un composant peut-être de tout type : Servlet, JSP, fichier statique, …
path est un chemin relatif ou absolu ne pouvant pas sortir du contexte
Pour distribuer en dehors du contexte courant il faut :
Identifier le contexte extérieur (utilisation de getContext())
keulkeul.blogspot.com
Utiliser la méthode getRequestDispatcher(String path)
Le chemin est uniquement en absolu
De préférence utilisez la méthode
getRequestDispatcher de
ServletRequest Servlets - M. Baron - Page 61
Partage du contrôle : distribuer un renvoi
La méthode forward(...) de l’interface RequestDispatcher
renvoie une requête d’une Servlet à une autre ressource sur
le serveur
void forward(ServletRequest req, ServletResponse res) : redirection de
requête
RequestDispatcher dispat =
req.getRequestDispatcher("/index.html");
dispat.forward(req,res);
Possibilité de transmettre des informations lors du renvoi
en attachant une chaîne d’interrogation (au travers de l’URL)
en utilisant les attributs de requête via la méthode setAttribute(...)
keulkeul.blogspot.com
Les choses à ne pas faire ...
ne pas effectuer de modification sur la réponse avant un renvoi
ne rien faire sur la requête et la réponse après une distribution d’un
renvoi Servlets - M. Baron - Page 62
Partage du contrôle : distribuer un renvoi
Exemple : distribuer un renvoi de Emetteur à Recepteur
public class SenderServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
Transmission
throws ServletException, IOException { d’informations par
req.setAttribute("seconde", "au revoir"); attributs
RequestDispatcher dispat = req.getRequestDispatcher("/recepteur.html?mot=bonjour");
dispat.forward(req,res);
// Ne rien faire sur req et res Le chemin est absolu par Transmission
} rapport au contexte de d’informations par
} l’application web chaîne d’interrogation
SenderServlet.java du projet
ForwardInclude
public class ReceiverServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
keulkeul.blogspot.com
out.println(req.getParameter("mot")); Affichage des
out.println(req.getAttribute("seconde")); informations stockées
} dans la requête
}
L’utilisation des attributs à la place des ReceiverServlet.java du projet
paramètres donne la possibilité de passer ForwardInclude
des objets et non des chaînes de caractères Servlets - M. Baron - Page 63
Partage du contrôle : distribuer un renvoi
Nous avons vu au début de cette partie qu’il existait une
méthode de redirection
sendRedirect(…) est une redirection effectuée par le client
forward(…) est une redirection effectuée par le serveur
Est-il préférable d’utiliser forward(…) ou sendRedirect(…) ???
forward(…) est à utiliser pour la partage de résultat avec un autre
composant sur le même serveur
keulkeul.blogspot.com
sendRedirect(…) est à utiliser pour des redirections externes car
aucune recherche getContext(...) n’est nécessaire
Préférez forward(…) pour des
redirections dans le contexte et
sendRedirect(…) pour le reste
Servlets - M. Baron - Page 64
Partage du contrôle : distribuer une inclusion
La méthode include(…) de l’interface RequestDispatcher
inclut le contenu d’une ressource dans la réponse courante
RequestDispatcher dispat =
req.getRequestDispatcher("/index.html");
dispat.include(req,res);
La différence avec une distribution par renvoi est :
la Servlet appelante garde le contrôle de la réponse
elle peut inclure du contenu avant et après le contenu inclus
Possibilité de transmettre des informations lors de l’inclusion
en attachant une chaîne d’interrogation (au travers de l’URL)
keulkeul.blogspot.com
en utilisant les attributs de requête via la méthode setAttribute(...)
Les choses à ne pas faire ...
ne pas définir le code d’état et en-têtes (pas de setContentType(…))
supprimer les balises <HTML> et <BODY> Servlets - M. Baron - Page 65
Partage du contrôle : distribuer une inclusion
Exemple : permet de distribuer une inclusion
public class IncluderServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<HTML><BODY>");
RequestDispatcher dispat = req.getRequestDispatcher("included.html");
dispat.include(req,res);
out.println("<br>");
req.setAttribute("bonjour", "Bonjour"); Cette Servlet réalise trois
dispat.include(req,res); inclusions
out.println("<br>");
req.setAttribute("bonsoir", "Bonsoir");
keulkeul.blogspot.com
dispat.include(req,res);
out.println("<br>");
out.println("</BODY></HTML>");
}
} IncluderServlet.java du projet
ForwardInclude
Servlets - M. Baron - Page 66
Partage du contrôle : distribuer une inclusion
Exemple (suite) : permet de distribuer une inclusion
public class IncludedServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
PrintWriter out = res.getWriter();
if(req.getAttribute("bonjour") != null) {
out.println(req.getAttribute("bonjour"));
if (req.getAttribute("bonsoir") != null) {
out.println(req.getAttribute("bonsoir"));
} else {
out.println("Pas Bonsoir");
}
} else {
out.println("Rien de rien"); Retour à l’appelant
}
}
}
keulkeul.blogspot.com
IncludedServlet.java du projet
ForwardInclude
Servlets - M. Baron - Page 67
Sécurité : authentification
La sécurité consiste à conserver les informations sensibles
dans les mains des utilisateurs
Authentification : capable de vérifier l’identité des parties impliquées
Habilitation : limiter l’accès aux ressources à un ensemble d’utilisateurs
Confidentialité : garantir la communication des parties impliquées
Nous distinguons plusieurs types d'autorisation :
BASIC : fournit par le protocole HTTP basé sur un modèle simple de
demande/réponse (codage Base64)
keulkeul.blogspot.com
FORM : authentification ne reposant pas celle du protocole HTTP
Servlets - M. Baron - Page 68
Sécurité : types d'autorisation
Principe des autorisations de type BASIC
GET / HTTP/1.1
Application
Application
HTTP/1.1 401 Unauthorized
WWW-Authenticate: BASIC
WEB
WEB
realm="Users"
GET / HTTP/1.1
Autorisation: BASIC RkfddsIRSddO=
Client Web Serveur Web Vérification si l'utilisateur
est connu et son mot de
Principe des autorisations de type FORM passe correct
GET / HTTP/1.1
keulkeul.blogspot.com
Application
Application
HTTP/1.1 200 OK
Content-Type: text/html
WEB
WEB
...
POST / HTTP/1.1
...
Serveur Web
Client Web
Données cachées et non visible
Servlets - M. Baron - Page 69
Sécurité : deux familles d'identification pour les Servlets
Gérée par le conteneur de Servlets (Ident 1) :
Spécification d'un domaine de sécurité dans le fichier de configuration
web.xml
Les utilisateurs sont gérés (l'utilisateur existe-il, le mot de passe est-il
correct, …) uniquement par le conteneur de Servlets
Basée sur les rôles (BASIC)
A base de formulaire (FORM)
Effectuée à l’intérieur des Servlets (Ident 2) :
keulkeul.blogspot.com
Les utilisateurs sont stockés dans une base de données, un fichier, …
La vérification est effectuée dans les Servlets (besoin d'un codage)
Personnalisée (BASIC)
Personnalisée à base de formulaire (FORM) Servlets - M. Baron - Page 70
Authentification basée sur les rôles : Ident 1
Exemple : Servlet qui après identification affiche un ensem-
ble d'informations Aucune vérification dans
le code de la Servlet pour
public class SecurityRolesServlet extends HttpServlet { l'identification
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
out.println("Bonjour : " + req.getRemoteUser());
out.println("Information Top-Secrête");
out.println("Type d'authentification : " + req.getAuthType());
out.println("Est-un administrateur : " + req.isUserInRole("admin"));
}
}
Conteneur de
keulkeul.blogspot.com
SecurityRolesServlet.java du projet Servlets
Ou
AuthentificationByRoles n i
a tio
c
n tifi ie ?
e s
Id réus
Servlets - M. Baron - Page 71
Authentification basée sur les rôles : Ident 1
Besoin de modification du fichier de configuration web.xml
web.xml du projet
de l'application WEB considérée AuthentificationByRoles
...
<web-app ...>
<display-name>Gestion d'une authentification par "Roles"</display-name> Définition des Servlets
<servlet> contenues dans
<servlet-name>SecuriteRolesServlet</servlet-name> l'application WEB et des
<servlet-class>SecuriteRolesServlet</servlet-class>
</servlet> chemins virtuels
<servlet-mapping>
<servlet-name>SecuriteRolesServlet</servlet-name>
<url-pattern>/SecuriteRolesServlet</url-pattern>
Définit pour quelles URL la
</servlet-mapping> contrainte d’identification
doit être mise en œuvre
<security-constraint>
<web-resource-collection>
<web-resource-name>SecretProtection</web-resource-name> Protection des
<url-pattern>/SecuriteRolesServlet</url-pattern>
<http-method>GET</http-method> ressources pour la
</web-resource-collection> méthode GET
<auth-constraint>
<role-name>test</role-name>
Rôle(s) ayant le droit
keulkeul.blogspot.com
</auth-constraint> d'accéder aux ressources de
</security-constraint> l'application WEB
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Authentification de SecuriteRoleServlet</realm-name> « Habillage » de la
</login-config> boîte d’identification
</web-app>
La définition des rôles sera
présentée dans la partie suivante Servlets - M. Baron - Page 72
Authentification personalisée basée sur les rôles : Ident 1
Exemple : Servlet qui après identification personnalisée
affiche un message de bienvenue Aucune vérification dans
le code{ de la Servlet pour
public class SecurityFormRolesServlet extends HttpServlet
l'identification
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("Bonjour : " + req.getRemoteUser()); Termine explicitement la
req.getSession().invalidate(); session. Obligation de
} s’identifier à chaque fois
} que la Servlet est appelée
Conteneur de
Servlets
SecurityFormRolesServlet.java du projet
Oui
AuthentificationFormByRoles tio
n
a
fic e ?
No
ti
en si
n
Id réus
keulkeul.blogspot.com
loginpage.html
Deux fichiers au format HTML gèrent errorpage.html
les pages de connexion et d’erreur
Servlets - M. Baron - Page 73
Authentification personalisée basée sur les rôles : Ident 1
Besoin de modification du fichier de configuration web.xml
de l'application WEB considérée
...
<web-app ...>
... Le début du fichier web.xml
<servlet> ... </servlet>
<servlet-mapping> ... </servlet-mapping> est identique au précédent
<security-constraint> ... </security-constraint> modulo le nom de la classe
<login-config>
SecuriteFormServlet
<auth-method>
FORM
</auth-method>
<form-login-config> Balise qui stocke la
<form-login-page>
/loginpage.html page de connexion
</form-login-page>
<form-error-page>
/errorpage.html
</form-error-page>
</form-login-config>
</login-config> Balise qui stocke la
keulkeul.blogspot.com
</web-app>
page des erreurs de
web.xml du projet connexion
AuthentificationFormByRoles
Les fichiers HTML sont placés à la
racine de l’application WEB et au même
niveau que le répertoire WEB-INF Servlets - M. Baron - Page 74
Authentification personalisée basée sur les rôles : Ident 1
Le formulaire de la page loginpage.html doit employer
la méthode POST pour la transmission des données
des valeurs spéciales pour les noms des composants
Le moteur de Servlet avec les informations
Rend invisible la contenues dans le fichier web.xml se charge
transmission des données de traiter l’identification
<FORM METHOD=POST ACTION="j_security_check">
Valeur pour le nom
d’utilisateur
Nom d’utilisateur : <INPUT TYPE=TEXT NAME="j_username"><br>
Mot de passe : <INPUT TYPE=PASSWORD NAME="j_password"><br>
keulkeul.blogspot.com
<INPUT TYPE=SUBMIT>
</FORM>
Valeur pour le mot loginpage.html du projet
C'est du JSP de passe AuthentificationFormByRoles
Servlets - M. Baron - Page 75
Authentification personnalisée : Ident 2
Exemple : Servlet qui traite les autorisations de type BASIC
public class SecurityServlet extends HttpServlet { SecurityServlet.java du projet
private Hashtable users = new Hashtable(); AuthentificationByServlet
public void init(ServletConfig config) throws ServletException {
super.init(config);
users.put("mickael:baron","allowed"); Récupère dans la
}
requête le HEADER
public void doGet(HttpServletRequest req, HttpServletResponse res) nommé Authorization
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter(); S’il s’agit du premier essai ou
String auth = req.getHeader("Authorization"); d’une mauvais saisie => envoie
d ’une réponse avec l’en-tête
if (!allowUser(auth)) {
res.setHeader("WWW-Authenticate", "BASIC realm=\"users\"");
WWW-Authenticate et l ’état
res.sendError(HttpServletResponse.SC_UNAUTHORIZED); SC_UNAUTHORIZED
} else out.println("Page Top-Secret");
}
protected boolean allowUser(String auth) throws IOException {
if (auth == null) return false;
if (!auth.toUpperCase().startsWith("BASIC "))
keulkeul.blogspot.com
return false;
String userpassEncoded = auth.substring(6); Méthode qui traite
String userpassDecoded = Base64EnDecoder.decode(userpassEncoded);
le résultat de l’en-
return ("allowed".equals(users.get(userpassDecoded))); tête Authorization
}
}
La vérification de l’identification est
effectuée dans le code de la Servlet Servlets - M. Baron - Page 76
Authentification personnalisée à base de formulaire :
Ident 2
Différences avec les autres types d’identification
Cette identification part d’un formulaire basique avec une protection
minimum des transmissions grâce à la méthode POST
Cette identification comparée à l’identification personnalisée basée
sur les rôles est « démarrée » directement par la page WEB de
connexion (login.html)
Au contraire l’identification personnalisée basée sur les rôles est
démarrée au travers de son URL virtuelle
Transmission par POST
keulkeul.blogspot.com
Servlet
Servletde
de Correcte
traitement
traitement
login.html
Erronée
Servlets - M. Baron - Page 77
Authentification personnalisée à base de formulaire :
Ident 2
Exemple : Servlet qui traite les autorisations de type FORM
Le mot de passe est
public class SecurityFormServlet extends HttpServlet {
private Hashtable users = new Hashtable(); caché dans la requête
de type POST
public void init(ServletConfig config) throws ServletException {
users.put("mickael:baron","allowed");
}
Récupère les variables
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException { qui ont été transmises
res.setContentType("text/html"); par le formulaire de
PrintWriter out = res.getWriter();
login.html
String account = req.getParameter("account");
String password = req.getParameter("password"); Génère une page
if (!allowUser(account, password)) { d’erreur avec la
out.println("<HTML><HEAD><TITLE>Access Denied</TITLE></HEAD>"); possibilité de s’identifier
out.println("<BODY>Votre compte et mot de passe sont incorrects.<BR>");
out.println("<A HREF=\"/SecuritePersoFormServlet/login.html\">
une nouvelle fois
Retenter</A>");
out.println("</BODY></HTML>");
keulkeul.blogspot.com
} else {
req.getSession().setAttribute("logon.isDone", account);
out.println("Bravo : " + account); L’identification est
}
}
réussie et on modifie la
... session en ajoutant le
} nom de l’utilisateur
SecurityFormServlet.java du projet
AuthentificationFormByServlet
Servlets - M. Baron - Page 78
Se connecter aux bases de données
Utilisation de l’API JDBC (Java DataBase Connectivity)
JDBC est une API du niveau SQL, elle permet d’exécuter des
instructions SQL et de retrouver les résultats (s’il y en a)
L’API est un ensemble d’interfaces et de classes conçues pour
effectuer des actions sur toute base de données (mySQL, ORACLE,
SYBASE, ODBC, Derby)
Utilisation d’un gestionnaire de pilotes JDBC
Un pilote JDBC spécifique à une base de données implémente
l’interface java.sql.Driver
Peut dialoguer avec tout pilote conforme à l ’API JDBC où les
pilotes sont disponibles à java.sun.com/products/jdbc
JDBC en quatre étapes
keulkeul.blogspot.com
Charger le pilote
Se connecter à la base
Créer et exécuter une requête SQL
Traiter le résultat si nécessaire Servlets - M. Baron - Page 79
Se connecter aux bases de données : charger un pilote
Le pilote est obligatoire, il convertit les appels JDBC en appels
natifs. Il est nécessaire de connaître le nom de la classe du
pilote JDBC que l’on veut utiliser La librairie
Pilote ORACLE : oracle.JDBC.driver.OracleDriver (généralement .jar)
désignant le pilote
Pilote JDBC/ODBC : sun.jdbc.odbc.JdbcOdbcDriver doit être placé dans
Pilote mySQL : com.mysql.jdbc.Driver le répertoire
WEB-INF/lib
Pilote Derby : org.apache.derby.jdbc.ClientDriver
Le chargement du pilote se fait en utilisant la méthode
Class.forName(String Pilote) throws ClassNotFoundException
Chargement du pilote
Exception levée sur
Derby
la classe pilote n’est
keulkeul.blogspot.com
pas trouvée
Class.forName("org.apache.derby.jdbc.ClientDriver");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Chargement du
pilote ODBC Servlets - M. Baron - Page 80
Se connecter aux bases de données : se connecter à la
base
Pour se connecter à une base de données il faut fournir une
URL qui indique où se trouve la base
URL ORACLE : jdbc:oracle:thin:host:port:idbase
URL ODBC : jdbc:odbc:IDDSN
URL mySQL : jdbc:mysql:host
Exception levée si la connexion à
URL Derby : jdbc:derby:host la base est impossible
La connexion à la base se fait en utilisant la méthode
DriverManager.getConnection("URL","user","pass") throws SQLException
Connexion à une base
mySQL nommée Espoir
Connection ma_connexion =
keulkeul.blogspot.com
DriverManager.getConnection("jdbc:mysql://localhost/Espoir","michael","baro
n");
Connection ma_connexion =
DriverManager.getConnection("jdbc:oracle:thin:@dbhost:1528:ORCL","michael",
"baron");
Connexion à une base
ORACLE nommée ORCL Servlets - M. Baron - Page 81
Se connecter aux bases de données : créer et exécuter
une requête SQL
La requête ne peut être créée et exécutée que si le pilote et
la connexion à la base se sont valides
Il faut avant tout créer une instruction SQL sur la base
createStatement() throws SQLException
Exception levée si l ’instruction
SQL ne peut être créée
Statement mon_statement = ma_connexion.createStatement();
La référence de la connexion à
une base de données
Il faut enfin exécuter la requête en écrivant concrètement le
requête SQL executeQuery(String requete) throws SQLException
keulkeul.blogspot.com
Exception levée si le requête
SQL n’est pas correcte
ResultSet mon_resultat = mon_statement.executeQuery("SELECT * FROM `table`");
La requête SQL
Référence de l’instruction SQL
Servlets - M. Baron - Page 82
Se connecter aux bases de données : traiter le résultat
Enfin il faut traiter un objet de type ResultSet il existe de
nombreuses méthodes
boolean next() : avancer d’une ligne de la table résultante
String getString(String columName) : interroger un champ String par
son nom
String getString(int columnIndex) : interroger un champ String par son
index
int getInt(…) : interroger un champ Integer par son nom ou index
Accède à la prochaine ligne
… s’il y en a
keulkeul.blogspot.com
while (mon_resultat.next()) {
String colonne1 = mon_resultat.getString(1);
out.println("Nom:" + colonne1);
}
Affiche le résultat en ligne Servlets - M. Baron - Page 83
Se connecter aux bases de données
Exemple : Servlet qui interroge une base de données mySQL
public class DataBaseServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html"); DataBaseServlet.java du projet
PrintWriter out = res.getWriter(); DataBaseConnection
try {
Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection ma_connexion =
DriverManager.getConnection("jdbc:derby://localhost:1527/PersonDB");
Statement mon_statement = ma_connexion.createStatement();
ResultSet mon_resultat = mon_statement.executeQuery("SELECT NAME,
FIRSTNAME, OLDYEAR FROM PERSON");
while (mon_resultat.next()) {
out.print("Nom : " + mon_resultat.getString(1));
out.print(" Prénom : " + mon_resultat.getString(2));
out.println(" Age : " + mon_resultat.getInt(3));
out.println("<br>");
}
keulkeul.blogspot.com
} catch(SQLException e) {
...
}
}
}
N’oubliez pas dans la requête
SQL les cotes ` ` entre les
différentes tables
Servlets - M. Baron - Page 84