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.