Blue Flower

Chercher

La structure du répertoire d'une application web

Dans toute application web en Java avec la technologie Servlet/JSP on a les composants suivants:

  • Du contenu statique éventuellement des pages HTML,
  • Des fichiers CSS et des fichiers JavaScript pour la présention,
  • Des fichiers JSP (Java Server Pages) pour générer du contenu dynamique,
  • Des Servlets,
  • Des librairies externes ou des fichiers jar,
  • Divers fichiers utilitaires,
  • Le fichier web.xml appelé fichier descripteur (deployment descriptor - en anglais)

Tout Server Web ou container s'attend à ce que les applications web en Java (Servlet/JSP) soient disponibles dans des répertoires spécifiques tels que:
Web Application Root Directory : C'est le répertoire principal appelé aussi la racine de l'application web. Normalement le nom de ce répertoire devient le "context" de l'application web. Par exemple, si le nom de l'application web est "projetServlet", alors le nom du répertoire racine de l'application web est

"projetServlet" et l'application est accessible via l'url http://localhost:8080/projetServlet.structure Web. App

WEB-INF: C'est un répertoire spécial juste en-dessous du répertoire racine de l'application Web. Ce répertoire est spécial car les fichiers qui sont dedans ne sont pas accessibles directement par les clients de l'application Web. Si par exemple on a un fichier appelé "login.html" dans ce répertoire, on ne peut pas l'atteindre directement par l'url http://localhost:8080/projetServlet/login.html.

WEB-INF/lib: On place tous fichiers "jar" dans ce répertoire.

WEB-INF/classes: tous les fichiers de code (d'extension "java", les servlets inclus) de l'application Web sont rangés dans ce répertoire. On peut aussi, si on a des fichiers "jar " qu'on a développé pour l'application, les mettre dans ce répertoire.

web.xml : ce fichier "web.xml" appelé aussi fichier "descriptor", est placé dans le répertoire "WEB-INF". Il contient tous les paramètres de configuration, d’initialisation ou de description de l'application.

META-INF/MAINFEST.MF: C'est le fichier Manifest (voir son emplacement dans l'image ci-dessus)

Static Files : Tous les fichiers statiques comme les fichiers HTML, css, JavaScript sont placés sous le répertoire racine de l'application Web. pour plus de sécurité on les place sous le répertoire WEB-INF.

Web.xml (Descripteur de déploiement)

C'est le fichier standard de déploiement de toute application Web et son contenu donne les détails de configuration, d' initialisation et de description de l'application.

Exemple de web.xml

 
<?xml version="1.0" encoding= "ISO-8859-1" ?> 
     <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance 
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
  version= "2.4">
 <servlet>    
 <servlet-name> projetServlet</servlet-name>
 <servlet-class> projetServlet </servlet-class>  
  <init-param><param-name>name</param-name>
 <param-value>First Servlet</param-value>
  </init-param>
<init-param> <param-name>purpose</param-name> <param-value>learning</param-value> </init-param> </servlet> <context-param> <param-name>param</param-name> <param-value>the value</param-value> </context-param> <servlet-mapping> <servlet-name> projetServlet </servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app>

(à suivre )

précédent suivant

I. Cycle de vie d'une Servlet

Une requête dans un conteneur web est prise en charge par le conteneur; si une requête arrive pour la première fois dans le serveur Web (conteneur), on a le conteneur qui effectue les actions suivantes:

  1. chargement de la Servlet,
  2. Création d'une instance de la Servlet (pour chaque Servlet, au cours de son cycle de vie, on a une et une seule instance créée),
  3. Initialisation de la Servlet par appel de la méthode init() par le Conteneur web.
  4. Une fois que la Servlet est initialisée, elle est prête pour exécuter les requêtes.
  5. Pour chaque requête le conteneur génère une thread qui exécute la méthode service()
  6. Quand le conteneur reçoit l'ordre de détruire la Servlet, il fait appel à la méthode destroy() de la Servlet.

