Programmation JEE/Servlets

Un livre de Wikilivres.
Aller à : navigation, rechercher

Un servlet est une classe JAVA coté 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 | modifier le wikitexte]

Exemple de servlet[modifier | modifier le wikitexte]

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 | modifier le wikitexte]

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

Déployement sous TomCat[modifier | modifier le wikitexte]

  • 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 | modifier le wikitexte]

http://localhost:999/webTest/Hello

Résultat dans le browser :

Hello World

Anatomie de l'url[modifier | modifier le wikitexte]

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

Méthodes d'informations sur l'URL[modifier | modifier le wikitexte]

          // 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 | modifier le wikitexte]

          // Recuperation du parametre par le nomParametre
        request.getParameter(nomParametre);
 
 // Retourne une enumeration de tous les parametres d'une requete
request.getParameterNames();
 
 // Retourne toutes les valeurs du parametre de nomParametre
        request.getParameterValues(nomParametre);
 
          // Retourne une iteration de nom de parametres
        request.getParameterMap();

Méthodes de lecture des En-Têtes[modifier | modifier le wikitexte]

          // 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 | modifier le wikitexte]

          // 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 | modifier le wikitexte]

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 | modifier le wikitexte]

  • (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 | modifier le wikitexte]

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 | modifier le wikitexte]

RequestDispatcher[modifier | modifier le wikitexte]

include[modifier | modifier le wikitexte]

Inclusion d'une ressource externe.

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

forward[modifier | modifier le wikitexte]

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 | modifier le wikitexte]

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

location[modifier | modifier le wikitexte]

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 | modifier le wikitexte]

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

Filtres[modifier | modifier le wikitexte]

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 | modifier le wikitexte]

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 | modifier le wikitexte]

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);
  }
}