Un servlet est une classe JAVA côté serveur qui reçoit des données HTTP et qui opère un ou des traitements et devant respecter les contraintes de ce protocole HTTP.

Les servlets

modifier

Exemple de servlet

modifier
package servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class Hello
 */
@WebServlet("/Hello")
public class Hello extends HttpServlet {

    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public Hello() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)              
                                               throws ServletException, IOException {
 
        // TODO Auto-generated method stub
       
        response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
        try {
            out.println("Hello World");
        } finally {
            out.close();
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub

        doGet(request,response);
    }
}

Description

modifier

On remarque deux méthodes dans cette classe : doGet et doPost, la première répond par HTTP à l’envoi d'une requête GET, la seconde à l'envoi d'une requête POST. Comme l'on veut que dans les deux cas la servlet réponde, doPost renvoie à doGet.

Déployement sous TomCat

modifier
  • Placer la classe compilée avec son package dans le répertoire classes de WEB-INF du répertoire web de travail (ici : webTest)
  • Modifier le web.xml de WEB-INF en ajoutant :
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">  

  <!-- Début ici -->

    <servlet>
      <servlet-name>Hello</servlet-name><!-- Nom de la classe -->
      <servlet-class>servlet.Hello</servlet-class><!-- Arborescence de la classe : avec le package -->
    </servlet>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name><!-- Nom de la classe -->
        <url-pattern>/Hello</url-pattern><!-- Pattern de la classe dans l'url -->
    </servlet-mapping>

   <!-- Fin ici -->

<web-app>

Le WEB-INF comprend donc :

   WEB-INF
     web.xml
     classes
       servlet
         Hello.class

Appel de la servlet

modifier

http://localhost:999/webTest/Hello

Résultat dans le navigateur :

Hello World

Anatomie de l'url

modifier

[Protocol://][DNS]:[PORT]/[RootEntryDirectory]/[ServletName]

Méthodes d'informations sur l'URL

modifier
          // Retourne le nom du serveur
        request.getServerName();

          // Retourne le port du serveur
        request.getServerPort();

          // Retourne le nom de l'application hébergeant la servlet
        request.getContextPath();

          // Retourne le chemin de la servlet
        request.getServletPath();

          // Retourne type de la requete http utillisee
        request.getMethod();

          // Retourne parametres passes dans URL
        request.getQueryString();

          // Retourne URL utilisee pour contacter la servlet
        request.getRequestURL();

          // Retourne l'adresse locale
        request.getLocalAddr();

        request.getLocalName();

        request.getLocalPort();

        request.getRemoteAddr();

        request.getRemoteHost();

Exemple dans la servlet :

package servlet;

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class Hello
 */
@WebServlet("/Hello")
public class Hello extends HttpServlet {
private static final long serialVersionUID = 1L;
   
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Hello() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {
    out.println(request.getServerName());
    out.println("<br/>");
    out.println(request.getServerPort());
    out.println("<br/>");
    out.println(request.getContextPath());
    out.println("<br/>");
    out.println(request.getServletPath());
    out.println("<br/>");
    out.println(request.getMethod());
    out.println("<br/>");
    out.println(request.getQueryString());
    out.println("<br/>");
    out.println(request.getRequestURL());
    out.println("<br/>");
    out.println(request.getLocalAddr());
    out.println("<br/>");
    out.println(request.getLocalName());
    out.println("<br/>");
    out.println(request.getLocalPort());
    out.println("<br/>");
    out.println(request.getRemoteAddr());
    out.println("<br/>");
    out.println(request.getRemoteHost());
    } finally {
    out.close();
    }
    }
   
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
   
      processRequest(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
     throws ServletException, IOException {
    // TODO Auto-generated method stub

    processRequest(request, response);
    }
}

Cet appel : http://localhost:999/webTest/Hello

localhost
999
/webTest
/Hello
GET
null
http://localhost:999/webTest/Hello
127.0.0.1
localhost
999
127.0.0.1
127.0.0.1

Méthodes de lecture des paramètres

modifier
          // Récuperation du paramètre par le nomParametre
        request.getParameter(nomParametre);

 // Retourne une énumeration de tous les paramètres d'une requête
request.getParameterNames();

 // Retourne toutes les valeurs du paramètre de nomParametre
        request.getParameterValues(nomParametre);

          // Retourne une itération de nom de paramètres
        request.getParameterMap();

Méthodes de lecture des En-Têtes

modifier
          // Retourne les noms du header
        request.getHeaderNames();

 // Retourne les headers
request.getHeaders();

 // Retourne le nombre d'octets dans la requête
        request.getContentLength();

          // Retourne le type de contenu de la requête
        request.getContentType();

          // Retourne la langue privilégiée
        request.getLocale();

          // Retourne la liste des langues
        request.getLocales();

          // Retourne la date du header
        request.getDateHeader(String name);

          // Retourne le header spécifié par le "name"
        request.getHeader(String name);

          // Retourne les headers spécifiés par le "name"
        request.getHeaders(String name);

Méthodes d'ajout d'informations à la requête

modifier
          // Assure le stockage d'un objet dans l'objet HttpServletRequest
        request.setAttribute(String name, Object o);

          // Retourne l'objet stocké "name"
        request.getAttribute(String name);

          // Returne une enumeration des noms d'attributs
        request.getAttributeNames();

          // Supprime l'attribut "name" des attributs de la requête
        request.removeAttribute(String name);

Méthodes d'ajout des en-têtes

modifier

Les en-têtes HTTP sont utilisés pour ajouter à la réponse des informations supplémentaires.

          // Cette méthode permet d'indiquer la nature des informations présentes dans la réponse
        response.setContentType(String type);

          // Cette méthode indique la langue locale
        response.setLocale(Locale loc);

          // Cette méthode ajoute le header "name" avec sa valeur "value"
        response.addHeader(String name, String value);

Élaboration du corps de la réponse

modifier
  • (PrintWriter)getWriter() permet de transferer du texte dans le corps de la réponse HTTP
  • (ServletOutputStream)getOutputStream() permet de transférer du binaire dans le corps de la réponse HTTP

Ne jamais utiliser ces deux objets simultanément sous peine d'une exception IllegalStateException

Voici un exemple d'envoi binaire:

package servlet;

import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ReponseHttp2
 */
@WebServlet("/ReponseHttp2")
public class ReponseHttp2 extends HttpServlet {
private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ReponseHttp2() {
        super();
        // TODO Auto-generated constructor stub
    }
   
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    response.sendRedirect("images/toto.jpg");
    }
   
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request,response);
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request,response);
}

}
  • Dans cet exemple nous faisont appel à processRequest(request, response) pour obtenir invariablement le traitement en get et post

