Vous êtes sur la page 1sur 8
SERVLET (2/2) 60 Maintien de l'état Le protocole HTTP est un protocole sans état impossibilité
SERVLET (2/2)
SERVLET (2/2)

60

Maintien de l'état Le protocole HTTP est un protocole sans état impossibilité de garder des
Maintien de l'état
Le protocole HTTP est un protocole sans
état
impossibilité de garder des informations
d’une requête à l’autre
impossibilité d'identifier un client d’un autre
entre 2 requêtes
Solutions =
les champs cachés
la réécriture d'URLs
les cookies
les sessions

61

Champs cachés et réécriture d'URL Champs cachés Information dans la page HTML cachée à l'utilisateur
Champs cachés et réécriture d'URL
Champs cachés
Information dans la page HTML cachée à l'utilisateur
<input type="hidden" name="secret" value="Chuuuut !" />
Positionné dans la balise <form>
Transmis au serveur lorsque le formulaire est soumis
Note : suivre un lien hypertexte en dehors du formulaire n'envoie
pas l'information au serveur
Réécriture d'URL
Sauver l'état dans l'URL
http://www.monsite.com/mapage?user=toto
Chaque URL est une requête de type "GET"
URL parfois longue car elle doit contenir toute
l'information liée à l'état

62

Cookies Informations textuelles envoyées par un serveur Web à un client (navigateur). Lorsqu’un client reçoit
Cookies
Informations textuelles envoyées par un serveur Web à un
client (navigateur). Lorsqu’un client reçoit un cookie, il le
stocke localement et le renvoie ensuite au serveur chaque
fois qu’il accède à une page sur ce serveur
Paires de 'nom/valeur' échangées via les en-têtes HTTP
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=50BAB1DB58D5F833D78D9EC1C5A10C5;Path=/myDir
GET /myDir/servlet/SessionServlet HTTP/1.1
Cookie: JSESSIONID=50BAB1DB58D5F833D78D9EC1C5A10C5
Les cookies ont une durée de vie paramétrable
Utilisations :
Suivi de session basé sur un identifiant unique
Personnalisation de l'application en fonction des choix du client

63

Cookies Limites : Ne contiennent que des chaînes de caractères Transmis à chaque requête =>
Cookies
Limites :
Ne contiennent que des chaînes de caractères
Transmis à chaque requête => impact sur les
performances
Déconseillés pour une utilisation sécurisée car la
valeur des paramètres est passée en clair dans la
requête
Le navigateur peut être paramétré pour les refuser
La taille et le nombre des cookies sont limités par le
navigateur pour des raisons de sécurité

64

Cookies Pour les manipuler : javax.servlet.http.Cookie Cookie(String name, String value) : constructeur String
Cookies
Pour les manipuler : javax.servlet.http.Cookie
Cookie(String name, String value) : constructeur
String get/setName() : retourne/attribue le nom du cookie
String get/setValue() : retourne/attribue la valeur du cookie
caractères non autorisés : espace [ ] ( ) = , " / ? @ : ;
setDomain(String) : assigne le nom du domaine (Généralement
laissé vide car le nom du serveur est assigné par défaut)
String get/setPath(String) : retourne/attribue le path où
s'applique le cookie
get/setMaxAge() : délai restant avant expiration du cookie (en
seconde)
Par défaut, durée de vie d'un cookie = la connexion courante

65

Cookies En pratique, la servlet : récupère les cookies liés à l'application dans la requête
Cookies
En pratique, la servlet :
récupère les cookies liés à l'application dans la
requête
Cookie[] HttpServletRequest.getCookies()
ajoute un cookie
HttpServletResponse.addCookie(Cookie)
modifie un cookie
ajouter un cookie avec le même nom et le même path
supprime un cookie
Cookie.setMaxAge(0) et l'ajouter dans la réponse
66
Cookies protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Cookies
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
PrintWriter out = res.getWriter();
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);
c.setMaxAge(60 * 60 * 24 * 365); // 1 an
res.addCookie(c);
out.println("Bonjour le nouveau");
} else {
out.println("Encore vous"); }
}
out.flush(); out.close();
}

67

Sessions Les sessions Permettent de stocker les informations des clients côté serveur et non du
Sessions
Les sessions
Permettent de stocker les informations des clients côté serveur
et non du côté client
Pallient aux limites des cookies : stockage d'objets complexes
et pas de limite de taille
Attention : elles ne sont pas persistantes et se terminent à la
déconnexion du client !
Objets de type javax.servlet.http.HttpSession
Obtenir une session à partir de HttpServletRequest
HttpSession getSession()
retourne la session associée à l’utilisateur
HttpSession getSession(false)
la session est récupérée ou null si elle n'existait pas déjà
HttpSession getSession(true)
la session est récupérée ou ouverte si elle n'existait pas déjà