Les trois étapes (a, b, c) sont exécutées une et une seule fois; la quatrième étape (l'étape d) quant à elle, est exécutée à chaque fois qu'il y a une nouvelle requête. La dernière étape, quand elle est exécutée, la Servlet est définitivement détruite.

II. Cycle de vie de chaque Servlet en détail

1. Chargement de la classe Servlet

Pour qu'une classe java arrive dans la mode exécution, elle doit être chargée et c'est la même chose pour une Servlet. Lorsqu'une Servlet est chargée, il n'existe qu'une seule instance de la Servlet durant son cycle de vie.

2. Création de l'instance d'une Servlet

Une fois que la Servlet est chargée, le conteneur crée une seule instance de la Servlet.
Le container exécute cette étape un seule et une seule fois pour une Servlet donnée.

3. Initialisation de la Servlet (le Container appelle la méthode init())

L'initialisation est réalisée une fois lorsque la Servlet est créée. Dans la méthode init(), on peut avoir les paramètres d’initialisation dans le fichier de configuration web.xml; voir un exemple de web.xml (voir détail ultérieurement)

4. Appel de la méthode service()

C'est la méthode principale qui exécute la logique métier de l'application et c'est elle qui est aussi responsable du traitement des requêtes des clients. Quand une nouvelle requête d' une Servlet arrive, le conteneur génère une nouvelle Thread; la nouvelle thread exécute la méthode service() puis la logique métier de l'application ou la tâche prévue de la Servlet.
La définition de la méthode service() est:

public void service(ServletRequest request, ServletResponse response)
throwsServletException, IOException{
}

La méthode service() prend deux arguments "request" de type ServletRequest et "response" de ServletResponse.
Une requête HTTP peut être de différents type comme GET, POST, PUT, DELETE, etc; le rôle de la méthode service() de voir la requête HTTP requise et de faire appel à la méthode adéquate qui peut être doGet, doPost, doPut, doDelete, etc .

doGet(ServletRequest req, ServletResponse res): le type par défaut de toute requête http est "GET"; cela veut dire que si on ne spécifie pas un type de requête c'est le type "GET" qui prend en charge la requête donc la méthode doGet() au sein d'une Servlet. Comme son nom l'indique la méthode doGet() récupère des données ou des informations du serveur via une ou plusieurs requêtes. Toutefois on peut aussi envoyer des données ou des informations au serveur via une requête. La méthode doGet(ServletRequest req, ServletResponse res)doGet a comme signature:

 public void doGet(HttpServletRequest request, HttpServletResponse response)   throwsServletException, IOException {
}

doPost(ServletRequest req, ServletResponse res): Cette méthode est utilisée pour envoyer des données au Serveur; pour faire des requêtes HTTP de type POST on le spécifie dans la balise "form" par l'attribut POST; La méthode POST est une bonne alternative à la méthode GET. Cette méthode code les informations de la même façon que la méthode GET (encodage URL et paires nom/valeur) mais elle envoie les données à la suite des en-têtes HTTP, dans un champ appelé corps de la requête. De cette façon la quantité de données envoyées n'est plus limitée, et est connue du serveur grâce à l'en-tête permettant de connaître la taille du corps de la requête. La signature de la méthode doPost(ServletRequest req, ServletResponse res) est:

public void doPost(HttpServletRequest request, HttpServletResponse response)   throwsServletException, IOException {
}

5. Appel de la méthode destroy()

La méthode destroy() est appelée à la fin du cycle de vie de la Servlet; elle permet aussi, si elle est invoquée, de fermer tous les fichiers ou bases de données ouverts par la Servlet lorsqu'elle était chargée par le conteneur.
Une Servlet est déchargée par le conteneur dans les deux cas suivants:

  1. Si le conteneur s'arrête,
  2. Si le conteneur recharge l'environnement d'exécution de l'application web

Après l'appel de la méthode destroy(), la Servlet es envoyée au ramasse-miette. La signature de la méthode destroy() est:

 public void destroy(){
}

Comme mentionné ci-dessus, la Servlet est chargée dès qu'elle sollicitée pour la première fois pour traiter une requête. Il existe des cas où on veut qu'elle le soit avant la sollicitation d'une requête; pour cela on le définit dans le fichier de configuration "web.xml" en se servant de la propriété "<load-on-startup>" . La valeur qu'on donne à cette propriété permet de forcer le conteneur de charger la Servlet dès que le conteneur démarre.

  <servlet>
       <servlet-name>MyFirstServlet</servlet-name>
       <servlet-class>MyFirstServlet</servlet-class>
       <init-param>
       <param-name>param-name</param-name>
       <param-value>param-value</param-value>
       </init-param>
        <load-on-startup>1</load-on-startup>
  </servlet>

Le nombre entre les deux balise ci-après "<load-on-startup>1</load-on-startup>" indique au conteneur de charger la Servlet dès que le que le conteneur est démarré. Si le nombre est négatif, la Servlet le conteneur peut charger la Servlet à n'importe quel moment.

précédent suivant

4. Autres  techniques de collaboration entre Servlets

La collaboration entre Servlets comme on l' a vue dans les précédents articles se fait par échange d'informations directement entre Servlets via leurs méthodes publiques (façon abandonnée pour des raisons de sécurité)  ou en s'appuyant sur d'autres techniques comme  "le partage d'informations" ou  le "Partage de contrôle".

4.1. Collaboration via le système de liste de propriétés de la Servlet

Une des plus simples façon qui permet l'échange d'informations entre Servlets est l'utilisation du système de liste des propriétés de Java qui se trouve dans la classe "java.lang.System". Dans ce système de liste de propriétés se trouvent des propriétés standard comme " java.version" et  "path.separator" mais aussi les propriétés les plus spécifiques d'une application. Chaque Servlet peut ajouter ou modifier une propriété en procédant comme suit:

System.getProperties().put("key", "value");

Toutes les Servlets qui se trouvent  sur le même serveur dans la même JVM peuvent accéder à la valeur d'une quelconque propriété de n'importe quelle  Servlet qui s'y trouve en procédant comme suit: 

 String value = System.getProperty("key");

On peut aussi changer la valeur ou l'enlever par:

System.getProperties().remove("key");

Il est beaucoup plus facile de manipuler un couple (clé, valeur) de la liste de propriétés  si la  clé du couple  propriété (Properties) a un préfixe qui contient le nom du package de la Servlet et le nom de du groupe de collaboration.

La classe Properties est une classe persistante qui représente les propriétés (properties) d'une application sous forme de couple de chaînes de caractères; chaque couple (clé, valeur) est donc un couple de "String"; cette limitation (le fait que ce soit un couple de String) est parfois contournée par des Servlets qui veulent stocker ou retirer des Objets qui ne sont pas de type String. Ces Servlets peuvent tirer avantage du faite que la classe Properties étend la classe Hashtable; la liste des propriétés peut donc être considérée comme un objet Hashtable quand on traite un couple (clé, valeur); Par exemple, une Servlet peut ajouter ou changer un objet Properties en procédant comme suit:   

System.getProperties().put(keyObject, valueObject);  // hack

On peut récupérer les propriétés d'un objet par l'instruction ci-dessous:

SomeObject valueObject = (SomeObject)System.getProperties().get(keyObject);

On peut retirer une propriété en procédant de la façon suivante:

   System.getProperties().remove(keyObject);

Le détournement de l'utilisation du système de liste des propriétés comme on l' a dit ci-dessus, provoque, de la part des méthodes "getProperty()", "list()" et "save()" de la classe Properties, une levée d'exception de type  ClassCastException car ces méthodes s'attendent à avoir à faire à des String. Pour cette raison, il faut éviter de se servir de ces méthodes mais plutôt utiliser d'autres techniques de collaboration entre Servlets; il faut aussi se souvenir que les fichiers contenant les classes de keyObject et de valueObject doivent se trouver dans la classPath du Serveur et non dans le répertoire où est chargée  la Servlet sinon on peut avoir des erreurs.
On a aussi plus de trois raisons  qui nous dissuadent d’utiliser les méthodes de collaboration entre Servlet; en effet, entre deux recharges d'une Servlet,  d'autre Servlet peuvent modifier les propriétés de certaines Servlets car les informations présentes dans les propriétés ne sont pas naturellement persistantes entre deux recharges d'une Servlet.

Exemple d'utilisations de propriétés
Malgré les avertissements ci-dessus pour l'utilisation du système de liste des propriétés des Servlets pour la collaboration entre Servlets se trouvant dans une même JVM, on peut s'en servir si on traite des informations non critiques; prenons l'exemple d'une Servlet utilisée pour la vente de produits et qui partage "une  vente spéciale du jour" avec d'autres Servlets sur le même serveur . La Servlet qui gère cette vente peut procéder comme suit:

 System.getProperties().put("com.LaCostena.special.burrito", "Pollo Adobado");  
System.getProperties().put("com.LaCostena.special.day", new Date());

Par la suite les autres Servlets sur le Server peuvent accéder à la vente spéciale du jour en procédant comme suit:

String burrito = System.getProperty("com.LaCostena.special.burrito"); 
Date day = (Date)System.getProperties().get("com.LaCostena.special.day");
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);    
String today = df.format(day);
out.println("Our burrito special today (" + today + ") is: " + burrito);

