Les servlets
Une servlet est un composant Web de Java EE. Elle permet de traiter une requête entrante sur un serveur et de générer une réponse dynamique. La plupart du temps, les servlets sont utilisées pour traiter des requêtes HTTP et générer dynamiquement une réponse.
L'API servlet est définie par la spécification JSR 340 et la version actuelle est la 3.1.
Structure d'une servlet HTTP
Une servlet HTTP est une classe Java qui hérite de la classe javax.servlet.http.HttpServlet :
package fr.epsi;
import javax.servlet.http.HttpServlet;
public class MyServlet extends HttpServlet {
}
Par défaut, la classe javax.servlet.http.HttpServlet fournit des méthodes doXXX (XXX représentant une méthode HTTP) qui seront appelées lorsque la servlet devra traiter une requête HTTP de la méthode correspondante.
HttpServlet dispose donc des méthodes doGet, doPost, doPut... L'implémentation par défaut de ces méthodes consiste à retourner un message d'erreur HTTP. Chaque servlet doit donc redéfinir les méthodes qui la concernent.
package fr.epsi;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* Exemple d'une servlet acceptant les requêtes HTTP GET
*/
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// traitement de la requête et génération du résultat à retourner au client
}
}
Les méthodes doXXX ont toutes deux paramètres : javax.servlet.http.HttpServletRequest et javax.servlet.http.HttpServletResponse qui représentent respectivement la requête HTTP entrante et la réponse renvoyée par le serveur.
Pour l'instant, les méthodes qui vont nous intéresser sur ces classes sont :
- String HttpServletRequest.setCharacterEncoding(String)
- Spécifie le format d'encodage des paramètres de la requête. Par défaut, l'encodage utilisé est ISO 8859-1 (Latin-1).
- String HttpServletRequest.getParameter(String)
- Retourne la valeur d'un paramètre d'une requête GET ou POST. La méthode attend le nom du paramètre et retourne sa valeur ou null si le paramètre n'existe pas.
- java.util.Map<java.lang.String,java.lang.String[]> HttpServletRequest.getParameterMap()
- Retourne une Map des paramètres d'une requête GET ou POST. La clé dans la Map correspond au nom du paramètre. La valeur est un tableau de chaînes de caractères. En effet, un paramètre peut être présent plusieurs fois dans une requête.
- void HttpServletResponse.setContentType(String)
- Positionne le type de contenu MIME de la réponse HTTP pour informer le client du format de la réponse. Par exemple : "text/html" pour une page HTML.
- void HttpServletResponse.setCharacterEncoding(String)
- Indique l'encodage caractère du flux de réponse. L'appel à HttpServletResponse.getWriter() tient compte de l'encodage positionné. Il faut donc appeler cette méthode avant HttpServletResponse.getWriter()
- java.io.PrintWriter HttpServletResponse.getWriter()
- Retourne un objet de type PrintWriter qui permet d'écrire la réponse dans le flux de sortie. L'objet PrintWriter offre des méthodes write pour générer une réponse au format texte (comme une page HTML).
- javax.servlet.ServletOutputStream HttpServletResponse.getOutputStream()
- Retourne un objet représentant le flux de sortie en mode binaire. Cette méthode est utile lorsque la réponse générée est au format binaire (comme une image par exemple).
package fr.epsi;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* Une servlet qui salue la personne qui envoie
* son nom dans le paramètre name.
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
resp.setContentType("text/plain");
resp.setCharacterEncoding("utf-8");
resp.getWriter().write("Hello " + name + "!");
}
}
Configuration du déploiement d'une servlet
Une servlet n'est pas une classe Java comme les autres, il s'agit d'un composant Java EE qui va être pris en charge par le serveur d'application. Le serveur d'application a besoin de savoir pour quelle(s) URL cette servlet sera responsable de traiter les requêtes et de fournir la réponse.
La méthode la plus simple pour configurer le déploiement d'une servlet consiste à utiliser l'annotation @WebServlet sur la classe.
package fr.epsi;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
resp.setContentType("text/plain");
resp.setCharacterEncoding("utf-8");
resp.getWriter().write("Hello " + name + "!");
}
}
Pour la servlet ci-dessus, l'annotation @WebServlet précise le motif de l'URL (URL pattern) pour lequel la servlet devra être sollicitée (dans cet exemple "/hello"). Une fois l'application déployée dans un serveur de test en local, une requête de la forme
http://localhost:8080/[nom de l'application]/hello?name=EPSI
devrait répondre
Hello EPSI!
Motif d'URL d'une Servlet
Comme nous l'avons vu dans la section précédente, une servlet pour être déployée a besoin d'un ou plusieurs motifs d'URL indiquant le chemin des requêtes qu'elle prend en charge. Il existe plusieurs syntaxes qui sont toutes équivalentes :
@WebServlet("/hello")
@WebServlet({"/hello"})
@WebServlet(urlPatterns={"/hello"})
Il est possible de donner plusieurs motifs d'URL indiquant que la même servlet peut être sollicitée à partir de chemins différents.
@WebServlet({"/hello", "/bonjour"})
@WebServlet(urlPatterns={"/hello", "/bonjour"})
Enfin, il est possible d'utiliser le caractère générique *. Par contre son utilisation est limitée car il ne peut apparaître que comme premier ou dernier élément d'un motif :
// Toutes les URL se terminant par .html
@WebServlet("*.html")
// Toutes les URL commençant par /hello/
@WebServlet("/hello/*")