Élaborer une réponse HTTP

modifier

Les codes de status sont répartis en 5 catégories :

1XX : informatif
2XX : succès
3XX : redirection
4XX : erreur client
5XX : erreur serveur

Le détail des codes est disponible chez http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

  • setStatus(int rc)
  • sendError(int sc, String message)

... permettent de changer le status d'erreur de la page. Pour exemple nous allons générer une erreur serveur.

package servlet;

import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ReponseHTTP
 */
@WebServlet("/ReponseHTTP")
public class ReponseHTTP extends HttpServlet {
private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ReponseHTTP() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {
    response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "le serveur est surchargé. Veuillez réessayer plus tard");
    } finally {
    out.close();
    }
    }
   
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}

}

Autres ressources

modifier

RequestDispatcher

modifier

include

modifier

Inclusion d'une ressource externe.

RequestDispatcher rd = null;
rd = getServletContext().getRequestDispatcher("/header.html");
rd.include(request, response);

forward

modifier

Transfert du resultat d'une servlet vers une autre ressource.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.HttpServlet;
import javax.servlet.HttpServletRequest;
import javax.servlet.HttpServletResponse;

public class Result extends HttpServlet {
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
     throws ServletException, IOException {
       
       response.setContentType("text/html;charset=UTF-8");
       PrintWriter out = response.getWriter();
       try {
         int result = 10;
         RequestDispatcher rd = null;
         rd = getServletContext().getRequestDispatcher("/result.jsp");
         request.setAttribute("resultat", result);
         rd.forward(request, response);
       } finally {
         out.close();
       }
   }
}

La ressource de destination : result.jsp

<%@page contentType="text/html" pageEncoding="UTF-8">
<%@page import="java.text.*" %>
<html>
  <body>
    <%
    resultat=(double) request.getAttribute("resultat");
    %>

    Resultat : <%= resultat %>
  </body>
</html>

Redirection

modifier

Le serveur informe le navigateur de faire une requête HTTP vers l'url indiquée.

location

modifier
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // Pour une réponse HTTP 301
response.setHeader("location", "http://www.google.be"); // Pour une réponse HTTP 302

redirect

modifier
response.sendRedirect("http://www.google.be");

Filtres

modifier

Les filtres ajoutent un traitement sur une requête HTTP avant qu'elle soit reçue par une servlet ou sur la réponse HTTP avant qu'elles soient transmises.

Leurs roles sont :

  • Contrôle des accès
  • Journalisation des accès
  • Décompression des données
  • Décryptage
  • Conversion des données

Plusieurs réponses peuvent être exécutées successivement. La classe filtre doit implémenter javax.servlet.Filter.

Évènements

modifier

Les évènements nous informent des opérations de l'application comme l'instanciation et la destruction des objets.

  • Évènements liés à l'application : Ceux déclenchés par servlet context.
  • Évènements liés aux sessions : Les classes de ce type doivent implémenter HttpSessionListener, HttpSessionAttributeListener.

Synchronisation des servlets

modifier

Cette synchronisation permet d'éviter au serveur d'utiliser deux threads en même temps, par exemple, lorsque deux instances de la même classe appellent une même méthode par deux clients différents. synchronized(this){} doit être appliquées aux traitements critiques comme les compteurs.

public class ... {
  public void method() {
    out = response.getWriter();
    synchronized(this) {
      compteur++;
    }
    out.println("La valeur du compteur est " + compteur);
  }
}