Programmation JEE/Servlets
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
modifierExemple de servlet
modifierpackage 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
modifierOn 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
modifierhttp://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
modifierLes 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
modifierLes 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
modifierRequestDispatcher
modifierinclude
modifierInclusion d'une ressource externe.
RequestDispatcher rd = null;
rd = getServletContext().getRequestDispatcher("/header.html");
rd.include(request, response);
forward
modifierTransfert 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
modifierLe serveur informe le navigateur de faire une requête HTTP vers l'url indiquée.
location
modifierresponse.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
modifierresponse.sendRedirect("http://www.google.be");
Filtres
modifierLes 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
modifierLes é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
modifierCette 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);
}
}