4.2. Chaînage rapide des images

On peut accélérer la transmission d'une image dans une Servlet à une autre Servlet  dans un ensemble de Servlets présentes dans une JVM en utilisant le système de liste de propriétés de la Servlet émettrice ou réceptrice. Dans un autre chapitre on a vu comment deux Servlets peuvent  s'échanger une image de manière classique; la première Servlet prend un Objet image, l'encode en un flux de bytes et envoie le flux de bytes à l'autre Servlet;  la Servlet qui reçoit le flux de bytes issu de l'objet image le décode  et récupère ainsi l'objet image. Cette façon de faire est très lente. Pour aller plus vite, ici on va se servir du système de liste des propriétés des Servlets issues d'un même JVM. Dans l'exemple que nous traiterons on montre exactement comment une Servlet transmet la clé de l'objet image  sauvegardée dans le système de liste des propriétés de l'application  et comment une autre Servlet récupère cette clé pour afficher ou traiter l'image sans la télécharger mais en la laissant  au même endroit.

4.3. Exemple:  échanger une image via la liste des propriétés

(à suivre)

précédent suivant

Servlets

1. Introduction

Une servlet est une application java qui s’exécute côté serveur en tant qu'extension du serveur; elle transmet des informations au serveur ou répond à des requêtes clientes. Toute application client/serveur peut mettre en œuvre une servlet en s'appuyant, soit sur le protocole http, soit sur d'autres protocoles comme ftp, smtp, etc. Dans les anciens serveurs Web,  on a besoin d'un mécanisme particulier pour prendre en charge les Servlets; ce mécanisme s'appelle conteneurs ou moteur de servlets; le plus célèbre d'entre eux  est Tomcat le moteur de Servlets développé par Apache Foundation.

