Servlet : introduction Une Servlet est un composant web conçu sous la forme d'une classe Java. Elle fonctionne dans un moteur/conteneur de servlet dans un serveur d'application. L'objectif d'une servlet est de rendre les contenus web dynamiques. Avantage des servlets : - Portable (Java) - Performante : Reste en mémoire tant qu'elle est utilisée - Haute disponibilité : Multitâche Une seule instance et un thread par client qui se partage l'instance Les servlets sont sujet à une normalisation stricte pour que le conteneur puisse les faire fonctionner. Cycle de vie : 1 : Instanciation 2 : Initialisation (Appel de la méthode init) 3 : Fonctionnement normale (Appel de la méthode service) 4 : Arrêt (appel de la méthode destroy) API Servlet : L'API servlet contient des classes et interfaces permettant le développement de servlet. Packages servlet : - javax.servlet - javax.servlet.http Fonctionnement par l'exemple :
Une classe java qui hérite de la classe javax.servlet.http.HttpServlet devient automatiquement une servlet. Méthode disponible à partir de la classe HttpServlet : - protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, java.io.IOException Cette méthode est appelée par défaut par le conteneur quelle que soit la requête HTTP. Deux paramètres sont disponibles : - HttpServletRequest req : Contient tous les paramètres de la requête. - HtppServletResponse res : Contient le lien avec le client permettant de lui envoyer la réponse Un client peut émettre plusieurs types de requêtes : - doPost(HttpServletRequest req, HttpServletResponse res) - doGet(HttpServletRequest req, HttpServletResponse res) - doDelete(HttpServletRequest req, HttpServletResponse res) Permet la suppresion d'un document sur le serveur. - doHead(HttpServletRequest req, HttpServletResponse res) Permet l'affichage des informations d'entêtes de la requête. - doOptions(HttpServletRequest req, HttpServletResponse res) Options détermine le niveau HTTP supporté par le serveur. - doPut(HttpServletRequest req, HttpServletResponse res) Chargement d'un fichier sur le serveur à partir du client - doTrace(HttpServletRequest req, HttpServletResponse res) Permet d'afficher la trace de la requête. Lorsque la méthode service n'est pas implémentée, la méthode correspondant à la requête est invoquée par la méthode service. Il est donc possible d'écrire tout le code dans la méthode service de façon à donner la même réponse quelle que soit la requête. |
Servlet : initialisation et Desctruction Au moment du chargement de la servlet en mémoire, le conteneur invoque la méthode init. public void init() throws ServletException {} Par défaut cette méthode est vide. Elle n'est appelé qu'une seule fois. Par conséquent elle peut être très utile pour : - Initialiser des variables - Ouvrir une connexion à la BDD - ... Pendant l'arrêt du conteneur, la méthode destroy est invoquée. Par défaut cette méthode est vide. Elle peut être utile pour fermer proprement les ressources (Connexion BDD, Fichiers texte, ...) public void destroy(){} |
Servlet : Invocation à partir du client L'appel d'une servlet se fait au travers du protocole HTTP. 99% des requêtes provenant du client correspondent aux méthodes : - doGet - doPost Requête doGet Cette méthode est invoquée quand le client : - Saisit directement l'URL dans la barre d'adresse http://monserveur/servlet/MaServlet - Clique sur un lien hypertext correspondant à l'URL précédente Exemple d'implémentation de la méthode doGet : (p 125) import javax.servlet.*; import javax.servlet.http*; import java.io.*; public class MaServlet extends HttpServlet{ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ PrintWriter out = res.getWriter(); out.println("<html><body>"); out.println("<H1>Test Servlet méthode doGet</H1><br>"); out.println("<a href=\"/servlet/MaServlet\">je me rappelle</a>"); out.println("</body></html>"); out.flush(); out.close(); } } Requête doPost Cette méthode est invoquée quand le client soumet un formulaire (clique sur un bouton de type submit). Exemple d'implémentation de la méthode doPost : (p 130) import javax.servlet.*; import javax.servlet.http*; import java.io.*; public class MaServlet extends HttpServlet{ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ PrintWriter out = res.getWriter(); out.println("<html><body>"); out.println("<H1>Test Servlet méthode doGet</H1><br>"); out.println("<a href=\"/servlet/MaServlet\">je me rappelle</a>"); out.println("</body></html>"); out.flush(); out.close(); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ PrintWriter out = res.getWriter(); out.println("<html><body>"); out.println("<H1>Formulaire posté</H1>"); out.println("</body></html>"); out.flush(); out.close(); } } Récupération des données saisies dans un formulaire : L'objet HttpServletRequest contient une méthode qui permet de connaître les données saisies dans le formulaire. getParameter("<nomParamètre>") Exemple : import javax.servlet.*; import javax.servlet.http*; import java.io.*; public class MaServlet extends HttpServlet{ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ PrintWriter out = res.getWriter(); out.println("<html><body>"); out.println("<H1>Test Servlet méthode doGet</H1><br>"); out.println("<a href=\"/servlet/MaServlet\">je me rappelle</a>"); out.println("</body></html>"); out.flush(); out.close(); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ //Récupération des paramètres String nom = req.getParameter("nom"); String prenom = req.getParameter("prenom"); //Création du retour PrintWriter out = res.getWriter(); out.println("<html><body>"); out.print("<p>Bonjour); out.print(" "); out.print(nom); out.print(" "); out.print(prenom); out.println(</p>"); out.println("</body></html>"); out.flush(); out.close(); } } Page HTML de test : <html> <title>Ma première servlet</title> <body> <form method="post" action="/servlet/MaServlet"> nom : <input type="text" name="nom"><br> prénom : <input type="text" name="prenom"><br> <input type="submit" value="envoyer"> </form> </body> </html> |
Méthode de l'objet HttpServletRequest: - getParameter(String nom) : Récupération d'un paramètre - getParameterNames() Enumeration : Liste de tous les paramètres - getParameterValues(String param) String[] : Retourne un tableau de valeur correspondant à tous les paramètre portant le même nom - getAttribute(String attr) Object : Récupération d'attributs passés d'une à une autre servlet par l'intermédiaire de la requête - getAttributeNames() Enumeration : Liste des attributs - getHeader(String hdr) String : Récupère un paramètre d'entête - getHeaderNames() Enumeration : Liste tous les paramètres d'entête - getSession() : Retourne un identifiant de session. - getSession(boolean id) : Retourne un identifiant de session. S'il n'existe pas et que le paramètre id est vrai, alors la méthode crée un identifiant. - getServerName() : Retourne le nom du serveur - getServerport() : Retourne le port du serveur - getRemoteAddr() : Retourne l'adresse IP du poste client - getRemoteHost() : Retourne le nom complet du poste client - getRemoteUser() : Retourne le nom de l'utilisateur s'il est authentifié - getQueryString() : Retourne la requête Méthode de l'objet HttpServletResponse: - addHeader(String nom, String value) : Ajoute une donnée d'entête à la réponse - addCookie(Cookie c) : Ajoute un cookie à la réponse - Classe Cookie : Nom, valeur, délai d'expiration - getWriter() PrintWriter : Ouvre un flot de sortie vers le client - sendError(int code) : Retourne un code erreur au client - encodeURL(String coding) : Permet d'encoder l'URL. - setContentType(String) : Permet d'envoyer vers le client des formats autres qu'HTML. (PDF, txt, csv, mpg, avi, ...) |
Exemple : L'objectif de l'exemple est de lister toutes les propriétés de l'entête d'une requête HTTP
Résultat : |
Exemple : L'objectif de l'exemple est de lister toutes les informations du client et du serveur
Résultat : |
Les contextes : Il est possible de lancer l'exécution d'une servlet avec des paramètres d'initialisation. La classe javax.servlet.ServletConfig permet d'obtenir les informations de configuration de la servlet. Pour accéder à cette objet, il faut surcharger la méthode init de la classe GenericServlet. Syntaxe : public void init() throws ServletException{} public void init(ServletConfig config) throws ServletException{} Méthode de la classe : - getInitParameter(String param) String : Retourne la valeur du paramètre au format chaîne de caractère - getInitParameterNames() Enumeration : Retourne la liste des paramètres - getServletName() String : retourne le nom de la servlet - getServletContext() ServletContext : Retourne une instance de la classe ServletContext qui contient l'ensemble de la configuration du serveur. Cette classe permet aussi le partage d'information entre Servlet. Exemple : Illustration de l'utilisation du ServletConfig
|
Utilisation du ServletContext : La classe ServletContext permet d'accéder à la totalité de la configuration d'une application Web. Sa seconde utilisation est le partage d'informations entre servlets. Pour Obtenir une instance de la classe ServletContext, il suffit d'appeler la méthode getServletContext(). Cette méthode est implémentée dans la classe GenericServlet dont chaque servlet hérite. Méthode de la classe : - getInitParameter(String param) String : Retourne la valeur d'un paramètre - getInitParameterNames() Enumeration : Retourne la liste des paramètres - getAttribute(String attr) Object : Retourne l'attribut passé en paramètre - getAttributeName() Enumeration : Retourne la liste des attributs - setAttribute(String attr, Object obj) : Insère un attribut - removeAttribute(String attr) : Supprime un attribut - getRequestDispatcher(String obj) RequestDispatcher : Il est possible de renvoyer le résultat du traitement d'une requête vers une autre Servlet ou un JSP. Cette opération se fait par la classe RequestDispatcher. Classe RequestDispatcher : Principe de fonctionnement : 1 La requête du client est dirigée vers une servlet qui effectue un traitement 2 La requête redirige la réponse vers - une autre servlet - un JSP Dans le modèle de programmation MVC (Architecture standard J2EE) la servlet ne doit jamais écrire du code HTML. La présentation doit être prise en charge par les JSPs. Méthode permettant de rediriger la réponse vers une autre servlet ou un JSP : getServletContext().getRequestDispatcher("/servlet/MaServlet").forward(req,res); Exemple : Illustration de l'utilisation du ServletContext Page HTML : <html> <body> <form method="POST" action="/servlet/formation.servlet.ContextDemo1"> <tr> <td width="11%">Nom : </td> <td width="89%"><input type="text" name="nom" size="20"></td> </tr> <tr> <td width="11%">Prénom : </td> <td width="89%"><input type="text" name="prenom" size="20"></td> </tr> <tr> <td width="11%">Ages : </td> <td width="89%"><input type="text" name="age" size="5" maxlength="3"></td> </tr> </table> <p><input type="submit" value="Envoyer" name="B1"> </form> </body> </html>
Appel |
Synchronisation : Les servlets sont multitâches. Une seule instance est exécutée plusieurs fois simultanément. Les variables d'instances doivent donc être sécurisées. Il faut être sur que la valeur de ces variables soit intègre. Syntaxe de synchronisation : synchronized(<variable>){ instruction1; instruction2; } Exemple :
|
Gestion des sessions : Le mode de fonctionnement d'une application web est asynchrone. Seul le client peut être à l'initiative d'un dialogue. Mécanisme : 1 : Requête du client 2 : Ouverture d'une socket entre le serveur web et le client 3 : Envoi de la réponse 4 : Fermeture de la socket. A la seconde requête du client, il faut pouvoir reconnaître le client : - Parce qu'il s'est authentifié - Parce qu'il fait des achats en ligne - .... La session HTTP permet de résoudre ce problème. Par défaut, lors de la première requête, l'on associe à l'utilisateur un identifiant unique. Cet identifiant est stockée sur le poste client sous la forme d'un cookie. La seconde méthode est la réécriture d'URL. Classe représentant une session HTTP : javax.servlet.http.HttpSession Méthode de la classe : - getSession()() HttpSession : retourne la session en cours - getSession(boolean)() HttpSession : retourne la session en cours. S'il n'existe pas de session, la méthode crée une session si le paramètre est vrai - getId() String : retournel'identfiant de la session - getCreationTime() long : retourne la date et heure sous la forme d'un numérique - isNew() boolean : Permet de savoir si la session vient d'être créée - invalidate() : Supprime la session de l'utilisateur - setAttribute(String attr, Object obj) : Permet de stocker un objet dans la session - getAttribute(String attr) Object : Permet de retrouver un attribut.
Résultat premier appel |
Gestion des cookies : Un cookie est un élément contenant une paire clé - valeur ainsi qu'une date d'expiration. Structure d'un cookie : - Clé : Identifiant du cookie - valeur : Contenu du cookie - Propriétés : - Nom de domaine du serveur qui à émis le cookie - Contexte l'application (Partie de l'url) - Durée de vie : Temps en secondes. Stocké en mémoire jusqu'à la fermeture du navigateur. - Sécurité : selon la connexion utilisé (HTTP ou HTTPS) Classe Cookie (javax.servlet.http.Cookie): - Constructeur : Cookie(String cle, String valeur) : Le constructeur impose de fournir une clé et une valeur -Méthode de la classe : - getName() : Récupère le nom du cookie - getValue() : Récupère la valeur du cookie - setValue() : Fixe la valeur du cookie - getDomain() : Récupère le domaine du cookie - setDomain() : Fixe le domaine du cookie - getMaxAge() : Récupère la durée de vie maximale du cookie - setMaxAge() : Fixe la durée de vie maximale du cookie Exemple d'utilisation :
Résultat premier appel |
Réécriture d'URL : La seconde méthode permettant l'identification d'un utilisateur est la réécriture d'URL Cette méthode permet d'éviter l'utilisation de cookie. Méthode de l'objet HttpServletResponse permettant la réécriture : - encodeURL(String url) String : Méthode qui encode l'URL enn incluant l'identifiant de session. Exemple d'utilisation :
Résultat appel |
Gestion des pools de connexion : Pour permettre une montée en charge correcte, il est fortement conseillé d'utiliser les pools de connexion pour accéder à la BDD. Principe général de fonctionnement : - Paramétrage de l'accès à la BDD - Accès aux paramétrage via JNDI - Obtention d'une connection - Renvoi de la connection au pool Exemple d'obtention d'une connexion via une DataSource pour WebSphere 3.5 : java.util.Properties p = new java.util.Properties(); p.put("javax.naming.Context.INITIAL_CONTEXT_FACTORY", "com.ibm.ejs.ns.jndi.CNInitialContextFactory"); p.put("javax.naming.Context.PROVIDER_URL", "iiop:///"); javax.naming.Context ctx = new javax.naming.InitialContext(p); DataSource ds = (DataSource)ctx.lookup("jdbc/BDVIN"); Exemple d'obtention d'une connexion via une DataSource pour TOMCAT : javax.naming.Context ctx = new javax.naming.InitialContext(); DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/BDVIN"); Classe javax.sql.DataSource : - getConnection() : Retourne une connexion ouverte du pool - getConnection(String user, String password) : Retourne une connexion ouverte du pool avec le user et le password passés en paramètre |