La technologie des Servlets

Présentation du protocole HTTP

Le protocole HTTP (Hyper Text Transmission Protocol) :

Figure figures/jsp/http

Les requêtes HTTP

Forme générale d'une requête (la première ligne est obligatoire) :

<méthode> <URI> <protocole>
<attribut1>: <valeur1>
<attribut2>: <valeur2>
                                      <-- ligne vide

Un exemple (méthode GET, URI à /index.html, protocole à HTTP/1.0 et trois lignes d'attribus). Notez la ligne vide à la fin :

GET /index.html HTTP/1.0
accept: */*
connection: keep-alive
cache-control: no-cache
                                      <-- ligne vide

Les requêtes de lecture

Les réponses HTTP

Forme générale d'une réponse :

<protocole> <code> <description>
<attribut1>: <valeur1>
<attribut2>: <valeur2>
                                      <-- ligne vide
<les données>

Un exemple (notez la ligne vide) :

HTTP/1.0 200 OK
server: Apache...
date: 10-12-2020
content-Type: text/html
encoding: UTF-8
                                      <-- ligne vide
<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 :

Figure figures/jsp/appweb

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 web.xml de configuration.

Une application WEB a la structure suivante :

+ RACINE
    | 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 (qui est un ZIP).

Conteneur WEB

Figure figures/jsp/servlet

Les applications sont déployées dans un conteneur WEB qui assure

  • la connexion avec le serveur WEB,
  • 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.

Ma première servlet

package myapp.web;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

@WebServlet(  name = "UneServletSimple",
              description = "Une servlet simple",
              urlPatterns = { "/simple/*", "*.do" },
              loadOnStartup = 5
           )
public final class SimpleServlet extends HttpServlet { // Ancienne méthode

    // initialisation et terminaison de la servlet
    public void init( ... ) throws ServletException { ... }
    public void destroy() { ... }

    // traitement des requêtes GET et POST
    public void doGet( ... )    { ... }
    public void doPost( ... )   { ... }
}
URL traitées par la servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.getWriter()
            .append("ServerName: " + request.getServerName()  + "\n")
            .append("contextPath: " + request.getContextPath() + "\n")
            .append("ServletPath: " + request.getServletPath() + "\n")
            .append("PathInfo: " + request.getPathInfo());
}
GET http://myserver/myapp/simple/docs/hello.html
ServerName: myserver
contextPath: /myapp
ServletPath: /simple/
PathInfo: docs/hello.html
GET http://myserver/myapp/product/265/edit.do
ServerName: myserver
contextPath: /myapp
ServletPath: /product/265/edit.do
PathInfo: null

Détail de la méthode doPost :

public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {
  
    // récupération d'un paramètre de la requête
    String data = request.getParameter("data");

    // traitement métier
    String result = data.toUpper();

    // construire du résultat
    response.setContentType("text/html");
    PrintWriter writer = response.getWriter();

    writer.println("<html><body>");
    writer.println("<h1>Hello</h1>");
    writer.printf("<p> %s </p>", result);
    writer.println("</body></html>");
}

Il existe autant de méthodes à surcharger dans la classe HttpServlet que de méthodes HTTP.

Détails des méthodes d'initialisation / terminaison :

// initialisation de la servlet
public void init(ServletConfig c) throws ServletException {
    String value1 = c.getInitParameter("param1");
    ...
}

// terminaison de la servlet
public void destroy() {
    ...
}

Configuration (web.xml)

Le fichier web.xml (qui est optionnel) :

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">

    <display-name>Application de test</display-name>
    <description>Ma première application</description>

    <!-- déclarations des servlets -->
    <servlet> ... </servlet>

    <!-- correspondance servlets / URL -->
    <servlet-mapping> ... </servlet-mapping>

</web-app>

Déclaration des servlets :

<servlet>
    <servlet-name>UneServletSimple</servlet-name>
    <servlet-class>myapp.web.SimpleServlet</servlet-class>
    <init-param>
        <param-name>param1</param-name>
        <param-value>value1</param-value>
    </init-param>
    ...
    <load-on-startup>2</load-on-startup>
</servlet>

<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>

Le cycle de vie d'une servlet

Les interfaces de requête et de réponse

Servlet et formulaires HTML

Un formulaire HTML :

<html><body>
    <form action="processForm" method="POST">

      <label>Nom : </label>
        <input type="text" name="nom" size="15"/><br/>

      <label>Prénom : </label>
        <input type="text" name="prenom" size="15"/><br/>

      <label>Statut : </label>
        <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 processForm :

public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws IOException, ServletException
{
   String nom = request.getParameter("nom");
   String prenom = request.getParameter("prenom");
   
   response.setContentType("text/html");
   response.getWriter().printf(
      "<html><body><p>Bonjour %s %s</p></body></html>",
      prenom, nom
   );
}

La gestion des sessions

Codage des sessions

La durée de vie des sessions

Réglage de la durée de vie des sessions :

<web-app ... >

    ... premières déclarations ...
    ... déclaration des servlets ...

    <!-- durée de vie des sessions en minutes -->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

    ...
</web-app>

Suivre les modifications de session

Durée de vie des objets

Il existe plusieurs visibilité et durée de vie pour les objets Java :

Instances de porté requête :

// ranger un objet dans une requête
request.setAttribute("myObject", myObject);
...
// le récupérer
myObject = (MyObject) request.getAttribute("myObject");

Utilité : faire passer des données d'une servlet à une autre servlet (chaînage) ou d'une servlet à une page JSP.

fin de vie : fin du traitement de la requête.

Instances de porté session :

// ranger un objet dans une session
HttpSession session = request.getSession();
session.setAttribute("myObject", myObject);
...
// le récupérer
myObject = (MyObject) session.getAttribute("myObject");

Utilité : faire passer des données d'une requête à une autre requête émise par le même client. A titre d'exemples :

  • panier d'une application de commerce électronique,
  • utilisateur authentifié d'une application sécurisée

fin de vie : fin de la session (timeout ou invalidation).

Instances de porté application :

// ranger un objet dans la zone application
HttpSession session = request.getSession();
ServletContext context = session.getServletContext();
context.setAttribute("myObject", myObject);
...
// le récupérer
myObject = (MyObject) context.getAttribute("myObject");

Utilité : rendre des données ou des services accessibles à tous les clients. A titre d'exemples :

  • données métiers globales (liste des paniers),
  • services singletons,
  • paramêtres de l'application,

fin de vie : fin de l'application (durée de vie très longue).

La porté des instances Java :

Figure figures/jsp/scope