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