TP2 : Etude des servlets

De $1

Introduction

Ce TP est consacré à l'étude des servlets. Nous allons étudier des exemples en Java EE 5 (où de nombreux éléments sont indiqués dans le descripteur web.xml, comme le mapping des servlets sur des URLs), mais aussi des exemples en Java EE 6 où les annotations de code sont omniprésentes.

Etude d'un projet contenant de nombreux exemples J2EE 1.4

Oui, il s'agit d'exemples en J2EE 1.4 (l'ancêtre de Java EE 5, lui-même ancêtre de Java EE 6 !). Ils sont toujours d'actualité, les seules choses qui peuvent changer en Java EE 6 sont les annotations de code qui permettraient de se passer d'une partie de ce qui est spécifié dans le descripteur web.xml (nous allons l'étudier un peu plus tard...)

Ouverture du projet

Sous netbeans, faites file/nouveau projet, puis choisissez dans les exemples le projet suivant :

Snap1.jpg

Cela va ouvrir dans netbeans un projet Java web contenant de nombreux exemples :

Snap3.jpg

Lancer le projet, tester les exemples, regarder le code source

Faites clic droit / run sur le projet, cela va ouvrir une page avec la liste des exemples de servlets que vous allez étudier. Regardez l'exécution, les URLs, et le code source.

Regardez aussi le vrai code source des servlets (dans le package par défaut, sous "src").

Notez au passage la manière dont l'aspect "multi-langue" est géré (à l'aide de fichiers de propriétés et de la classe ResourceBundle) :

 

ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",request.getLocale());

Cette ligne indique que l'on ira chercher les "ressources" dans un fichier LocalStrings.properties par défaut, contenant des couples clé=valeur. Selon la langue du système, on ira chercher dans un fichier LocalStrings_fr.properties, LocalStrings_es.properties, LocalStrings_en.properties, etc le fichier de base étant celui par défaut.

Puis ensuite, lorsqu'on veut manipuler une chaine de caractères pour l'affichage : 

String title = rb.getString("helloworld.title");

On retrouvera la valeur de cette chaîne de caractère dans le fichier LocalStrings_fr.properties si on est en français. Double cliquez sur le nom du fichier pour voir son contenu :

 

helloworld.title=Salut le Monde!

requestinfo.title=Exemple d''information sur la requête
requestinfo.label.method=Méthode:
...

Regardons la partie "servlets" du fichier de configuration web.xml

Double cliquez sur le fichier web.xml qui se trouve sous "configuration". Netbeans doit ouvrir une "vue" de ce fichier, vous pouvez en cliquant sur le bouton "XML" passer à la vue XML du fichier. Il contient de nombreuses informations. Pour le moment, nous allons nous intéresser à la partie "servlets", notamment au mapping entre les servlets et les URLs qui permettent de les invoquer.

Vue "servlet" du fichier web.xml :

