Servlets

publicité
Contenu
A
• Formulaires HTML
• Interface CGI
• Perl
Applicatif côté serveur (Servlets)
• PhP
• Servlets
TPI
P. Reignier
TPI
P. Reignier
A.1
Motivations
• Java : langage de programmation généraliste
A1 - Servlets
• Permet le développement de grosses applications
• Objectif : offrir un accès Web à ces applications
TPI
P. Reignier
TPI
P. Reignier
A.3
Motivations (2)
Motivations (3)
• Java : support réseau (Sockets . . . )
• Application :
– Prise en charge de tous les services communs
– Evite de les redévelopper pour chaque application web
– Container de servlets
• Support Web :
– Interpréteur HTTP
– Codage + décodage MIME
– Support des cookies, des sessions
– ...
• Interfaçage :
– Plusieurs fournisseurs de container de servlet
– Comment peux-t-on fournir ses classes pour étendre le container
– Normalisation de l’interface
⇒ Les Servlets
• Deux approches potentiellement possibles :
1. Ajout de bibliothèques (jar) à votre application
2. Ajout de vos classes à une application (serveur Web)
TPI
P. Reignier
TPI
P. Reignier
A.4
A.5
Plan
Servlet
<< interface >>
Servlet
+ init ():void
+ destroy ():void
+ service (req :ServletRequest ,resp :SevletResponse ):void
• Servlets + Container de servlets
• JSP
Classe abstraite
GenericServlet
• Architecture MVC
+ service (req :ServletRequest ,resp :ServletResponse ):void
• JSP tags (Philippe Genoud)
HttpServlet
+ doGet (req :HttpServletRequest ,resp :HttpServletResponse ):void
+ doPost (req :HttpServletRequest ,resp :HttpServletResponse ):void
+ doHead (req :HttpServletRequest ,resp :HttpServletResponse ):void
TPI
P. Reignier
A.6
TPI
Created with Poseidon for UML Community Edition. Not for Commercial Use.
A.7
P. Reignier
doGet, doPost : paramètres
Cycle de vie
• Géré par le container.
• Initialisation :
– Chargement de la classe (au démarrage ou sur requête).
– Instantiation d’un objet.
– Appel de la méthode init() (par exemple : ouverture de lien JDBC)
• Utilisation :
– Appel de la méthode service()
– Dans le cas d’une HttpServlet : appel vers doGet(), doPost().
• Destruction :
– Peut être provoquée pour optimiser la mémoire
– Appel de la méthode destroy()
TPI
P. Reignier
• HttpServletRequest :
– Contexte de l’appel
– Paramètres de formulaires
– Cookies
– Headers
– ...
• HttpServletResponse
– Contrôle de la réponse
– Type de données
– Données
– Cookies
– Status
– ...
TPI
P. Reignier
A.8
A.9
Première Servlet
SerlvetRequest / ServletResponse
<< interface >>
ServletRequest
import java.io.∗;
import javax.servlet.∗;
import javax.servlet.http.∗;
public class PremiereServlet extends HttpServlet
{
public void doGet(HttpServletRequest requete,HttpServletResponse reponse)
throws IOException, ServletException
{
reponse.setContentType("text/html");
PrintWriter pw = reponse.getWriter();
<< interface >>
ServletResponse
+ getParameterName (name :String ):String
+ getParameterNames ():
+ getReader ():
+ getInputStream ():
+ getContentLength ():int
+ getContentType ():String
pw.print("<html>");
pw.print("<body bgcolor=\"white\">");
pw.print("<head>");
pw.print("<title>Ma première servlet</title>");
pw.print("</head>");
pw.print("<body>");
pw.print("<h1>Ca marche !</h1>");
pw.print("</body>");
pw.println("</html>");
}
+ setContentType (type :String ):void
+ getOutputStrem ():ServletOutputStream
+ getWriter ():PrintWriter
<< interface >>
HttpServletRequest
<< interface >>
HttpServletResponse
+ getCookies ():
+ getRequestURI ():String
+ addCookie (cookie :Cookie ):void
+ sendError (err :int ,mesg :String ):void
+ sendRedirect (location :String ):void
Created with Poseidon for UML Community Edition. Not for Commercial Use.
}
TPI
P. Reignier
A.10
TPI
P. Reignier
A.11
Cookie
Exemple
Cookie
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException {
+ getName ():String
+ getValue ():String
+ getDomain ():String
+ getPath ():String
+ setValue (name :String ):void
+ setMaxAge (age:int ):void
+ setPath (path :String ):void
<< create >> + Cookie (domain :String ,name :String ,value :String ):void
res.setContentType("text/html");
PrintWriter pw = reponse.getWriter();
Enumeration e = req.getParameterNames();
pw.setContentType("text/html") ;
...
while (e.hasMoreElements())
{ // récupération des paramètres
String attribute = (String)e.nextElement();
pw.print("Attribut : " + attribute) ;
pw.print("Valeur : " + req.getParameter(attribute)) ;
}
...
}
• Une fois créé, le nom d’un cookie ne peut être changé
TPI
P. Reignier
TPI
A.12
P. Reignier
A.13
Exemple (suite)
Execution
cookie = req.getCookies() ;
if (cookie != null)
{
for (int i=0; i<cookie.length; i++)
{
pw.print("<TR><TD>\n") ;
pw.print(cookie[i].getName()) ;
pw.print("</TD><TD>\n") ;
pw.print(cookie[i].getValue()+"</TD>\n") ;
pw.print("</TR>\n") ;
}
}
TPI
• Serveur web multi-threadé
– Un thread par requête
• Attention à la gestion des ressources partagées
• Lien Instance ⇔ Thread. Par défaut :
– Une seule instance
– Les attributs de la classe deviennent des ressources partagées
P. Reignier
A.14
TPI
P. Reignier
A.15
Exemple
Exemple (suite)
public class Factorielle extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
protected int nombre ;
protected int factorielle(int x) {
int res=1 ;
try {
this.nombre = x ;
res = 1 ;
for (int i =1; i<=nombre; i++) {
Thread.sleep(1000) ;
res ∗ = i ;
}
} catch (InterruptedException e) {
e.printStackTrace() ;
}
return res ;
}
out.println("<html>");
out.println("<head>");
out.println("<title>Factorielle</title>");
out.println("</head>");
out.println("<body>");
int x = Integer.parseInt(request.getParameter("x")) ;
int fact = factorielle(x) ;
out.println(request.getParameter("x")+"!
out.println("</body>");
out.println("</html>");
protected void goGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
= " + fact) ;
out.close();
}
}
TPI
P. Reignier
TPI
P. Reignier
A.16
A.17
Solutions
Sessions
• Permet de simuler une connexion continue entre un navigateur et le serveur.
• Sections critiques :
• Sauvegarde d’objets (associés à un client) :
– entre différentes pages
– entre des appels successifs à une même page
– Utilisation du mot clé synchronized
• Identifiant unique transmis sous forme de cookie
• Modèle d’exécution : 1 instance par thread
• Utilisation de l’interface :
– Implémenter l’interface SingleThreadModel
javax.servlet.http.HttpSession
TPI
P. Reignier
A.18
TPI
P. Reignier
A.19
Utilisation
Utilisation(2)
• Sauvegarde d’objets :
– Association clé ⇔ instance
• Session : associé à HttpServletRequest
• Accès à la session :
– HttpSession session = request.getSession(true) ;
– Récupération de la session associée au navigateur
– Création de la session si elle n’existe pas
Obj o ;
session.setAttribute("cle", o)
• Extraction d’objets :
Obj o ;
o = (Obj) session.getAttribute("cle") ;
• session.isNew() :
– Permet de tester si la session vient d’être créée.
⇒ initialisation.
• Fin de session :
session.invalidate() ;
TPI
P. Reignier
TPI
A.20
P. Reignier
A.21
Exemple : un compteur
public class CompteurServlet extends HttpServlet
{
public void doGet( HttpServletRequest requete,HttpServletResponse reponse)
throws IOException, ServletException
{
reponse.setContentType("text/html");
ServletOutputStream os = reponse.getOutputStream();
HttpSession session = requete.getSession(true) ;
Compteur cpt = session.getAttribute("compteur") ;
if (cpt == null)
{
cpt = new Compteur() ;
session.setAttribute("compteur", cpt) ;
}
A2 - Container de Servlets
os.print("<HTML>\n") ;
. . ..
cpt.incrCpt() ;
if (cpt.getCpt() == 5)
session.invalidate() ;
}
}
TPI
P. Reignier
A.22
TPI
P. Reignier
Définition
Jakarta-Tomcat
• Container de Servlet :
– Application Java
– Normalisation Sun (J2EE)
– Prise en charge du protocole Http
– Permet d’utiliser vos propres objets pour le traitement des requêtes
– Plusieurs “applications web” par container
• Deux aspects :
– Où doit on mettre ses fichiers .class pour que le container les trouve :
∗ le déploiement
– A quelle URL sera associée les classes, quels sont les paramètres de
lancement, quelle sécurité . . .
∗ le descripteur de déploiement
TPI
P. Reignier
• Tomcat : un des plus célèbre container de servlet
• Conçu par Apache
• Reconnu implémentation de référence par Sun de la norme Servlet
• http://jarkata.apache.org/tomcat/index.html
• Actuellement en version 5 :
– 5.0 : fonctionne sous jdk1.4
– 5.5 : ne fonctionne que sous jdk1.5
TPI
A.24
P. Reignier
A.25
Déploiement d’une application Web
Arborescence de Tomcat
• bin
• Normalisation de l’arborescence des fichier binaires
• common : packages java communs à l’ensemble des applications
– classes
– endorsed
– lib
MyApplication/
classes/
WEB−INF/
lib/
• conf
index.html
• common : packages java communs à l’ensemble des application
– classes
– lib
web.xml
javadoc/
• webapps : ensemble des applications web
TPI
P. Reignier
A.26
TPI
P. Reignier
A.27
Déploiment (suite)
Arborescence Binaire (2)
• Sommet : fichiers HTML et JSP (voir plus loin)
– Des sous répertoires peuvent être créés pour structurer le stockage
de ces fichiers.
• javadoc : documentation développeur des servlets.
• WEB-INF :
– classes : servlet compilées.
– lib : jar nécessaires à l’application (cf JDBC)
– Remarque : ces deux répertoires sont directement accessibles à la
machine virtuelle exécutant le container de servlet.
– web.xml : description du déploiement.
TPI
P. Reignier
• 3 solutions (on ne s’intéressera qu’à la troisième) :
1. Copie de l’arborescence binaire dans le répertoire webapps
– Redémarrer Tomcat pour prendre en compte la nouvelle application
2. Création d’une archive war déposée dans le répertoire webapps
– Redémarrer Tomcat pour prendre en compte la nouvelle application
– Décompression automatique du fichier war par Tomcat
3. Utilisation de l’interface admin de Tomcat
– Permet d’indiquer le répertoire où se trouve l’application
– Pas besoin de redémarrer Tomcat
TPI
A.28
P. Reignier
A.29
Descripteur de déploiement
Quelques éléments de web.xml
• Application web = mise à disposition de servlets
• Accès aux servlets :
– Par URL
– http://localhost/Application/NomSymboliqueVersServlet
– Application = contexte. En général, le nom du répertoire
– NomSymboliqueVersServlet : fichier de configuration
• Fichier de configuration de l’application
– Association URL ⇔ Servlets
– Paramétrage
– ...
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<context-param>
<param-name>webmaster</param-name>
<param-value>[email protected]</param-value>
<description>
The EMAIL address of the administrator to whom questions
and comments about this application should be addressed.
</description>
</context-param>
• Fichier web.xml du répertoire WEB-INF
TPI
P. Reignier
A.30
TPI
P. Reignier
A.31
Quelques éléments de web.xml (2)
Quelques éléments de web.xml (3)
<servlet>
<servlet-name>formulaire</servlet-name>
<description>
Repond au formulaire
</description>
<servlet-class>Formulaire</servlet-class>
<!-- Load this servlet at server startup time -->
<load-on-startup>1</load-on-startup>
</servlet>
<context-param>
<param-name>webmaster</param-name>
<param-value>[email protected]</param-value>
</context-param>
• Paramètres accessibles par la servlet.
• Optionnel.
• Evite de recompiler.
<servlet-mapping>
<servlet-name>formulaire</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
• Accès :
String value = getServletContext().getInitParameter("webmaster");
</web-app>
// exemple d’utilisation
pw.print("Contact : <a HREF=\"mailto:"+value+"\">"+value+"</a>") ;
TPI
P. Reignier
TPI
P. Reignier
A.32
A.33
Quelques éléments de web.xml (4)
Quelques éléments de web.xml (4)
<servlet>
<servlet-name>formulaire</servlet-name>
<servlet-class>Formulaire</servlet-class>
<!-- Load this servlet at server startup time -->
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>formulaire</servlet-name>
<url-pattern>/action.form</url-pattern>
</servlet-mapping>
• associe une URL à un nom symbolique de servlet
• Accessible par :
• Déclaration des servlets disponibles.
http://localhost:8080/MyApplication/action.form
• Paramètres optionnels :
– Relecture par : getServletConfig().getInitParameter("param1") ;
• Attention : le fichier action.form n’existe pas
• Permet de les pré-charger.
TPI
P. Reignier
A.34
TPI
P. Reignier
A.35
Quelques éléments de web.xml (5)
Arborescence source
<servlet-mapping>
<servlet-name>formulaire</servlet-name>
<url-pattern>/*.form</url-pattern>
</servlet-mapping>
• associe une URL à un nom symbolique de servlet
• Accessible par :
http://localhost:8080/MyApplication/action.form
http://localhost:8080/MyApplication/autre.form
• Permet de gérer plusieurs URL par une même servlet
• Aiguillage dans la servlet par req.getRequestURI().
TPI
P. Reignier
A.36
• Cycle de développement :
1. Ecriture du code source
2. Compilation vers le répertoire build
3. Déploiement sous tomcat (soit par recopie vers webapps, soit en utilisant directement le répertoire build)
4. Test
5. Retour si nécessaire au point 1
6. Une fois terminé, création de l’archive war sous dist.
P. Reignier
A.38
P. Reignier
A.37
Développement
TPI
TPI
Téléchargement