Programmation Servlet/JSP (présentation du
Transcription
Programmation Servlet/JSP (présentation du
Architectures Java/Web : Servlets & JSP Alain Paoli Novembre 2001 1 Plan • Architectures CGI, PHP, Servlets, JSP • Principes de programmation CGI vs. Servlet et PHP vs. JSP • Servlets – – – – – Exemple Cycle de vie Traitement des formulaires Sessions Connexions au bases de données • JSP – – – – Syntaxe Tags JSP pré-définis: traitement des formulaires HTML Exemple simple Architecture MVC: Exemple 2 1 Architecture CGI Page HTML logon: xx@... pass: **** Requête HTTP OK Serveur Web Vous êtes enregistré ! Module CGI Programme CGI Page Réponse Client Serveur • Module CGI (Common Gateway Interface): appelle le programme CGI correspondant à la requête. • Pour chaque requête, un processus système est créé sur le serveur. 3 Architecture PHP Page PHP <?php ….. Interprète la page PHP et génère la page de réponse logon: xx@... pass: **** Requête HTTP OK ….. ?> Vous êtes enregistré ! Serveur Web Module PHP MySQL Page Réponse Client Serveur • Pour chaque requête: – Suivant la plate-forme (Apache/mySQl/Unix, ou autre), on utilise un processus existant, ou on en crée un pour interpréter la page PHP et 4 générer la page de réponse. 2 Architecture Servlet Page HTML logon: xx@... pass: **** Requête HTTP Servlet Engine OK Serveur Web Vous êtes enregistré ! Instance du Servlet Thread Page Réponse Client Serveur • ServletEngine: dirige la requête vers le servlet correspondant. • Servlet = instance d ’une classe héritant de javax.servlet.http.HttpServlet – Une seule instance est crée par le moteur de servlet. • Pour chaque requête – Lancement d’un nouveau thread sur la méthode doGet ou doPost de l’instance 5 unique du servlet pour générer la page de réponse. Architecture JSP Page JSP <% ….. logon: xx@... pass: **** Requête HTTP JSP Engine Servlet Engine OK ….. %> Vous êtes enregistré ! Client Serveur Web Instance du Servlet Thread Page Réponse Serveur • JSP Engine: – Si la page JSP n’a pas encore été compilée sous la forme d’un servlet: • Génère le source d’un servlet, puis compile ce source. – Passe la requête au Servlet Engine, qui crée l’instance de ce servlet. 6 3 Programmation CGI vs. Servlet • Un même principe: – Un programme génère le code HTML de la page de réponse. • Logique de l’application et présentation ne sont pas séparées. • Différences: – CGI: Programmation classique. • Les paramètres de la requête HTTP sont passés au programme appelé. – Servlet: C’est une instance d’une classe qui hérite de la classe javax.servlet.httpHttpServlet et qui redéfini la (ou les) méthode(s) doPost ou doGet. • Appel de la méthode doPost ou doGet du servlet suivant le type de la requête HTTP (GET ou POST) • Les paramètres de la requête HTTP sont encapsulés dans un objet (javax.servlet.http.HttpServletRequest) passé en paramètre des méthodes doPost ou doGet. 7 • Code réentrant: le servlet ne doit pas mémoriser d’état. Programmation PHP / JSP • Un même principe: – On insère du code PHP (vs. JSP) dans du code HTML • Séparation (partielle ou complète) entre logique de l’application et présentation. • Différences entre PHP et JSP: – Syntaxiques: en JSP on distingue entre: • du code Java qui retourne une valeur: expression entre ‘ <%=‘ et ‘ %> • du code Java qui exécute une action: scriptlet entre ‘ <%‘ et ‘ %> – Sémantiques: sessions, connexions aux bases de données, ... – En JSP on peut : • Utiliser les tags pré-définis JSP • Définir ses propres tags JSP: permet d’étendre le langage JSP. 8 4 Programmation des Servlets 9 Servlet - Idiome import java.io.*; import javax.servlet.*; import javax.servlet.http.*; Déclaration des noms de packages dont on va utiliser les classes. Permet de citer les classes avec leur nom ‘court’. public class MonServlet extends HttpServlet { ‘MonServlet’ hérite de HttpServlet Surcharge la méthode doGet public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Objet encapsulant la requête HTTP Objet encapsulant la réponse // (1) Utiliser l’objet "request" pour lire les headers HTTP (ex. cookies) // et les paramètres transmis par un formulaire HTML // (2) Spécifie les headers HTTP (e.x. MIME type, passer des cookies) à l’aide de l’objet // "response" pour écrire la page réponse, et récupère le flot de sortie via cet objet "response" PrintWriter out = response.getWriter(); // Utiliser l’objet "out" pour écrire la page réponse envoyée au navigateur } } 10 5 Servlet Exemple import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWWW extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); // Positionne le type MIME dans le header de la réponse PrintWriter out = response.getWriter(); out.println("<HTML>"); out.println("<HEAD><TITLE>Hello WWW</TITLE></HEAD>"); out.println("<BODY>"); out.println("<H1>Hello WWW</H1>"); // Pas de séparation logique de l’application / présentation out.println("</BODY></HTML>"); } } 11 Servlet - Cycle de Vie • Initialisation – appel de la méthode init() définie au niveau de la classe HttpServlet. Ne fait rien. Peut être surchargée. • Traitement requêtes HTTP – appel de la méthode service() définie au niveau de la classe HttpServlet. Cette méthode dispatche vers doGet() ou doPost() suivant le type de requête HTTP reçue. • Les méthodes doGet et doPost définies au niveau de la classe HttpServlet ne font rien. • Destruction – appel de la méthode destroy() définie au niveau de la classe HttpServlet. Ne fait rien. Peut être surchargée. 12 6 Paramètres de la requête HTTP • PHP: Vu comme des variables globales de la page PHP. • Servlet: – Encapsulés dans une instance de la classe HttpServletRequest passée en paramètre de doGet ou doPost. Supporte les méthodes: • • • • getCookies(): retourne un tableau d’objets Cookie. getHeader(String headerName): retourne la valeur (String) d’un en-tête HTTP. getSession(): retourne la session sous la forme d’un objet HttpSession getParameter(String parameterName): retourne la valeur (String) d’un paramètre mono-valué. • getParameterValues(String parameterName): retourne la valeur (tableau de String) d’un paramètre multi-valué. • getParameterNames(): retourne une énumération (instance de la classe Enumeration) des noms de paramètres. 13 • etc Traitement des formulaires logon: xx@... Requête HTTP pass: **** OK Servlet Engine …/MonServlet?logon=xx@yy&pass=123&ok=OK nom servlet paramètres <html> <form method=‘POST’ action=‘MonServlet’> <input name=‘logon’ type=‘text’> <input name=‘pass’ type=‘password’> <input name=‘ok’ type=‘submit’ value=‘OK’> </form> </html> Instance de HttpServletRequest logon=xx@yy pass=123 ok=‘OK’ Instance de HttpServletResponse Formulaire HTML doPost(HttpServletRequest request, HttpServletResponse response) Vous êtes enregistré ! Page Réponse Instance de MonServlet 14 7 Traitement des formulaires package exemple; import javax.servlet.http.*; import java.io.*; public class ConnectionServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // (1) Utiliser l’objet "request" pour lire les paramètres String logon = request.getParameter( "logon"); String pass = request.getParameter( "pass"); // (2) Accéder au PrintWriter pour écrire la réponse response.setContentType("text/html"); PrintWriter out = response.getWriter(); // (3) Vérifier que l’utilisateur est enregistré // … // (4) Il est enregistré: afficher message de bienvenue out.println("<HTML>Vous êtes Enregistré !</HTML>"); // (5) Il n’est pas enregistré: afficher message d’erreur out.println("<HTML>Erreur: Vous n ’êtes pas Enregistré !</HTML>"); } 15 } Sessions en PHP • But: Stocker, pour un utilisateur donné, des variables persistantes d’une requête HTTP à l’autre. – Valeurs stockées dans un fichier sur le serveur. • Ne permet pas de stocker certains types de variables comme des connexions à une base de données. – Le programmeur doit déclarer que la page PHP participe à la session (fonction PHP session_start()). – Implémentées à l’aide d’un cookie, ou d’un identifiant passé en paramètre de la requête HTTP. • Si l’identifiant est utilisé, il est manuellement propagé comme paramètre des requête HTTP par le programmeur (variable PHP ‘SID’) – <A HREF="nextpage.php?<?=SID"?>cliquez ici</?> – La session est terminée explicitement par le programmeur, suite à une action de l’utilisateur, ou a l’initiative du serveur si sa durée dépasse une valeur fixée dans le fichier de configuration de PHP. 16 8 Sessions avec Servlets • But: Maintenir un environnement (i.e. ensemble d’objets) pour un utilisateur donné. • La session est implémentée par un objet HttpSession qui est accessible via une méthode de l’objet HttpServletRequest: – HttpSession session = request.getSession(); • Le programmeur ou le JSP Engine stocke / retrouve des objets dans un dictionnaire (i.e. chaque objet est associé à un nom unique) géré par l’objet HttpSession. • Une session (i.e. un objet HttpSession) est automatiquement créé pour chaque utilisateur qui se connecte au site. Processus complètement automatisée, le programmeur n’a rien à faire. • La session est implémentée à l’aide de cookies temporaires ou (si le navigateur refuse les cookies) par un identifiant passé en paramètre de toutes les requêtes HTTP. • Se termine à l ’initiative du programmeur, ou au bout d’un certain temps d’inactivité (i.e. pas de requête HTTP à traiter pour cette session). Ce 17 temps d’inactivité est paramétré au lancement du JSP Engine. Connexions aux BDR • PHP: – Principe: 1 page PHP ⇒ 1 connexion à une base de données – Avec mySQL / UNIX: possibilité d’utiliser des connexions persistantes. • Servlet: – On utilise un pool de connexions (implémenté par le serveur d’application) • L’objet qui gère le pool demande n connexions à la base de données. • Lorsqu’un servlet a besoin de faire une requête SQL, il: – (1) demande une connexion libre au pool (sinon il attend). – (2) effectue sa requête et lit les résultats avec cette connexion. – (3) rend cette connexion au pool (i.e. elle redevient ‘libre’). 18 9 Programmation JSP 19 Syntaxe • Expression: <%= expression Java %> – Expressions Java retournant une valeur convertible en une String insérée dans la page réponse. • Eléments de scripts (Scriptlet): <% instructions Java %> • code Java inclut dans le servlet. • Déclarations: <%! déclarations Java %> • déclaration de variables ou de méthodes • Directives <%@ ... %> • contrôle la structure globale du servlet • Tags: <jsp:useBean ...> • Tags jsp pré-définis: contrôle le comportement du moteur JSP • Tags jsp définis par le programmeur: contient logique applicative et autorise un contrôle fin de la génération de la page réponse. 20 10 Variables pré-définies JSP • Des variables pré-définies peuvent être utilisées dans les expressions et les scriptlets: – – – – – request (de type HttpServletRequest) response (de type HttpServletResponse) out (de type PrintWriter): utilisé pour écrire la page réponse session (de type HttpSession): la session de l’utilisateur ….. • Exemple: – <p>Le nom de votre machine est: <%= request.getRemoteHost() %>.</p> 21 Expression JSP • Sert à inclure une valeur dans le flot de sortie (page réponse) • Syntaxe: – <%= expresssion Java %> • Exemple: – <p>Aujourd’hui: <%= new java.util.Date() %> </p> • L’expression Java est évaluée, convertie en une string, et insérée dans la page. Cette évaluation est faite lors du traitement de la requête HTTP. • Attention: Une expression ne comporte pas de ‘;’ final 22 11 Scriptlet JSP • Permet d’insérer n’importe quel code Java – Syntaxe: <% code Java %> • Exemple: Les variables déclarées dans un scriptlet sont locales. <% String queryData = request.getQueryString(); out.println("Attached GET data: " + queryData); %> Attention: les instructions se terminent normalement par un ‘;’. • Le code d’un scriptlet est inséré tel quel dans le corps de la méthode service() du servlet généré, et n’importe quel code HTML statique avant ou après un scriptlet est converti en instructions d’écriture de la page réponse. 23 Scriptlet JSP • Exemple: <% if (Math.random() < 0.5) { %> Vous avez <B>gagné</B>! <% } else { %> Vous avez <B>perdu</B>! <% } %> • Dans le servlet, sera compilé en quelque chose comme: if (Math.random() < 0.5) { out.println(”Vous avez <B>gagné</B>!"); } else { out.println(" Vous avez <B>perdu</B>!"); } 24 12 Déclaration JSP • Permet de définir des méthodes ou des attributs au niveau du servlet généré par compilation de la page JSP. – La valeur d’un attribut sera partagée par tous les threads appliqués à la méthode service(), et accessible de n’importe quel scriptlet de la page JSP – La méthode sera accessible de n’importe quel scriptlet de la page JSP. • Syntaxe: – <%! Code Java %> • Exemples: <%! private int accessCount = 0; %> <!-- déclaration d’attribut --> <p>Nombre d’accès à cette page : <%= ++accessCount %></p> <!-- utilisation --> <%! public String hello() { return "hello”; } %> <!-- déclaration de méthode --> 25 Directive JSP • Une directive affecte la structure du servlet. • Syntaxe: – <%@ directive attribut="valeur" %> • Les deux principales directives sont page et include: – page: import de classes Java, passage de paramètres au servlet généré. – include: insertion (statique) d’un fichier lors de la compilation de la page JSP en servlet. – taglib: déclaration de la librairie contenant un tag défini par le programmeur. 26 13 Tags JSP pré-définis • Possèdent une syntaxe XML. Modifient dynamiquement le comportement du moteur JSP. • jsp:useBean - Retrouve ou instancie un Bean. • jsp:setProperty - Positionne les propriétés d’un Bean. • jsp:getProperty - Récupère la valeur d’une propriété d’un Bean et l’insère dans la sortie. • jsp:include - Inclut (dynamiquement) un fichier lors de l’exécution de la requête. • jsp:forward - Dirige la requête vers une autre page. • jsp:plugin - Génère du code spécifique pour le navigateur permettant d’insérer un applet (tag OBJECT) ou le plug-in de la JVM (tag EMBED). 27 Tag <jsp:useBean> • Syntaxe: – <jsp:useBean id="user" class="appli.User" scope="session"/> • Cette action associe un Bean, instance de la classe spécifiée par ‘class’, avec une portée spécifiée par ‘scope’, avec la référence spécifiée par ‘id’. • Si une instance associée avec la même référence n’est pas trouvée dans la portée, une nouvelle instance est crée. Elle est stockée dans la session si cette portée est session. • Portée: quatre valeurs possibles – application: bean visible de toutes les pages, pour toutes les sessions – session: bean visible de toutes les pages pour une session considérée – request: bean visible de toutes les pages participant à une requête, pour une session considérée – page: bean visible dans la page considérée, pour une session considérée 28 14 Tag <jsp:setProperty> • Syntaxe: deux variantes d ’utilisation – (A) <jsp:setProperty name="user" property="*" /> – (B) <jsp:setProperty name="user" property="logon" param="nomUser" /> • Les deux variantes modifient une ou des valeurs de propriétés du Bean dont la référence est spécifiée par ‘name’, en utilisant l’introspection: – Variante (A): Modifie toutes les propriétés du Bean avec les valeurs passées en paramètres dans la requête, de telle façon qu’un paramètre de nom ‘prop’ modifiera la valeur d’une propriété de nom ‘prop’ (i.e. ce Bean est muni d’un ‘setter’ setProp()), en réalisant des conversions implicites (String ⇒ type ‘prop’). – Variante (B): Modifie une propriété du Bean avec la ou les valeurs passées dans la requête pour un paramètre de telle façon que le paramètre de nom ‘param’ modifiera la valeur de la propriété de nom ‘prop’ (i.e. ce Bean est muni d’un ‘setter’ setProp()), en réalisant des conversions implicites (String ⇒ type ‘prop’). 29 Formulaires: PHP vs. JSP • PHP: Les composants de formulaires (ex: <input type=‘text’ …>) sont vues comme des variables PHP globales <html> <form method=‘POST’ action=‘MaPage.php’> <input name=‘logon’ type=‘text’> <input name=‘pass’ type=‘password’> <input name=‘ok’ type=‘submit’ value=‘OK’> </form> </html> <?php if ($logon != "" and $pass != "") { // les variables $logon et $pass n’ont // pas besoin d’être déclarées. …………. } ?> • JSP: <jsp:useBean id="user" class=User scope="session"/> <jsp:setProperty name="user" property = "*"/> <html> <form method=‘POST’ action=‘MaPage.jsp’> <input name=‘logon’ type=‘text’ value=‘<% user.getLogon()‘ %>> <input name=‘pass’ type=‘password’ value=‘<% user.getPass()‘ %>> > <input name=‘ok’ type=‘submit’ value=‘OK’> </form> </html> Bean user logon: xxxx pass: zzzz 30 15 Traitement des formulaires <jsp:useBean id="user" class="User" scope="session"/> email: xx@... pass: **** Requête HTTP …/MonServlet?email=xx@yy&pass=123&ok=OK OK Servlet Engine paramètres Le servlet Engine: (1) Si pas d’objet référencé par ‘user’ dans la session, en fabrique un et le référence. (2) Par introspection, positionne dans les propriétés du Bean les valeurs correspondantes passées en paramètres dans la requête HTTP. Bean User email=xx@yy pass=123 Page d’accueil du site Instance de HttpSession Instance de HttpServletRequest email=xx@yy pass=123 ok=‘OK’ Instance de HttpServletResponse doPost(HttpServletRequest request, HttpServletResponse response) Instance du Servlet Page Réponse 31 Bean User package appli; public class User { private String logon = "" ; // chaîne vide private String pass = ""; // chaîne vide Par introspection, on déduit que ce Bean contient les propriétés: - ‘logon’ de type String, accessible en lecture et écriture. - ‘pass’ de type String, accessible en lecture et écriture. - ‘registred’ de type boolean accessible en lecture. public User() { } // constructeur sans paramètre public String getLogon() { return logon; } public void setLogon(String logon) { this.logon = logon; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } public boolean isRegistred() { // si (logon != null) et (pass != null) et (logon != "") et (pass != "") // et si logon et pass correspondent à un utilisateur enregistré // alors retouner ‘true’ sinon retourner ‘false’ } } 32 16 Traitement des formulaires (1) Crée une référence "user" vers un Bean User stocké dans la session (le Bean est créé si besoin) <jsp:useBean id="user" class=appli.User scope="session"/> <jsp:setProperty name="user" property = "*"/> (2) Déclenche les méthodes setXXX du Bean "user" pour chaque paramètre de la requête dont le nom est ‘ xXX’ <% if (user.isRegistred()) { // rediriger la requête HTTP vers la page d’accueil du site response.sendRedirect("accueil.jsp"); } else { <p>Vous n’êtes pas enregistré !</p> (3) Récupère la valeur d’une propriété du Bean <% } %> "user" <html> <form method="POST" action="login.jsp"> <input name= "logon" type="text" value="<%= user.getLogon() %>" > <input name="pass" type="password" value="<%= user.getPass() %>" > <input name="ok" type="submit" value="OK"> </form> 33 </html> Architecture MCV: Exemple • Saisie d’un formulaire simple d’inscription: – La première fois, le formulaire est affiché vierge. • L’utilisateur saisi ses informations, puis clique sur OK. – S’il y a des erreurs de saisie: • On réaffiche le formulaire avec les valeurs saisies + un message pointant les erreurs commises. – S’il n’y a pas d’erreurs de saisie: • On réaffiche le formulaire avec les valeurs saisies + un message confirmant l’inscription. 34 17 Exemple MVC: diagramme d’états Etat: initialisation Action: init Affichage du formulaire vierge Action: ctrl Etat: erreurs_saisies Action: ctrl Etat: saisie_OK Affichage du formulaire saisi + message d’erreur Affichage du formulaire saisi + message OK fin 35 Architecture MVC - Si action=init: ne fait rien. - Si action=ctrl: contrôle valeurs saisies. si erreur: positionne message erreur dans le Bean sinon: positionne message OK dans le Bean - Toujours: rediriger la requête vers une page JSP …/ControlServlet?action=ctrl Vue (Page JSP) Contrôleur (Servlet) …/ControlServlet?action=ctrl Appel des méthodes: ctrl() et setMsg(msg) sur le bean Modèle (Bean) 36 18 Bibliographie • Java: Série d'articles sur les bases du langage Java: – http://www.javaworld.com/javaworld/jw-10-2001/jw-1005-java101.html • Cours Servlet: – http://www.commentcamarche.com/servlets/servintro.php3 (français) – http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/ (Servlet + JSP) – Déploiement des Servlets dans Tomcat et BEA Systems: • http://www.javaworld.com/javaworld/jw-02-2001/jw-0223servletweblogic.html – http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Servlets.html • Cours JSP: – http://www.commentcamarche.com/jsp/jspintro.php3 (français) http://java.sun.com/products/jsp/docs.html (débutant JSP) – http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPIntro.html 37 Bibliographie (suite) • Java Channel (Références articles sur Java - Niveau avancé): – http://pharos.inria.fr/Java/ • Home Page JSP de Sun: – http://java.sun.com/products/jsp/ • Home page Jakarta / Apache: http://jakarta.apache.org/ • Ressources: – – – – http://www.servlets.com/ http://java.sun.com/products/jsp/taglibraries.html http://www.esperanto.org.nz/jsp/jspfaq.jsp (JSP FAQ) http://coldjava.hypermart.net/ • Implémentations du moteur de JSP Tomcat (et sous-projets): – http://jakarta.apache.org/site/binindex.html 38 19