68

Sessions Manipuler la session à partir de HttpSession setAttribute(String, Object) création/remplacement d'un
Sessions
Manipuler la session à partir de HttpSession
setAttribute(String, Object)
création/remplacement d'un attribut
Object getAttribute(String)
retourne un attribut par son nom
removeAttribute(String)
supprime un attribut par son nom
Enumeration getAttributeNames()
retourne le nom de tous les attributs
invalidate()
invalide l’ensemble de la session et libère tous les
objets qui y sont associés

69

Sessions Un compteur de visites au cours d'une même session public class SessionServlet extends HttpServlet
Sessions
Un compteur de visites au cours d'une même session
public class SessionServlet 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.");
}
}

70

Sessions : suivi Il existe 2 moyens de gérer les sessions (transparent) : à l'aide
Sessions : suivi
Il existe 2 moyens de gérer les sessions (transparent) :
à l'aide de cookies (par défaut)
à l'aide re la réécriture d'URL
Cookies
A chaque session créée, le serveur envoie un identificateur
(cookie) correspondant au client. Ensuite le client renverra ce
cookie au serveur lors de sa prochaine requête permettant ainsi
au serveur d'identifier le client => mais les cookies peuvent être
désactivés !
Réécriture des URLs
Le serveur ajoute l'identificateur de session à la fin de chaque
URL des pages envoyées par celui-ci
Cette technique a un coût pour le serveur : il doit personnifier
l'URL en y incluant l'identifiant de session

71

Sessions : suivi Réécriture des URLs 2 méthodes existent pour individualiser les URL: String
Sessions : suivi
Réécriture des URLs
2 méthodes existent pour individualiser les URL:
String HttpServletResponse.encodeRedirectURL(String)
res.sendRedirect(res.encodeRedirectURL("/servlet/login");
String HttpServletResponse.encodeURL(String)
out.println("<A HREF=\"/servlet/toto\">Go</A>");
// à remplacer par
out.print("<A HREF=\"" + res.encodeURL(req.getContextPath() +
"/servlet/toto") + "\">Go</A>");
http://localhost:8080/monAppli1/servlet/toto;jsessionid=c0o7fszeb1
Ces méthodes réécrivent l'URL uniquement si le client n'accepte pas
les cookies. Dans l'autre cas l'URL reste inchangée
Limitations des 2 approches : pas de données volumineuses,
caractères non autorisés, longueur URL, données visibles (sécurité)

72

Sessions : web.xml <session-timeout> : permet de définir la durée en minutes pendant laquelle la
Sessions : web.xml
<session-timeout> : permet de définir la durée en
minutes pendant laquelle la session d'un utilisateur
reste active
web.xml
<web-app>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>

73

ServletContext : Partage d'informations Les servlets d'une même application peuvent partager des informations
ServletContext : Partage d'informations
Les servlets d'une même application peuvent partager des
informations au moyen du contexte ( ≠ session ! )
Le conteneur de servlet gère un contexte par application
Le contexte peut servir à communiquer :
de l'information entre servlets d'une même application (ou non)
avec le conteneur de servlet (Obtenir des ressources sur le serveur,
écrire dans un fichier de log)
Le contexte implémente l'interface ServletContext et est accessible
par getServletContext() via HttpServlet
Partage d’information inter-servlets :
Enumeration getAttributeNames()
retourne l’ensemble des noms de tous les attributs liés
Object getAttribute(String)
retourne l’objet sous le nom indiqué
void setAttribute(String, Object)
lie un objet au nom indiqué
void removeAttribute(String)
supprime l’objet lié sous le nom indiqué

74

ServletContext : Partage d'informations Partage d’information inter-applications Possibilité de partager des
ServletContext : Partage d'informations
Partage d’information inter-applications
Possibilité de partager des informations entre contextes web
d'un même serveur
Solution : la Servlet recherche un autre contexte à partir de
son propre contexte
ServletContext getContext(String uri) : obtient le contexte à partir
d’un chemin URI (chemin absolu)
Obtenir des ressources de l'application à partir du
contexte courant
Set getResourcePaths(String) : Liste des chemins à partir
d'un chemin ("/META-INF/", "/WEB-INF/", etc.)
String getRealPath(String) : obtenir le chemin absolu à partir
d'un chemin relatif de l'application
URL getResource(String)
InputStream getResourceAsStream(String)

75

ServletContext : Gestion des traces Produire des logs dans Tomcat (<tomcat>/logs/): void log(String) void
ServletContext : Gestion des traces
Produire des logs dans Tomcat (<tomcat>/logs/):
void log(String)
void log(String, Throwable)
Servlet
public void doGet(
)
{
getServletContext().log("A message");
try {
//
} catch (Exception e) {
getServletContext().log("An exception occurred", e);
}
Tomcat
2007-10-06 21:12:54 A message
2007-10-06 21:12:54 An exception occurred
java.io.IOException
at com.master2.MyServlet.doGet(Unknown Source)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)

76

ServletContext : web.xml Des informations de contexte peuvent être définies dans le descripteur web.xml Ces
ServletContext : web.xml
Des informations de contexte peuvent être définies
dans le descripteur web.xml
Ces informations sont accessibles par toutes les
servlets de l'application web
String ServletContext.getInitParameter(String)
web.xml
<web-app>
<context-param>
<param-name>annee</param-name>
<param-value>2007</param-value>
<description>une description
</context-param>
</web-app>
</description>

77

Collaboration de servlets Les servlets peuvent partager ou déléguer le contrôle de la requête Deux
Collaboration de servlets
Les servlets peuvent partager ou déléguer le contrôle de
la requête
Deux types de collaborations :
Délégation : une Servlet peut renvoyer une requête entière à
une autre servlet
Inclusion : une Servlet peut inclure du contenu généré par une
autre servlet
Les avantages sont :
Délégation de compétences
Meilleure abstraction et architecture logicielle MVC
Interface gérant la collaboration :
javax.servlet.RequestDispatcher
Une instance de RequestDispatcher est obtenue :
Sur la requête : getRequestDispatcher(String path)
path est le chemin relatif ou absolu d'une ressource (servlet, JSP,
fichier statique, …) ne pouvant pas sortir du contexte courant