Une Servlet peut être invoquée plusieurs fois par plusieurs requêtes simultanées. Écrite en java, une Servlet en retire toutes les avantages notamment, la portabilité, l'accès à toutes les API de Java comme JDBC (API qui permet l'accès aux bases de données).

2. L'interface javax.servlet.Servlet

L'API Servlet est rajoutée à JAVA à partir de J2EE 1.4; elle est repartie dans deux packages, le package "java.servlet" et  le package "javax.servlet.http". L’appellation javax au lieu de java au sein du nom du package indique que l'API Servlet fait partie de java J2EE. L'interface de base de cet API est javax.servlet.Servlet.

2.1 Le package javax.servlet 

Ce package contient des classes génériques, des interfaces qui ne dépendent pas d'un protocole particulier (protocol-independent)

2.2 Le package javax.servlet.http

Ce package contient des classes et des interfaces spécifiques pour des fonctionnalités relatives au protocole HTTP. 
L'interface javax.servlet.Servlet définit toutes les méthodes gérant le cycle de vie de toute Servlet. Comme cette interface est l'interface de base de toute  Servlet, chaque Servlet doit implémenter toutes ses  méthodes à savoir:

  1. public abstract void init(ServletConfig) throws ServletException : C'est la méthode déterminant le cycle de vie pour une Servlet;  elle est invoquée une seule fois lorsque le cycle de vie d'une Servlet particulière est traitée. cette méthode est utilisée pour initialiser une  Servlet.
  2. public abstract void service(ServletRequest , ServletResponse ) throws ServletException, IOException : C'est la méthode principale responsable de la logique métier d'une Servlet; si une nouvelle requête arrive au niveau de la Servlet, le conteneur web génère une nouvelle Thread; cette Thread exécute la méthode service() et traite la logique métier ou la tâche particulière attendue par la requête.
  3. public abstract void destroy(): La méthode destroy() est appelée uniquement à le fin du cycle de vie d'une Servlet;  cela permet à la Servlet de fermer  toutes les opérations restées en suspens comme, l'accès à des bases de données ou la fermeture de tous les fichiers ouverts.
  4. public abstract ServletConfig getServletConfig(): Cette méthode retourne l'objet Configuration de la Servlet; cet Objet  Configuration contient tous les paramètres de configuration et d’initialisation de la Servlet.
  5. public abstract String getServletInfo(): Cette méthode retourne une chaîne caractères qui contient des informations relatives à la Servlet; par exemple, on peut l'utiliser pour avoir  le nom de l'auteur de la Servlet.

