390 likes | 585 Views
Servlets. Objectifs. Pré-requis : HTML Java Principes de la programmation de pages web dynamiques (PHP, etc.) Configuration Apache TomCat Objectifs : Se familiariser avec les fonctionnalités des servlets. Qu'est-ce que les servlets ?. Une interface de l' API Java
E N D
Objectifs • Pré-requis : • HTML • Java • Principes de la programmation de pages web dynamiques (PHP, etc.) • Configuration Apache TomCat • Objectifs : • Se familiariser avec les fonctionnalités des servlets
Qu'est-ce que les servlets ? • Une interface de l'API Java • Un programme Java classique permettant de générer des pages Web dynamiques • En général, une servlet étend une des deux classes suivantes, qui implémentent javax.servlet.Servlet : • javax.servlet.http.HttpServlet (pour les requêtes HTTP) • javax.servlet.GenericServlet (pour les autres requêtes) • Les points d'entrée du client vers la servlet sont généralement les méthodes doGet() ou doPost() (selon la méthode HTTP utilisée pour la requête)
Exemple : classe Java import java.io.*; import javax.servlet.*; import javax.servlet.http.*; package exemple; public class MaPremiereServletextendsHttpServlet { public voiddoGet(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException { // Etape 1. Spécifier le type MIME du contenu de la réponse response.setContentType("text/html"); // Etape 2. Récupère le PrintWriter pour envoyer des données au client PrintWriterout = response.getWriter(); // Etape 3. Envoyer l’information au client out.println("<html>"); out.println(" <head><title>Bonjour</title></head>"); out.println(" <body>"); out.println(" <h1> Bonjour à tous </h1>"); out.println(" Il est : " + new java.util.Date()); out.println(" </body></html>"); } public voiddoPost(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException { doGet(request, response); } } java
Exemple : fichier de configuration <?xml version="1.0" encoding="UTF-8"> <web-appversion="2.5"xmlns="http://java.sun.com/xml/ns/javaee"> <servlet> <servlet-name>MaPremiereServlet</servlet-name> <servlet-class>exemple.MaPremierServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MaPremiereServlet</servlet-name> <url-pattern>/exemple</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> XML
Exemple servlet 3.0 Permet d’éviter le fichier de configuration import java.io.*; import javax.servlet.*; import javax.servlet.http.*; package exemple; @WebServlet(name="MaPremiereServlet", urlPatterns={"/exemple"}) public class MaPremiereServletextendsHttpServlet { … } java
Appel d'une servlet • Le serveur ne crée par défaut qu'une seule instance de chaque servlet • Un appel d'un client déclenche la création d'un nouveau thread qui manipule cette instance • Des appels simultanés génèrent donc plusieurs threads qui manipule la même instance ! • Attention donc à la synchronisation
Appel d'une servlet import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class BonThreadextendsHttpServlet { privateint compteur = 0; public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throwsServletException, IOException { synchronized(this) { inttmpCompteur = ++compteur; } PrintWriter out = res.getWriter(); out.println("Cette Servlet a été accédée " + tmpCompteur+ " fois."); } }
Appel d'une servlet • Pour qu'une instance différente soit générée à chaque appel, on implémente l'interface SingleThreadModel • Cela rend parfois la manipulation plus confortable mais consomme plus de mémoire et supprime quelques fonctionnalités
Initialisation d'une servlet • On peut personnaliser l'initialisation en redéfinissant la méthode : • public voidinit(ServletConfig config); • On peut refuser l'initialisation en lançant dans cette méthode l'exception UnavailableException. Par exemple : • throw new UnavailableException("Charge du serveur trop élevée", 120); • Refuse l'initialisation et impose un délai de 120 secondes avant de recommencer.
Exécution d'une servlet • Redéfinition d'une ou plusieurs de ces méthodes :qui sont appelées en passant deux objets de type HttpServletRequest (requête) et HttpServletResponse (réponse)
Destruction d'une servlet • Décidée par le moteur • Appel de la méthode • public void destroy() • que l'on peut redéfinir
Contexte d'un servlet • On peut définir un contexte permettant d'accéder aux autres ressources utilisées par l'application Web : • Servlets • JSP • Classes utilitaires • Documents statiques (HTML ou autres) • Applications client • méta-informations • On peut par exemple accéder au contexte de la façon suivante : public voidinit(ServletConfig config) { ServletContext contexte = config.getServletContext(); /* suite du code */ }
Contextes sous Tomcat • WEB-INF/web.xml : contient la description du contexte • WEB-INF/classes/ : contient les classes des servlets • WEB-INF/lib/ : contient les .jar utilisées par l'application • (et on peut archiver le tout dans un fichier .war) • Voir le fichier web.xml généré par eclipse • Le contexte est disponible dans toute l’application
Contexte d'un servlet Définition d’un paramètre d’initialisation dans web.xml <context-param> <param-name>contextParam1</param-name> <param-value>valeur 1</param-value> <description>La première valeur du contexte (paramètre d’initialisation)</description> </context-param>
À quoi sert une session ? (rappel) • Les sessions : • Maintiennent l’état du client pendant une série de requêtes du même utilisateur • Permettent d’identifier le client • Permettent de conserver les données au cours d’une série d’échanges • Plusieurs façons de faire en général : • Ajouter des variables d’identification à l’URL • Utiliser les champs cachés des formulaires • Manipuler des cookies • Mécanisme transparent en servlet : classe HttpServlet
Créer ou récupérer une session public class Caddie extendsHttpServlet{ public voiddoGet (HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException{ // Récupère la session HttpSessionsession = request.getSession(true); // … } } Si « true », crée la session si elle n’existe pas Si « false », renvoie null si la session n’existe pas
Stocker des attributs public class Caddie extendsHttpServlet{ public voiddoGet (HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException{ // Récupère la session HttpSessionsession = request.getSession(true); // L’âge de l’utilisateur est dans la requête // (issue d’un formulaire) intage = Integer.parseInt(request.getParameter("age_user")); // Conserve l’information dans la session session.setAttribute("age",new Integer(age)); } }
Récupérer des attributs public class Caddie extendsHttpServlet{ public voiddoGet (HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException{ // Récupère la session HttpSessionsession = request.getSession(true); // Récupère l‘âge de l'utilisateur intage= (int)session.getAttribute("age"); } }
Fermer une session public class Caddie extendsHttpServlet{ public voiddoGet (HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException{ // Récupère la session HttpSessionsession = request.getSession(true); // Ferme la session session.invalidate(); } }
Création de cookies public class Caddie extendsHttpServlet{ public voiddoGet (HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException{ // Création du cookie Cookie c = new Cookie("id","674684641"); // définition de la limite de validité c.setMaxAge(24*3600); // envoi du cookie dans la réponse HTTP response.addCookie(c); } }
Récupération des cookies public class Caddie extendsHttpServlet{ public voiddoGet (HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException{ // Récupération des cookies de la session Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { String name = cookie.getName(); Object value = cookies.getValue(); } } }
HttpSessionListener • Pour surveiller la création et la disparition de sessions • Méthodes : • voidsessionCreated(HttpSessionEvent se); • voidsessionDestroyed(HttpSessionEvent se); • (puis se.getSession() pour obtenir la session en question) • À déclarer dans web.xml (ou avec l’annotation @WebListener dans les servlets 3.0) web.xml <listener> <listener-class>exemple.sessionListenerExemple</param-name> </listener>
HttpSessionAttributeListener • Pour surveiller l’évolution des attributs de sessions • Méthodes : • voidattributeAdded(HttpSessionBindingEventevent); • voidattributeRemoved(HttpSessionBindingEventevent); • voidattributeReplaced(HttpSessionBindingEventevent); • (puis event.getSession(), event.getName() etevent.getValue() pour obtenir les informations sur l’attribut en question)
Informations sur le serveur import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ServeurInfoextendsHttpServlet { public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throwsServletException, IOException{ res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); out.println("Nom du serveur : " + req.getServerName() + " ."); out.println("Logiciel utilisé : " + req.getServletContext().getServerInfo() + " ."); out.println("Port du serveur : " + req.getServerPort() + " ."); out.println("Port du serveur : " + req.getServerPort() + " ."); out.println("Chemin vers le fichier " + req.getPathInfo() + " : " + req.getPathTranslated(req.getPathInfo()) + " ."); } }
Informations sur le client import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ServeurInfoextendsHttpServlet { public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throws ServletException, IOException{ res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); out.println("Adresse IP du client : " + req.getServerName()); out.println("Nom d'hôte du client : " + req.getRemoteHost()); } }
Informations sur la requête import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class ServeurInfoextendsHttpServlet { // En mode GET (même chose pour POST) public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throwsServletException, IOException{ res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); Enumerationparametres = req.getParameterNames(); out.println("Affichage des informations sur les paramètres de la requête"); while (parametres.hasMoreElements()) { String nomParametre = (String) parametres.nextElement(); out.println("Le paramètre " + nomParametre + " a la valeur : " + getParameter(nomParametre) + " ."); } } }
Informations sur les entêtes de la requête • le logiciel utilisé par le client. • les types MIME des formats de données acceptés. • le type d'authentification utilisé dans le cas d'une connexion sécurisée. • la date de dernière requête du client pour la ressource demandée. • le jeu de caractères utilisé par le navigateur. • la valeur du cookie associé au domaine auquel appartient la servlet demandée. • le langage utilisé par le client.
Informations sur les entêtes de la requête import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class ServeurInfoextendsHttpServlet { public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throwsServletException, IOException{ res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); out.println("Affichage des informations sur les en-têtes de la requête"); Enumerationentetes = req.getHeaderNames(); while (entetes.hasMoreElements()) { String nomEntete = (String) entetes.nextElement(); out.println("à l'entête " + nomEntete + " correspond la valeur" + getHeader(nomEntete) + "."); } } }
Informations sur le serveur import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ServeurInfoextendsHttpServlet { public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throwsServletException, IOException{ res.setContentType("text/plain"); // on produit du texte ASCII PrintWriter out = res.getWriter(); out.println("Nom du serveur : " + req.getServerName() + " ."); out.println("Logiciel utilisé : " + req.getServletContext().getServerInfo() + " ."); out.println("Port du serveur : " + req.getServerPort() + " ."); out.println("Chemin vers le fichier " + req.getPathInfo() + " :" + req.getPathTranslated(req.getPathInfo()) + " ."); } }
Construire la réponse : l'entête • HttpServletResponse response • On précise le type MIME de réponse avec response.setContentType (par exemple, "text/html") • On peut préciser le statut de la réponse avec response.setStatus • response.setStatus(HttpServletRequest.SC_NOT_FOUND) => erreur 404 • res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY) avant de rediriger • http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html pour voir tous les statuts possibles
Construire la réponse : le contenu • Construction de HTML public voiddoGet(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException { // Etape 1. Spécifier le type MIME du contenu de la réponse response.setContentType("text/html"); // Etape 2. Récupère le PrintWriter // pour envoyer des données au client PrintWriterout = response.getWriter(); // Etape 3. Envoyer l’information au client out.println("<html>"); out.println("<head><title>Bonjour</title></head>"); out.println("<body>"); out.println("<h1> Bonjour à tous </h1>"); out.println("Il est : " + new java.util.Date()); out.println("</body></html>"); }
Construire la réponse : le contenu import javax.servlet.*; import javax.servlet.http.*; import weblogic.html.*; import java.io.*; public class BonjourMondeObjetextendsHttpServlet { public voiddoGet(HttpServletRequestreq, HttpServletResponseres) throws ServletException, IOException { res.setContentType("text/html"); ServletPagepage = new ServletPage(); page.getHead().addElement(new TitleElement("Bonjour !")); page.getBody().addElement(new BigElement("Bonjour !")); page.output(res.getOuputStream()); } } • Construction de HTML orientée objet, avec weblogic par exemple (http://www.weblogic.com)
Construire la réponse : le contenu • Renvoyer un fichier demandé en paramètre public class FileServerextendsHttpServlet { // on peut être amené à envoyer des fichiers binaires, donc on utilise // un ServletOutputStream au lieu d'un PrintWriter ServletOutputStream out = res.getOutputStream(); // récupération d'une référence sur le fichier demandé File fichier = new File(req.getPathTranslated(); if (fichier == null) // si le fichier est introuvable on envoie un code d'erreur 404 res.sendError(HttpServletResponse.SC_NOT_FOUND); // sinon le type de contenu de la réponse correspond au type MIME // du fichier res.setContentType(getServletContext().getMimeType(fichier)); try { // on utilise un tampon de 4 ko pour lire le fichier // ce qui est plus rapide qu'un lecture ligne par ligne char[] tampon = new char[4 * 1024]; FileInputStream in = new FileInputStream(fichier); while (in.read(tampon) >= 0) { out.write(tampon); } } catch (IOEXception e) { // si une erreur se produit au milieu de la réponse // on envoie le code d'erreur HTTP adéquat res.sendError(HttpServletResponse.SC_PARTIAL_CONTENT); } finally { if (fichier != null) fichier.close(); } } }