Snap5.jpg

 Comme vous pouvez le voir, on peut utiliser des expressions régulières pour associer non pas un URL à une servlet, mais aussi plusieurs ! Ici la servlet RequestInfoExample est associée à tous les URLs de type /servlet/RequestInfoExample/*

Executez donc cet exemple, et modifiez l'URL, par exemple en ajoutant "toto" à la fin :

Snap6.jpg

Regardez dans le source comment on peut récupérer le "/toto". Cet exemple montre comment on peut par exemple, développer une Servlet qui utilise l'URL complet pour un paramètre permettant par exemple d'aller chercher "toto" dans une base de données. Imaginez : http://www.monsite.com/disques/Beatles/AbbeyRoad, et une unique servlet "disques" qui saura à partir de cet URL aller chercher le disque "Abbey Road" des Beatles dans sa base de données.

Modification de la page d'accueil par défaut du projet

Lorsqu'on exécute le projet il affiche la page par défaut du projet. On peut préciser quelle est cette page dans le descripteur web.xml, on peut même en indiquer plusieurs (si la première n'existe pas, c'est la seconde qui sera utilisée, etc.). Par défaut, c'est la page index.html qui est affichée. Les pages web se situent sous "Web Pages" dans la structure de projets de netbeans. 

  1. Modifiez maintenant cette page pour que cela soit le fichier reqinfo.html qui soit affiché par défaut (on doit voir le source de l'exemple du screenshot précédent s'afifcher),
  2. Modifiez maintenant la page par défaut pour que cela soit la servlet HelloWorldExample qui soit affichée (cela doit afficher non pas le source mais l'exécution de la servlet, soit le message "Salut le monde !"

NOTE : il se peut que vous deviez faire shift-reload sur votre navigateur pour que la page s'affiche réellement, cela dépend des navigateurs et des options de cache.

Positionnement de paramètres "globaux" à l'application dans le web.xml ("context parameters")

Nous allons maintenant utiliser le fichier web.xml pour positionner des paramètres "globaux" à l'application. On les appelle des "Context Parameters". Vous allez, dans le fichier web.xml, positionner un de ces paramètres, que vous appellerez par exemple SMTP_server (cela peut être utile si vous écrivez une application qui envoie des mails). Vous lui donnerez comme valeur "smtp.google.com".

Pour cela, double cliquez sur le fichier web.xml et utilisez l'onglet "general" pour positionner ce paramètre. Nous allons voir que l'on peut récupérer ces paramètres :

  1. soit au tout début de l'exécution de notre application web (la première fois qu'elle est lancée), dans une classe qui implémente "ContextListener",
  2. soit dans la méthode init() d'une servlet, exécutée lors de la première invocation d'une servlet.

Snap8.jpg

Une fois le paramètre positionné, ouvrez le fichier ContextListener.java et regardez un peu le code, nous allons nous intéresser plus particulièrement à la méthode contextInitialized() située à la fin... et nous allons ajouter deux lignes pour afficher la valeur du paramètre :

 

public void contextInitialized(ServletContextEvent event) {
    this.context = event.getServletContext();
      String smtpServer = context.getInitParameter("SMTP_server");

     log("contextInitialized()");

      log("SMTP SERVER = " +smtpServer);
    }

Nous allons observer ce qu'il se passe dans la console du serveur. Au passage, c'est là qu'apparaissent les erreurs s'il y en a, il faudra prendre l'habitude de l'utiliser ! Pour commencer, effaçons son contenu :

Snap11.jpg

Executons maintenant le programme et regardons à la loupe la trace dans la console :

Snap12.jpg

Habituellement, dans un contextListener, on "prépare les choses", en gros, on récupère un gros paquet de paramètres et on fait des initialisations globales à partir de ces paramètres... on crée de nouveau objets que l'on ajoute dans le servletContext (avec setAttribute). Un exemple concret : on écrit un CMS qui va utiliser de nombreux chemins sur le disque, pour gérer les images, les vidéos, les pages, etc. On va lire tous ces chemins, créer un objet de type PathManager, instance d'une classe à vous, avec des getPathForVideos() etc... et on va rajouter l'instance de ce PathManager dans le contexte. Dans n'importe quelle servlet qui devra utiliser ces chemins, dans sa méthode init() elle récupèrera dans le contexte une référence sur le PathManager et la conservera dans une variable qui sera utilisée pendant toute la durée de vie de la servlet.

Exemple de code dans une servlet qui récupère le paramètre SMTP_server (ici dans la servlet SessionExample.java)

 

public class SessionExample extends HttpServlet {
    String smtpServer = "";

    public void init() {
        smtpServer = getServletContext().getInitParameter("SMTP_server");
        System.out.println("Dans la Servlet SessionExample.java : SMTP Server = " + smtpServer);
    }
...

Faites donc cette modification puis exécutez la servlet, et regardez les traces du serveur comme précédemment.

Utilisation de paramètres d'initialisation d'une Servlet (les "init parameters")

Il est possible de passer des paramètes aux servlets, qui seront récupérables de la même manière que les paramètres globaux, sauf que cette fois-ci ils seront propres à une servlet. On utilise pour cela l'onglet "Servlet" de l'éditeur de fichier web.xml.

  • Ajoutez donc un paramètre dans une des servlets du projet et récupérez-le dans une méthode init() de cette servlet, que vous écrirez. Executez le projet et regardez la trace.

Redirection du traitement, gestion de session, authentification

Dans une véritable application, les servlets jouent le rôle de contrôleurs web. En gros, on reçoit une requête, on la traite, puis on a passe la main à un autre élément (typiquement une page JSP ou une page JSF pour afficher des résultats), on peut aussi passer la main à une autre Servlet.

Ce "passage" se fait à l'aide de ces quelques lignes de code :

 

 RequestDispatcher dp = request.getRequestDispatcher("bienvenue.html");

 dp.forward(request, response);

Attention, on n'a pas le droit d'exécuter quoique ce soit après la dernière ligne, puisque la Servlet qui a exécuté ce code a déjà "passé la main". Notez que on passe à l'URL vers lequel on va la requête et la réponse dans l'état.

Travail à faire :

  1. Ecrivez une page authentification.html qui affiche un formulaire demandant un login et un password. Les champs de saisie auront pour noms : "nom" et "motDePasse".
  2. Ce formulaire passera les paramètres à une servlet ServletAuthentification.java qui devra :
    1. Récupérer les valeurs des paramètres "nom" et "motDePasse",
    2. Afficher dans la console "demande d'authentification pour l'utilisateu :r" + nom + " avec comme mot de passe" + motDePasse...
    3. Gérer une HashMap loginsEtPassword, qui contiendra des couples "nom/mot de passe", pour vérifier si un login/password est correct ou pas, par défaut elle contiendra "buffa/toto" et "john/lennon". Vous initialiserez ces valeurs dans la méthode init() de la Servlet.
    4. La Servlet vérifiera si le couple nom/motDePasse passé en paramètre est correct. Si ce n'est pas le cas, elle "passera la main" à la page "mauvaisPassword.html" qui affichera un message indiquant que le lgin et le password sont incorrects. Si le couple est correct (présent dans la Map), elle "passera la main" à la page "bienvenue.html" qui indiquera que l'on s'est bien authentifié. Chacune des deux pages HTML contiendra un lien vers la page d'authentification initiale.
  3. Vous ajouterez à la page d'accueil un second formulaire permettant de s'enregistrer. Dans ce cas, le nom et le mot de passe seront renvoyés à la même Servlet, mais dans le but de les rajouter à la Hashmap contenant la liste des utilisateurs et leurs passwords. Vous utiliserez dans les deux formulaires un champ <input type="hidden" action="enregistrer"/> ou <input type="hidden" action="authentifier"/> pour indiquer à la servlet l'action qu'elle doit exécuter. Après un enregistrement, la Servlet renverra vers une page 'enregistrementTermine.html".
  4. Maintenant on va gérer une session HTTP dans la servlet d'authentification. On stockera dans la session une variable "authentifié" qui vaudra true ou false selon que la personne est authentifiée ou pas. La première fois que la personne s'authentifie correctement, on positionne la variable de session à true et on renvoie vers la page bienvenue.html. Si on redemande la page authentification.html et que l'on essaie de s'authentifier à nouveau, alors la servlet affichera un message "session en cour avec l'utilisateur " + récupérer le nom de l'utilisateur courant. Veuillez vous déconnecter d'abord si vous voulez vous connecter sous un autre nom !
  5. Rajoutez un lien ou un bouton pour se déconnecter dans la page d'authentification. Lorsqu'on clique sur le lien ou la session, cela ferme la session et renvoie à nouveau vers la page d'authentification.

Bien sûr dans les prochains cours, lorsque nous aurons vu les pages JSPs et JSFs nous feront tout cela de manière bien plus élégante !

Un peu de Java EE 6, annotations, ServletFilters et WebListeners

Dans Java EE 6 une des grosses différences est que le fichier web.xml n'est plus indispensable et que nombre d'annotations de code remplacent des éléments auparavant dans le web.wml, comme :

  • L'association URL ou URL pattern avec la servlet,
  • La spécification de paramètres d'initialisation,
  • La spécification de "filtres", nous allons voir de quoi il s'agit, 
  • etc.

Travail à faire :

  1. Récupérez l'archive mood.zip et dézippez-là dans le répertoire où vous stockez les projets netbeans (dans Mes Documents\Netbeans Projects sous windows), et corrigez le fichier "build.xml" : remplacez "<import file="../../bp-project/main.xml"/>" par "<import file="nbproject/build-impl.xml"/>",
  2. Ouvez le projet avec netbeans,
  3. Executez-le ! 
  4. Remarquez que le projet ne contient pas de fichier web.xml,
  5. Regardez le source de la Servlet, remarquez que le mapping avec son URL est dans une annotation de code,
  6. Qui passe le paramètre "mood" (qui signifie "humeur" en français) à la Servlet ? Pourtant il est bien dans la requête,
  7. Regardez le fichier TimeOfDayFilter.java, il s'agit d'un "filtre" (ServletFilter en anglais). Les filtres sont des "intercepteurs d'appel d'URLs" qui permettent de faire des choses "avant" que la Servlet correspondant à l'URL soit appelée. Le travail se passe 1) dans la méthode init pour récupérer une valeur par défaut à la variable "mood", et 2) dans la méthode doFilter() qui est appelée à chaque appel d'un URL qui correspond à la pattern indiquée dans l'annotation de code juste avant la déclaration de la classe (@WebFilter(filterName = "TimeOfDayFilter", urlPatterns = {    "/*"}, initParams = {    @WebInitParam(name = "mood", value = "awake")})
  8. Notez que le paramètre d'initialisation est spécifiée aussi dans une annotation, pas dans le web.xml comme dans les exemples précédents.
  9. Regardez la classe SimpleServletListener.java qui fait l'équivalent du ContextListener du début du TP. Ici aussi, une simple annotation de code a suffi.

 Création d'un gestionnaire de contacts

Voilà, maintenant c'est à vous de jouer. On vous demande de créer un petit gestionnaire de contacts. Créez un projet de type "web application".

Vous utiliserez la classe Contact.java que vous écrirez, avec comme attributs nom, prenoms, adresse, tel. Ajoutez constructeurs, get/set etc. Et une Servlet GestionnaireDeContacts + des pages html pour saisir un contact, et chercher des contacts, etc. L'affichage sera du HTML généré par la Servlet (nous n'avons pas encore vu comment créer une "vue" des résultats séparément de la Servlet, mais cela va venir...)

Pour démarrer, vous ne ferez pas de persistence, utilisez une Collection pour gérer les contacts.

  • Ecrivez une méthode init qui créée déjà une dizaine de contacts au démarrage.
  • Implémentez dans la Servlet une méthode qui renvoie la liste des contacts sous forme de tableau HTML
  • Une méthode qui accepte en argument une chaine de caractère et qui renvoie un tableau HTML avec les contacts contenant cette chaine de caractères.

Par la suite nous verrons comment améliorer ce petit gestionnaire.

Mots clés:
FichierTailleDateAttaché par 
 mood.zip
Aucune description
72.36 Ko05:25, 17 Fév 2011MichelBuffaActions
Images (7)
Voir 1 - 6 sur 7 images | Voir tout
Aucune description
Snap12.jpg  Actions
Aucune description
Snap11.jpg  Actions
Aucune description
Snap8.jpg  Actions
Aucune description
Snap6.jpg  Actions
Aucune description
Snap5.jpg  Actions
Aucune description
Snap3.jpg  Actions
Commentaires (0)
Vous devez être connecté pour poster un commentaire.