3. L'interface Javax.servlet.ServletConfig

Au sein d'une Servlet on se sert de cette interface pour récupérer les paramètres d'initialisation et de configuration qui sont définis dans le fichier de configuration "web.xml". Chaque Servlet a ses propres paramètres et pour y avoir accès, on fait appel à la méthode "getServletConfig()" qui retourne  un objet ServletConfig. Les méthodes les plus importantes de l'interface ServeltConfig sont:

  1. public abstract ServletContext getServletContext():
    Cette méthode retourne un objet "ServletContext" au sein de la Servlet.
  2. public abstract Enumeration getInitParameterNames():
    Cette méthode retourne une  Enumeration des noms des paramètres de "init" définis pour la Servlet.
  3. public abstract String getInitParameter(String ):
    Cette méthode retourne la valeur d'un paramètre d'initialisation dont le nom est donné comme paramètre d'appel; si ce nom ne référence pas un paramètre présent dans "web.xml", elle  retourne "null".

4. La classe abstraite Javax.servlet.GenericServlet

 Cette classe abstraite implémente  les deux interfaces  "javax.servlet.Servlet" et  "javax.servlet.ServletConfig". Comme son nom l'indique, cette classe  est générique, donc elle ne nécessite pas de protocole particulier. Dans les classes qui dérivent de cette classe, on a part défaut l'implémentation de toutes les méthodes disponibles dans les interfaces  javax.servlet.Servlet et javax.servlet.ServletConfig.  Nous pouvons  donc simplement étendre cette classe pour avoir toutes les fonctionnalités disponibles par défaut et les utiliser. Comme la méthode service() est une méthode abstraite, si on utilise la classe GenericServlet on doit implémenter soit même la méthode service().

5. La classe abstraite javax.servlet.http.HttpServlet

La classe  abstraite "javax.servlet.http.HttpServlet" dispose  de beaucoup de méthodes entre autre les méthodes :

  • doGet(), pour les requêtes HTTP GET
  • doPost(), pour les requêtes HTTP POST
  • doPut(), pour les requêtes HTTP PUT
  • doDelete() pour les requêtes HTTP DELETE

Ces méthodes facilitent le travail avec le protocole HTTP en permettant aux clients du serveur web de dialoguer avec les Servlets HTTP présentes  au sein du serveur web. La classe javax.servlet.http.HttpServlet implément l'interface javax.servlet.Servlet définie ci-dessus; donc elle définit les 5 méthodes  init(), service(), destroy(), getServletConfig() et getServletInfo() qui assurent le cycle de vie d'une quelconque Servlet HTTP  en étant respectivement appelée lors de la création d'une Servlet, lors de l'appel d'une Servlet  pour le traitement d'une requête et lors de la destruction d'une instance de la Servlet.
La méthode public abstract void init(ServletConfig) throws ServletException: Elle est appelée par le serveur juste après l'instanciation de la Servlet. Lors de l'instanciation, le conteneur de Servlets passe en argument à la méthode init() un objet ServletConfig permettant de charger des paramètres de configuration propres à la Servlet. En cas d'anomalie lors de l'appel de la méthode init(), celle-ci renvoie une exception de type ServletException et la Servlet n'est pas initialisée.
La méthode public abstract void service(ServletRequest , ServletResponse ) throws ServletException, IOException: Elle ne peut pas être invoquée tant que la méthode init() n'est pas terminée; elle reçoit et répond aux requêtes des clients
La méthode public abstractvoid destroy(): Elle est appelée juste avant que le serveur ne détruise la Servlet: cela permet de libérer des ressources allouées dans la méthode init() tel qu'un fichier ou une connexion à une base de données.
public abstract ServletConfig getServletConfig(): Cette méthode retourne un objet qui représente la configuration de la Servlet; cet objet contient chaque paramètre d'initialisation et de démarrage de la Servlet.
public abstract String getServletInfo(): Cette méthode retourne une chaîne de caractères contenant  des informations relatives à la Servlet.

