La technologie des Servlets
Présentation du protocole HTTP
Caractéristiques du protocole HTTP (Hyper Text Transmission Protocol) :
- Basé sur TCP/IP (port 80).
- Une structure client/serveur (voir schéma).
- Pas de notion de session (les requêtes sont indépendantes).

Les requêtes HTTP
Forme générale d'une requête :
attribut1: valeur1
attribut2: valeur2
....
<ligne vide>
Un exemple (notez la ligne vide à la fin) :
GET /index.html HTTP/1.0
accept: */*
connection: keep-alive
cache-control: no-cache
Les requêtes de lecture
♦ Méthode GET : récupération de données identifiées par l'URI.
♦ Méthode HEAD : demande d'informations sur les données identifiées par l'URI (pas de transmission de données).
♦ Méthode POST : identique à GET, mais le client ajoute à la requête un ensemble de paires :
nom1=valeur1 nom1=valeur2 nom2=valeur3 ...
Vous pouvez noter qu'il est possible d'associer plusieurs valeurs au même nom.
Les requêtes de modification
♦ Méthode PUT : dépose d'un fichier.
♦ Méthode OPTIONS : interroge le serveur sur les méthodes disponibles sur une URI donnée.
♦ Méthode DELETE : ...
♦ Méthode TRACE : ...
Les réponses HTTP
Forme générale d'une réponse :
attribut1: valeur1
attribut2: valeur2
....
<ligne vide>
données
Un exemple (notez la ligne vide) :
HTTP/1.0 200 OK
server: Apache...
date: ...
content-Type: text/html
<html>
....
</html>
Les codes de réponse HTTP
Les principaux codes de réponse :
| 200 | requête exécutée avec succès |
| 301 | ressource déplacée définitivement |
| 302 | ressource déplacée temporairement |
| 403 | requête non autorisée |
| 404 | ressource non disponible |
| 500 | erreur interne du serveur |
| ... | ... |
Retrouvez les principaux codes sur http://www.codeshttp.com/ ou directement dans la RFC2616.
Applications WEB
Principes des applications WEB :
- les requêtes sont interprétées par des applications,
- les réponses sont calculées en fonction du traitement des requêtes.

Solutions propriétaires et CGI
♦ CGI (Common Gateway Interface) une solution simple mais coûteuse :

Chaque requête donne lieu à la création d'un processus qui traite la requête et produit la réponse. La charge du système est donc très importante. Des langages de scripts (bash, perl, python, etc.) sont souvent choisis pour leur facilité de mise en oeuvre.
♦ API propriétaires non portables (ISAPI de Microsoft ou NSAPI de Netscape) :

Dans cette approche, chaque application WEB est une librairie ajoutée au serveur WEB. Nous suivrons la même idée dans le monde Java.
ASP, PHP et JSP
♦ ASP (Active Server Page) de Microsoft. Les pages ASP sont un mélange de VBscript et de HTML.
♦ PHP (PHP : Hypertext Preprocessor) même solution avec un langage de script conçu à cet effet.
♦ Servlet, JSP (Java Server Page) même solution avec un mélange de Java et HTML.
La technologie des Servlets
Application WEB Java
Une application WEB Java est constituée
- de classes qui traitent les requêtes (les servlets),
- de ressources statiques (JPG, CSS, (X)HTML, XML, XSL, etc.),
- de librairies Java (fichiers .jar),
- d'un fichier de configuration (web.xml).
Une application WEB a la structure suivante :
mon-application.war
| ressources statiques (html, jpg, css, ...)
+ WEB-INF/
| web.xml
+ classes/ contient les .class
+ lib/ contient les .jar
Ces fichiers peuvent être rangés dans une WAR (Web Application aRchive) en fait une archive jar.
Conteneur WEB
♦ Les applications sont déployées dans un conteneur WEB (aussi appelé un moteur de servlets) :

♦ Le conteneur WEB assure :
- le décodage des requêtes et le codage des réponses,
- l'aiguillage sur la bonne servlet (et la bonne application),
- la gestion des sessions,
- le cycle de vie des servlets,
- la gestion est l'allocation des threads.
Configuration (web.xml)
♦ le fichier web.xml :
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
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"
version="2.4">
<display-name>Application de test</display-name>
<description>Ma première application</description>
... déclarations des servlets ...
... correspondance servlets <--> url ...
</web-app>
♦ Déclaration des servlets :
<servlet>
<servlet-name>UneServletSimple</servlet-name>
<servlet-class>mypackage.SimpleServlet</servlet-class>
<init-param>
<param-name>jdbc.url</param-name>
<param-value>jdbc:mysql://machine/nomdebase</param-value>
</init-param>
...
<load-on-startup>2</load-on-startup>
</servlet>
La clause load-on-startup permet d'indiquer un ordre dans le chargement et l'initialisation des servlets.
♦ Mise en correspondance servlet versus URL :
<servlet-mapping>
<servlet-name>UneServletSimple</servlet-name>
<url-pattern>/simple*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UneServletSimple</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
URL rédirigés vers la servlet :
http://serveur-name/application-name/simple http://serveur-name/application-name/simple/hello.html http://serveur-name/application-name/simple/documents/7419.html http://serveur-name/application-name/simple/hello.do http://serveur-name/application-name/logout.do
Des méthodes s'appliquant sur la requête permettent de découper l'URL.
Ma première servlet
package mypackage;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import mybusiness.Business;
public final class SimpleServlet extends HttpServlet
{
Business bs = null;
public void init(ServletConfig c)
throws ServletException
{ bs = new Business(c); ... }
public void destroy()
{ bs.close(); ... }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{ ... }
}
♦ Détail de la méthode doGet :
public void doGet(
HttpServletRequest request,
HttpServletResponse response
)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
// appel de la couche métier
String result = bs.action(request.getParameter("data"));
writer.println("<html><body>");
writer.println("<h1>Hello</h1>");
writer.println("<p>" + result + "</p>");
writer.println("</body></html>");
}
Le cycle de vie d'une servlet
♦ Un exemple :

♦ C'est la même instance (éventuellement exécutée en parallèle dans plusieurs threads) qui traite les requêtes de tous les clients.
♦ Les Servlets peuvent être préchargées au lancement du serveur ou lancées à la demande.
Les interfaces de requête et de réponse
♦ javax.servlet.http.HttpServletRequest
public HttpSession getSession() public String getParameter(String name) public String[] getParameterValues(String name) ...
♦ javax.servlet.http.HttpServletResponse
public void setContentType(String type) public java.io.PrintWriter getWriter() throws ... public ServletOutputStream getOutputStream() throws ... public void addHeader(String name, String value) public void addCookie(Cookie cookie) ...
Servlet & formulaires HTML
♦ Un formulaire HTML :
<html><body>
<form action="test" method="POST">
Nom : <input type="text" name="nom" size="15"/><br/>
Prénom : <input type="text" name="prenom" size="15"/></br>
Statut : <select name="statut" size="1">
<option value="Etudiant">Etudiant</option>
<option value="Prof">Enseignant</option>
</select></br>
<input type="SUBMIT" name="boutonOK" value="Valider"/>
</form>
</body></html>
♦ La servlet test :
public void doPost(
HttpServletRequest request,
HttpServletResponse response
)
throws IOException, ServletException
{
response.setContentType("text/html");
response.getWriter().println("<html><body><p>Bonjour "
+ request.getParameter("prenom") + " "
+ request.getParameter("nom") + "</p></body></html>");
}
La gestion des sessions
♦ Principe : pour identifier le client, le serveur renvoi, dans la réponse à la première requête, un cookie (JESSIONID) :

♦ Les cookies sont tirés au hasard.
♦ Lors des requêtes suivantes, le client est repéré et le serveur peut lui associer une session :

Codage des sessions
♦ L'interface javax.servlet.http.HttpSession :
public Object getAttribute(String name) public void setAttribute(String name, Object value) public void invalidate() ...
Ces méthodes permettent de récupérer un objet depuis une session, de placer un objet dans une session et finalement, de vider une session.
Suivre les modifications de session
♦ Si un object implante l'interface
javax.servlet.http.HttpSessionBindingListener alors,
les évènements
void valueBound(HttpSessionBindingEvent event) ; void valueUnbound(HttpSessionBindingEvent event) ;
lui indiquent sont attachement ou son détachement d'une session.
♦ On peut également écouter les évènements :
- création, destruction, modification d'une session,
- changement dans le contexte d'une servlet,