78

Collaboration de servlets : redirection Pour distribuer en dehors du contexte courant, il faut :
Collaboration de servlets : redirection
Pour distribuer en dehors du contexte courant, il faut :
Identifier le contexte extérieur : utilisation de getContext(String uri)
Utiliser ensuite getRequestDispatcher(String path)
Note : les chemins sont uniquement en absolu
Redirection de la requête d’une servlet vers une autre
ressource sur le serveur
Types de redirection :
Effectuée par le serveur sur le même serveur
void RequestDispatcher.forward(ServletRequest, ServletResponse)
Effectuée par le serveur sur un autre serveur
void RequestDispatcher.sendRedirect(String)
Possibilité de transmettre des informations lors de la
redirection
en utilisant les attributs de requête via la méthode
setAttribute(
)
en attachant des paramètres à l’URL
79
Collaboration de servlets : redirection Illustration de redirection interne public class Emetteur extends HttpServlet {
Collaboration de servlets : redirection
Illustration de redirection interne
public class Emetteur extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
req.setAttribute("nom", "toto"); // getAttribute(
)
pour
// retrouver la valeur
RequestDispatcher disp =
req.getRequestDispatcher("/recepteur.do?age=22");
disp.forward(req, res);
// Ne rien faire sur req et res
}
}
public class Recepteur extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
out.println(req.getParameter("age")); // chaîne de caractères
out.println(req.getAttribute("nom")); // objet
}

}

Collaboration de servlets : redirection Illustration de redirection externe : alternative 1 : redirection différée
Collaboration de servlets : redirection
Illustration de redirection externe : alternative 1 : redirection différée
du client vers une autre URL
public class ClientMove extends HttpServlet {
static final String NEW_HOST = "http://www.newhost.com";
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
String newLocation = NEW_HOST + req.getRequestURI();
res.setHeader("Refresh", "5; URL=" + newLocation);
out.println("Changement d'URL : <A HREF=\"");
out.println(NEW_HOST+ "\">"+ NEW_HOST +"</A><BR>");
out.println("Vous serez redirigé dans 5 secondes
");
}
}
Illustration de redirection externe : alternative 2 : redirection
immédiate du client vers une autre URL :
sendRedirect(String)
81
Collaboration de servlets : inclusion Inclusion du contenu d’une ressource dans la réponse courante (Jsp,
Collaboration de servlets : inclusion
Inclusion du contenu d’une ressource dans la
réponse courante (Jsp, servlet, fichier texte
)
void RequestDispatcher.include(
ServletRequest req, ServletResponse res)
La différence avec une redirection 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 utilisant les attributs de requête via la méthode
setAttribute(
)
82
Collaboration de servlets : inclusion public class Regroupage extends HttpServlet { protected void
Collaboration de servlets : inclusion
public class Regroupage 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("/inclus.do");
dispat.include(req,res); out.println("<BR />");
req.setAttribute("bonjour", "Bonjour");
dispat.include(req,res); out.println("<BR />");
req.setAttribute("bonsoir", "Bonsoir");
dispat.include(req,res); out.println("<BR />");
out.println("</BODY></HTML>");
}
}
public class Inclus 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"); }

}

}

