D03-TP05- Jakarta EE : La portée des objets
Nous poursuivons le développement de l'application de gestion des clients Actuellement, lorsqu'un utilisateur valide la création d'un client, un message s'affiche afin de confirmer la création dans la base de données.
- Comment l’identifiant créé au niveau de la couche modèle peut-il être affiché au niveau de la vue (page JSP) ?
- Avons-nous actuellement les moyens d'afficher les identifiants de tous les clients venant d'être créés ?
I. La durée de vie des objets
La portée des objets (visibilité ou scope) définit leur durée de vie.
Il existe 4 portées différentes :
- page (pour les JSP uniquement) : les objets de cette portée ne sont accessibles qu'au niveau de la page JSP.
- requête : les objets de cette portée sont uniquement accessibles durant l'existence de la requête, dès que la réponse est re-transmise, elle disparaît.
- session : les objets de cette portée restent accessibles durant l'intégralité de la connexion d'un utilisateur.
- application : les objets de cette portée sont accessibles durant l'existence de l'application pour tous ceux qui se connectent.
Il est possible de créer et de manipuler des objets de portées requête, session ou application depuis une page JSP ou depuis une servlet.
- Quel type d'objet devrions-nous mémoriser afin de pouvoir afficher la liste des clients venant d'être créés ?
- Quelle sera la portée la plus pertinente pour cet objet ?
II. Le principe de la session
La session représente un espace mémoire alloué pour chaque utilisateur, permettant de sauvegarder des informations tout au long de leur visite.
Le contenu d'une session est conservé jusqu'à la fin de la connexion de l'utilisateur, ou après un délai d'inactivité trop long.
L'objet Java qui gère une session est HttpSession.
A. Les méthodes d'accès à la session et aux attributs mémorisés
1. Récupération de la session
La méthode getSession de l'objet HttpServletRequest permet de récupérer la session si elle existe, ou d'en créer une :
HttpSession maSession = request.getSession();
2. Récupération des attributs sauvegardés en session
La méthode getAttribute(“nomAttribut”) appliquée à la session permet de récupérer un attribut sauvegardé.
Exemple :
String maChaine = null; if (maSession.getAttribute("monAttribut" != null) { String maChaine = (String) maSession.getAttribute("monAttribut"); }
3. Mise en session des attributs que l'on souhaite mémoriser
La méthode setAttribute appliquée à la session permet de sauvegarder les attributs.
Exemple :
maSession.setAttribute("monAttribut", maChaine);
La chaine de caractères maChaine sera sauvegardée dans un attribut de session sous le nom de monAttribut.
4. Suppression d'une variable de session
maSession.removeAttribute("monAttribut");
5. Accès à une variable de session avec EL :
${sessionScope.nomVariable}
B. Mise en œuvre au niveau de la servlet (NouveauServlet.java)
Au niveau de la méthode doPost de la servlet NouveauServlet, avant la redirection vers la couche vue, il faut :
- Récupérer la session
- Rechercher la collection des nouveaux clients si elle existe, si elle n'existe pas il faut la créer.
- Ajouter le nouveau client créé à cette collection.
- Sauvegarder la collection des nouveaux Clients au niveau de la session
(Code à ajouter avant la redirection vers la jsp)
if (idClient != -1) { // Ajout du no du client créé, dans une collection d’entiers stockée en session // 1, Récupération de la session HttpSession maSession = request.getSession(); // 2. Récupération de la collection des clients si elle existe, création sinon ArrayList<Integer> lesNouveauxClients = (ArrayList<Integer>) maSession.getAttribute("lesNvxClients"); if (lesNouveauxClients == null) { lesNouveauxClients = new ArrayList<>(); } // 3. Ajout du no du client créé dans la collection lesNouveauxClients.add(idClient); // 4. Mise à jour de la session maSession.setAttribute("lesNvxClients", lesNouveauxClients); }
C. Mise en œuvre au niveau de la vue (nouveauClientVue.jsp).
Il faut désormais afficher le contenu de la collection lesNvxClients. En java, il faudrait ;
- Récupérer la session
- Récupérer la collection lesNvxSalaries
- Faire une boucle de parcours de la collection et afficher chaque no de client
Avec JSTL, on pourra écrire :
<article> <h3>Liste des numéros des clients récemment créés : </h3> <c:forEach items="${sessionScope.lesNvxClients}" var="unClient"> ${unClient} - </c:forEach> </article>
III. Comment fonctionne la session
1. À la suite d'un appel à request.getSession() :
L'identifiant de l'objet de type HttpSession créé est placé dans la réponse retournée au navigateur du poste client et celui-ci l'enregistre.
2. Le navigateur placera cet identifiant dans les prochaines requêtes qu'il effectuera :
3. Vérifier cet échange d'identifiant de session avec les outils de développement du navigateur
- Se positionner sur l'onglet Réseau des outils de développement, recharger la page et créer un nouveau client
- Cliquer sur la ligne de la requête POST, l'onglet Cookie permet de connaître son identifiant : valeur de JSESSIONID (Doc - Name = NouveauClient - Headers
- On retrouve également cet identifiant dans l'entête de la requête.
IV. Modification de l'authentification
Actuellement, la page d'authentification existe, mais il est possible de passer outre : on peut aller directement à la liste des clients ou créer un nouveau client. (Ex :localhost:8080/Test2Jakarta/NouveauClient).
L'authentification concerne les salariés de l'entreprise il faut donc les gérer :
- créer une table salarie dans la base de données qui contient leur login, mot de passe et leur rôle (estAdmin, booléen : administrateur ou pas)
- créer la javabean SalarieMysql pour gérer les salariés (2 méthodes : readAll() et lireSalarie1))
- créer une méthode existeUser(HttpServletRequest request) dans la classe AuthentifForm qui retourne un booléen pour vérifier l'existence de l'utilisateur dans la base de données
- changer la méthode controlerAdmin de la classe AuthentifForm pour utiliser le rôle du salarié qui s'authentifie
Après une authentification réussie, il faudra mettre en session un booléen (isAuthentified) indiquant cette réussite ou non (méthode doPost de la servlet AuthentifServ.java, avant la redirection). De même, il faudra supprimer cette variable de session au niveau de la méthode doGet.
Ensuite il faudrait faire en sorte qu'aucune page ne puisse s'afficher sans passer par une authentification réussie.
Cette façon de procéder fonctionne, mais le problème, c'est qu'il faudrait reproduire cette modification dans toutes les servlets. Ce qui n'est pas satisfaisant.
Au lieu d'apporter cette modification dans toutes les servlets, nous allons créer un filtre.
Un filtre est un objet Java qui peut modifier les entêtes et le contenu d'une requête http avant l'intervention d'une servlet.
Pour créer un filtre :
* onglet File>New File>Web>Filter puis Next.
* Nommer ce filtre AuthentifFilter, indiquer le Package com.mycompany.filter, puis Next
* Cocher la case “Add information to deployment descriptor (web.xml)”, puis Next et Finish
Dans la classe AuthentifFilter.java, remplacer le corps de la méthode doFilter par celui-ci :
<code>
Cast de l'objet request
HttpServletRequest requete = (HttpServletRequest) request; Pas de filtrage des css, des images, des js
String chemin =
requete.getRequestURI().substring(requete.getContextPath().length()); if (chemin.startsWith(“/css”) || chemin.startsWith(“/images”) || chemin.startsWith(“/js”)) {
chain.doFilter(request, response);
return;
}
Récupération de la session
HttpSession maSession = requete.getSession();
Récupération du booléen d'authentification
boolean authentificationOK = false;
if (maSession.getAttribute(“isAuthentified”) != null) {
authentificationOK = (boolean) maSession.getAttribute(“isAuthentified”);
}
if (authentificationOK) {
Poursuite sans problème
chain.doFilter(request, response);
} else {
retour vers la page d'authentification
request.getRequestDispatcher(“Accueil”).forward(request, response); }
</code>
Penser à adapter le nom du booléen d'authentification.
Tester.
Vérifier la présence de 2 nouvelles sections au niveau du fichier web.xml : <filter> et <filter mapping>
<del>Peut-être avez-vous remarqué un problème concernant les caractères spéciaux (accent, tréma, …) saisis dans les formulaires. Pour remédier à ce problème, il faut ajouter un filtre qui permettra de spécifier le format d'encodage UTF-8 pour les données échangées.
Télécharger filtreEncodage.xml depuis le Drive, et en copier le contenu dans votre fichier web.xml, redémarrer le serveur Tomcat (Services/Serveur/Restart) et tester.
</del>
A Savoir:
- Il existe 4 portées d'objets différentes, représentant 4 durées de vie différentes : page, requête, session et application.
- Une session suit un visiteur tant qu'il est connecté au site. La session est détruite si l'utilisateur quitte le navigateur ou après une longue période d'inactivité. Ce temps est paramétrable au niveau du fichier web-xml.
- Une session est un espace mémoire alloué sur le serveur et dont le contenu n'est accessible que depuis le serveur.
- Afin de savoir à quel poste client est associé à une session, le serveur transmet au poste client un identifiant de session dans les entêtes de la réponse. Il s'agit du cookie JSESSIONID. Le navigateur du poste client stocke ce cookie et le retransmettra au serveur lors de ses prochaines requêtes.
- L'initialisation ou la récupération d'une session s'effectue par :
HttpSession maSession = request.getSession();
- La récupération d'un attribut de session s'effectue par :
Type monAttribut = (Type) maSession.getAttribute("nomAttribut");
Type représente le type d'objet ou de donnée (Ex. : Salarie, int, String, ArrayList <Salarie> …)
- La mémorisation d'un attribut de session s'effectue par
maSession.setAttribute("nomAttribut", attribut);
V. Amélioration de l’application
À partir de la liste des clients, proposer la modification :
- Quand l'utilisateur souhaite modifier un client, il clique le lien hypertexte Modifier. Les données du client apparaissent au niveau du formulaire. La validation permet la mise à jour dans la base de données.
À vous de voir s'il y a besoin de créer des variables de session. Les méthodes doGet et doPost de la servlet se compliquent un peu : elles doivent désormais gérer les 2 cas : création ou modification.
1. Modification de l'interface graphique listeclientVue.jsp
Ajouter une colonne intitulée Action au tableau. Au niveau de chaque ligne de cette colonne, proposer “Modifier” qui sera un lien hypertexte vers nouveau?id=xx
- Quelle servlet s'activera après un clic sur Modifier ?
- Quelle méthode de cette servlet sera sollicitée ?
2. Modifier la servlet de façon à ce qu'elle tienne compte de la requête de l'utilisateur et qu'elle permette la modification du client.
3. Modifier à nouveau l'interface graphique, en cas de modification, il faut :
- Changer la légende affichée au niveau de la partie formulaire
- Afficher les données du client à modifier dans les 3 zones de texte du formulaire c. Mettre en évidence la ligne actuellement modifiée au niveau du tableau
- Quelle servlet s'activera sur un clic du bouton Valider ?
- Quelle méthode de cette servlet sera sollicitée ?
4. Modifier à nouveau la servlet afin d'effectuer la mise à jour dans la base de données et dans la collection lesNvxClients.
VI.Autres évolutions/Améliorations possibles
- suppression d'un client
- hachage du mot de passe
- sécurisation de l'application
- ajout favicon
- …