VIII. Exemple 06 - La session▲
VIII-A. La notion de session▲
Lorsqu'un navigateur client se connecte la première fois à une application web, il reçoit un jeton de session, une suite de caractères unique qu'il renvoie à chaque nouvelle requête qu'il fait à l'application web. Cela permet à celle-ci de reconnaître le navigateur client. A ce jeton de session, elle peut alors associer des données. Ces données appartiennent à un unique navigateur client. Ainsi, au fil des requêtes du navigateur client, se constitue une mémoire.

Ci-dessus, chaque utilisateur (navigateur) a sa propre mémoire qu'on appelle sa session. Cette mémoire est partagée par toutes les requêtes d'un même utilisateur. Il existe également une mémoire de plus haut niveau appelée mémoire de l'application. Cette mémoire est partagée par toutes les requêtes de tous les utilisateurs. Elle est en général en lecture seule.
VIII-B. Le projet Netbeans▲
Le projet [exemple-06] est obtenue par recopie du projet [exemple-05]. Nous allons changer quelques éléments pour
- bénéficier de la session de l'utilisateur.
- ajouter une nouvelle action [Effacer] [1] pour effacer le champ de saisie.
VIII-C. Configuration▲
Le fichier [struts.xml] évolue de la façon suivante :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- internationalisation -->
<constant name="struts.custom.i18n.resources" value="messages" />
<!-- package default -->
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<action name="index">
<result type="redirectAction">
<param name="actionName">Saisir</param>
<param name="namespace">/actions</param>
</result>
</action>
</package>
<!-- package actions -->
<package name="actions" namespace="/actions" extends="struts-default">
<action name="Saisir">
<result name="success">/vues/Saisie.jsp</result>
</action>
<action name="Confirmer" class="actions.Confirmer">
<result name="success">/vues/Confirmation.jsp</result>
</action>
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
</package>
</struts>
Les lignes 27-29 définissent une nouvelle action [Effacer] associée à une classe [Effacer]. La réponse à cette action est la vue [Saisie.jsp].
VIII-D. L'action [Confirmer]▲
Elle évolue comme suit :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Confirmer extends ActionSupport implements SessionAware{
// modèle
private String nom;
// session
private Map<String, Object> session;
// getters et setters
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
@Override
public void setSession(Map<String, Object> session) {
this.session=session;
}
@Override
public String execute(){
// on met le nom dans la session
session.put("nom",nom);
// navigation
return SUCCESS;
}
}
- ligne 7 : la classe [Confirmer] implémente l'interface SessionAware. Cette interface n'a qu'une méthode, la méthode setSession des lignes 25-27. Avant l'appel de la méthode execute, l'un des intercepteurs de la requête va injecter, via la méthode setSession, la session de l'utilisateur sous la forme d'un dictionnaire Map<String, Object> (ligne 25). Nous choisissons de mémoriser ce dictionnaire dans le champ session de la ligne 12.
- lignes 30-34 : la méthode execute de l'action. Lorsqu'elle s'exécute, le champ session a été initialisé par l'un des intercepteurs ainsi que le champ nom par un autre intercepteur. On utilise ce dictionnaire session pour y stocker le champ nom. Ainsi le nom va-t-il faire partie de la mémoire de l'utilisateur et être disponible à toutes les requêtes de celui-ci.
VIII-E. Les vues [Confirmation.jsp] et [Saisie.jsp]▲
La vue [Confirmation.jsp] reste inchangée. La vue [Saisie.jsp] évolue comme suit :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><s:text name="saisie.titre1"/></title>
</head>
<body>
<h1><s:text name="saisie.titre2"/></h1>
<s:form action="Confirmer">
<s:textfield key="saisie.libelle" name="nom" value="%{#attr['nom']}"/>
<s:submit key="saisie.valider" action="Confirmer"/>
<s:submit key="saisie.effacer" action="Effacer"/>
</s:form>
</body>
</html>
- ligne 12 : nous introduisons un attribut value à la balise <s:textfield>. Cet attribut fixe la valeur à afficher dans la zone de saisie. En l'absence de cet attribut, value = name. Ici, la valeur de l'attribut est une expression OGNL (Object-Graph Navigation Language) de la forme %{expression_à_évaluer}. Ici, l'expression à évaluer est #attr['nom']. L'attribut nom sera cherché dans l'action courante, la page, la requête, la session, l'application dans cet ordre. Comme l'action [Confirmer] met l'attribut nom dans la session, il sera trouvé là. C'est ce que montre la requête suivante :
En [1], le nom saisi a été ST. On sait que l'action [Confirmer] a mis ce nom dans la session. Le lien [2] nous mène à l'Url [3]. La vue [Saisie.jsp] est affichée. Pour le champ de saisie, l'attribut %{#attr['nom']} permet de retrouver le nom dans la session.
- ligne 14 : le bouton [Effacer] qui va déclencher l'exécution de l'action [Effacer] et l'affichage de la vue [Saisie.jsp]
2.
3.
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
VIII-F. L'action [Effacer]▲
Le code de l'action [Effacer] est le suivant :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Effacer extends ActionSupport implements SessionAware{
// session
private Map<String, Object> session;
@Override
public String execute(){
// on récupère le nom dans la session
String nom=(String)session.get("nom");
// on l'enlève de la session si besoin est
if(nom!=null){
session.remove("nom");
}
// navigation
return SUCCESS;
}
@Override
public void setSession(Map<String, Object> map) {
this.session=map;
}
}
- ligne 7 : la classe [Effacer] implémente l'interface [SessionAware] comme le faisait l'action [Confirmer].
- ligne 13 : l'action [Effacer] doit effacer le contenu du champ de saisie du nom dans la vue [Saisie.jsp]. On sait que cette vue va chercher ce nom dans la session. On doit donc enlever le nom de la session. C'est ce que fait la méthode execute.
Voyons ce que ça donne :
En [1], on veut effacer le champ de saisie. On clique sur le bouton [Effacer].
<s:submit key="saisie.effacer" action="Effacer"/>L'action [Effacer] va s'exécuter. En [2], on remarque que l'Url appelée a été celle de l'action [Confirmer]. Cela vient de la balise <s:form> du formulaire :
<s:form action="Confirmer">qui fait que le formulaire est posté à l'action [Confirmer]. Au clic sur le bouton [Effacer], le paramètre
action:Effacer=Effacer
a été posté à l'Url [/actions/Confirmer.action]. Struts utilise ce paramètre pour faire traiter les données postées par l'action [Effacer]. Celle-ci enlève le nom de la session. La page [Saisie.jsp] est la réponse de l'action [Effacer] :
2.
3.
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
Celle-ci qui affiche le nom de la session affiche alors une chaîne vide [3].
Nous avons écrit plusieurs exemples simples afin d'introduire des concepts importants de Struts 2 :
- l'internationalisation des pages
- l'injection de paramètres postés dans les champs des actions
- la notion de session
- l'articulation entre Actions et Vues
Avec ces concepts acquis, nous sommes capables maintenant d'aborder des exemples plus complexes. Nous commençons par présenter les différentes balises utilisables dans un formulaire.