(à suivre).. 

précédent

3. Communication entre Servlets:  Partage de contrôle

3.1. Généralités : l'interface RequestDispatcher

3.1. 1. Présentation
L'interface RequestDispatcher possède deux méthodes qui permettent le partage de contrôle de requêtes; la première méthode forward() permet la délégation d'une requête à une autre Servlet et la deuxième méthode include() inclut le contenu d'un fichier à une autre Servlet.

  1. void forward(ServletRequest request, ServletResponse response) :  cette méthode forward une requête à partir d'une Servlet vers une autre ressource qui peu être une  Servlet, un fichier  JSP, ou un fichier HTML présent dans  le Server.
  2. void include(ServletRequest request, ServletResponse response):  cette méthode va inclure le contenu d'une ressource  (servlet, JSP page, HTML file) dans la réponse renvoyée au client. La réponse peut être ainsi construite à partir d'un ensemble de contenus générés par divers composants web. Dans ce cas la première Servlet conserve le contrôle.

3.2. Fonctionnement de 'interface RequestDispatcher

3.2.1. Délégation
La délégation est obtenue par un distributeur de requête, c'est-à-dire par une instance de la classe "javax.servlet.RequestDispatcher". La Servlet qui se sert de cette instance obtient un distributeur sur la requête vers un composant de l'application (servlet, jsp, fichier statique, ...) en indiquant son URI par la méthode:
public RequestDispatcher ServletRequest.getRequestDispatcher(String uri) ;
l'URI peut être:

  1. relatif; dans ce cas  on reste dans le contexte de la Servlet courante
  2. absolu; dans ce cas  l'"URI" est interprété relativement à la racine du contexte

Le chemin ( l'URI) peut être complété par une chaîne d'interrogation comme on le verra dans un exemple ci-dessous.

C'est La méthode forward(...) de l’interface RequestDispatcher qui permet de faire ce renvoie d'une requête d’une Servlet à une autre ressource sur le serveur:
"void forward(ServletRequest req, ServletResponse res)" : ici on a une redirection de requête

RequestDispatcher dispat = req.getRequestDispatcher("/index.html");
dispat.forward(req,res);

req est un objet de type ServletRequest qui représente la requête faite par le client à la Servlet ; getRequestDispatcher est une méthode de ServletRequest 
res est un objet de type ServletResponse représentant la réponse faite au client par la Servlet .
On voit bien que le chemin est relatif   au contexte de l'application (cela est précisé par la présence de "/" au début de l'URI). La réponse ne doit pas être traitée après qu'on est fait appel à "forward(..)" sinon on a un levée d'exception.

....

3.2.2. inclusion de contenu

La méthode include(...) de l’interface RequestDispatcher inclut le contenu d’une ressource dans la réponse courante 

RequestDispatcher dispat = req.getRequestDispatcher("/index.html");
dispat.include(req,res);

La différence avec une distribution par renvoi est que la Servlet appelante garde le contrôle de la réponse et qu' elle peut inclure du contenu avant et après le contenu inclus

Possibilité de transmettre des informations lors de l’inclusion

  • en attachant une chaîne d’interrogation (au travers de l’URL)
  • en utilisant les attributs de requête via la méthode setAttribute(...)

Exemple

public class IncluderServlet extends HttpServlet { 
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { 
  res.setContentType("text/html"); 
  PrintWriter out = res.getWriter(); 
  out.println("");
  RequestDispatcher dispat = req.getRequestDispatcher("included.html"); 
dispat.include(req,res); out.println(" "); req.setAttribute("bonjour", "Bonjour"); dispat.include(req,res); out.println(" "); //Cette Servlet réalise trois inclusions req.setAttribute("bonsoir", "Bonsoir"); dispat.include(req,res);
out.println(" "); out.println(""); }
}

...(à suivre)

précédent suivant