83

Servlet et Thread Une servlet ne possède qu'une seule instance (singleton) qui est attaquée par
Servlet et Thread
Une servlet ne possède qu'une seule instance
(singleton) qui est attaquée par plusieurs
threads à la fois (1 thread / client)
Problèmes :
Plusieurs threads peuvent traverser la méthode
service() en même temps => ne sont pas thread
safe ni les variables d'instance, les contextes, les
sessions
Cas d'un client qui clique plusieurs fois sur un bouton
"submit", ouvre plusieurs navigateurs, etc.
Accès concurrents sur une ressource : modification
d’un fichier commun, etc.

84

Servlet et Thread Solution 1 : utilisation de synchronized public class MyThread extends HttpServlet {
Servlet et Thread
Solution 1 : utilisation de synchronized
public class MyThread extends HttpServlet {
private int i = 0;
public void doGet(…)…{
synchronized(this) {
int tmp = ++i;
} public class MyThread extends HttpServlet {
… public void doGet(…)…{
User user = new User();
HttpSession session = req.getSession(true);
synchronized(session) {
session.setAttribute("user", user);
}
En général :
Les variables doivent être locales aux méthodes
Les attributs de classes ne peuvent être que de constantes de
configuration initialisées dans la méthode init()

85

Servlet et Thread Solution 2 : Utiliser l’interface SingleThreadModel implémentée par la servlet qui permet
Servlet et Thread
Solution 2 :
Utiliser l’interface SingleThreadModel implémentée par la
servlet qui permet d’indiquer au moteur de servlets que l’on
souhaite qu’une instance de la servlet ne soit attaquée que par
un Thread à la fois
Cette interface ne comporte aucune méthode à implémenter, elle ne
représente qu’un drapeau pour le moteur de servlet
86
web.xml : Gestion des erreurs <web-app> web.xml <servlet-mapping>
web.xml : Gestion des erreurs
<web-app>
web.xml
<servlet-mapping>
<servlet-name>ErrorServlet</servlet-name>
<url-pattern>/servletErr</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>javax.servlet.ServletException</exception-type >
<location>/servletErr</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/errorpages/error403.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type >
<location>/errorpages/error403.jsp</location>
</error-page>

87

web.xml : Filtres API javax.servlet.Filter Permet de consulter et transformer les en-têtes et le contenu
web.xml : Filtres
API javax.servlet.Filter
Permet de consulter et transformer les en-têtes et le
contenu des requêtes et des réponses
Traitement s’interposant entre le client et la ressource
requise (Servlet, JSP, fichier)
Chaînage de filtres selon l’ordre de déclaration dans
web.xml
Exemple de filtres
Authentification, blocage des adresses IP
Conversion (Image), Transformation (XSLT)
Chiffrage, Compression
Log,

88

Transformation (XSLT) Chiffrage, Compression Log, 88 web.xml : Filtres Web.xml <filter>
web.xml : Filtres Web.xml <filter> <filter-name>LogFilter</filter-name>
web.xml : Filtres
Web.xml
<filter>
<filter-name>LogFilter</filter-name>
<display-name>LogFilter</display-name>
<description>envoie des logs</description>
<filter-class>myapp.filters.LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/unPath/*</url-pattern>
Filtre
</filter-mapping>
http://localhost:8080/appli/unPath
public class LogFilter implements javax.servlet.Filter {
private FilterConfig config;
public void init(FilterConfig fc) throws ServletException {
config = fc;
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
config.getServletContext().log(
"Request received from: " + req.getRemoteHost());
chain.doFilter(req, res);
}

public void destroy() { }

}

89

web.xml : Accès à des paramètres <env-entry> Web.xml <env-entry-name>nom</env-entry-name>
web.xml : Accès à des paramètres
<env-entry>
Web.xml
<env-entry-name>nom</env-entry-name>
<env-entry-value>toto</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
Servlet
Context ctx = new InitialContext();
String value = (String) ctx.lookup("java:/comp/env/nom");
Centralisation de paramètres dans le fichier web.xml
accessibles aux servlets de l'application
Illustration : paramètres d'accès à une base de données

90

web.xml : Autres fonctionnalités Web.xml permet également de paramétrer : Observateurs de session : réagir
web.xml : Autres fonctionnalités
Web.xml permet également de paramétrer :
Observateurs de session : réagir face à des
événements intervenants dans la session
Mapping de types MIME : lorsque des fichiers sont
envoyés au client, Tomcat génère automatiquement
un en-tête "Content-Type" pour les types définis
dans le descriteur
Références d'EJB
Configuration des sources de données (appels
JNDI)
Configuration de la JSP et des tags JSP (à voir)
Contraintes de sécurité (à voir)
etc.

91