XVI. Exemple 13 - le contexte d'une action▲
Cette application vise à montrer qu'une action a accès :
- aux paramètres de la requête
- aux attributs de la requête
- aux attributs de la session de l'utilisateur
XVI-A. Le projet Netbeans▲
Le projet Netbeans est le suivant :
- en [1], la vue [Context.jsp]
- en [2], l'action [Action1.java] et le fichier de configuration Struts [example.xml]
XVI-B. Configuration▲
La configuration du projet est faite dans [example.xml] :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<?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>
<package
name
=
"example"
namespace
=
"/example"
extends
=
"struts-default"
>
<action
name
=
"Action1"
class
=
"example.Action1"
>
<result
name
=
"success"
>
/example/Context.jsp</result>
</action>
</package>
</struts>
- ligne 8 : la demande de l'Url [/example/Action1] va provoquer l'instanciation de la classe [example.Action]. Comme aucune méthode n'est précisée, ce sera la méthode execute qui sera exécutée.
- ligne 9 : une seule clé est acceptée. La clé success conduit à l'affichage de la vue [Context.jsp].
L'architecture simplifiée de traitement d'une requête va être la suivante :
La requête va être traitée par deux éléments de l'application web : l'action [Action1] [1] et la vue [Context.jsp] [2]. Ces deux éléments ont accès à des données de différentes natures :
- des données de portée Application [3], c.a.d. des données accessibles à toutes les requêtes de tous les utilisateurs. Elles sont quasiment tout le temps en lecture seule. On trouve souvent dans ces données, la configuration initiale de l'application. Ici [Action1] et [Context.jsp] ont accès à ces données.
- des données de portée Session [4], c.a.d. des données accessibles à toutes les requêtes d'un même utilisateur. Elles sont en lecture / écriture. Ici [Action1] utilisera la session en lecture / écriture, alors que [Context.jsp] l'utilisera en lecture.
- des données de portée Requête [5], accessibles à tous les éléments qui traitent la requête. Ici [Action1] mettra une donnée dans cette mémoire et [Context.jsp] la récupèrera. Les données de portée Requête permettent à un élément N de transmettre de l'information à l'élément N+1.
- les paramètres de la requête [6] envoyés par le client. Ils sont utilisés en lecture seule par les éléments qui traitent la requête.
XVI-C. L'action [Action1]▲
Le code de la classe [Action1] est la 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.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
package
example;
import
com.opensymphony.xwork2.ActionSupport;
import
java.util.Map;
import
java.util.Set;
import
org.apache.struts2.interceptor.ParameterAware;
import
org.apache.struts2.interceptor.RequestAware;
import
org.apache.struts2.interceptor.SessionAware;
public
class
Action1 extends
ActionSupport implements
SessionAware, RequestAware, ParameterAware {
// constructeur sans paramètre
public
Action1
(
) {
}
// Session, Request, Parametres
Map<
String, Object>
session;
Map<
String, Object>
request;
Map<
String, String[]>
parameters;
@Override
public
String execute
(
) {
// liste des paramètres
System.out.println
(
"Paramètres..."
);
Set<
String>
clés =
parameters.keySet
(
);
for
(
String clé : clés) {
for
(
String valeur : parameters.get
(
clé)) {
System.out.println
(
String.format
(
"[%s,%s]"
, clé, valeur));
}
}
// session
System.out.println
(
"Session..."
);
if
(
session.get
(
"compteur"
) ==
null
) {
session.put
(
"compteur"
, new
Integer
(
0
));
}
Integer compteur =
(
Integer) session.get
(
"compteur"
);
compteur =
compteur +
1
;
session.put
(
"compteur"
, compteur);
System.out.println
(
String.format
(
"compteur=%s"
, compteur));
// requête
request.put
(
"info1"
, "information1"
);
// affichage page JSP
return
SUCCESS;
}
// session
public
void
setSession
(
Map<
String, Object>
session) {
this
.session =
session;
}
// requête
public
void
setRequest
(
Map<
String, Object>
request) {
this
.request =
request;
}
// paramètres
public
void
setParameters
(
Map<
String, String[]>
parameters) {
this
.parameters =
parameters;
}
}
- ligne 10 : la classe implémente les interfaces suivantes
- SessionAware : pour avoir accès au dictionnaire des attributs de la session (ligne 16). Cette interface n'a qu'une méthode, celle de la ligne 46.
- RequestAware : pour avoir accès au dictionnaire des attributs de la requête (ligne 17). Cette interface n'a qu'une méthode, celle de la ligne 51.
- ParameterAware : pour avoir accès au dictionnaire des paramètres de la requête (ligne 18). On remarquera qu'à une clé (le nom du paramètre) correspond un tableau de valeurs. Ceci est nécessaire pour prendre en compte les zones de saisie qui postent plusieurs valeurs comme par exemple une liste à sélection multiple. L'interface ParameterAware n'a qu'une méthode, celle de la ligne 56.
- ligne 21 : la méthode execute qui est exécutée lorsqu'on demande l'action [Action1]. Lorsqu'elle s'exécute, les intercepteurs ont fait leur travail :
- la méthode setParameters (ligne 56) a été appelée et le dictionnaire parameters de la ligne 18 contient tous les paramètres de la requête.
- la méthode setSession (ligne 46) a été appelée et le dictionnaire session de la ligne 16 contient tous les attributs de la session.
- la méthode setRequest (ligne 51) a été appelée et le dictionnaire request de la ligne 17 contient tous les attributs de la requête.
- lignes 31-38 : on écrit la valeur associée à la clé compteur dans la session
- lignes 32-34 : la clé compteur est cherchée dans la session. Si elle ne s'y trouve pas, on l'y met associée à la valeur entière 0.
- lignes 35-37 : la clé compteur est cherchée dans la session, sa valeur est incrémentée puis la clé est remise dans la session.
- ligne 38 : la valeur associée à la clé compteur est affichée. L'incrément étant fait à chaque requête sur l'action [Action1], on devrait voir la valeur du compteur augmenter au fil des requêtes.
- ligne 40 : on insère dans le dictionnaire des attributs de la requête un attribut de clé info1 et de valeur information1. Les attributs d'une requête sont différents de ses paramètres. Les paramètres sont envoyés par le client de l'application web. Les attributs de la requête eux permettent la communication entre les différents éléments de l'application web qui la traitent. Ainsi, après l'exécution de [Action1], la vue [Context.jsp] va être affichée. Nous allons voir qu'elle est capable de récupérer les attributs de la requête.
- ligne 42 : la méthode execute rend la clé succes.
XVI-D. Le fichier des messages▲
Le fichier [messages.properties] est le suivant :
2.
3.
4.
5.
Context.titre=Contexte de l''action
Context.message=Contexte de l''action
Context.parameters=Param\u00E8tres de l''action
Context.session=Elements de session
Context.request=Attributs de requ\u00EAte
XVI-E. La vue [Context.jsp]▲
La vue [Context.jsp] a pour rôle d'afficher :
- certains paramètres de la requête
- la valeur de la clé compteur dans la session
- la valeur de la clé info1 dans la requête
Son code 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.
<%@
page
contentType
=
"text/html; charset=UTF-8"
pageEncoding=
"UTF-8"
%>
<%@
taglib
prefix
=
"s"
uri
=
"/struts-tags"
%>
<html>
<head>
<title><s
:
text
name=
"Context.titre"
/></title>
<s
:
head
/>
</head>
<body background=
"<s:url value="
/ressources/standard.jpg
"/>"
>
<h2><s
:
text
name=
"Context.message"
/></h2>
<h3><s
:
text
name=
"Context.parameters"
/></h3>
<s
:
iterator
value=
"#parameters['nom']"
var=
"nom"
>
nom : <s
:
property
value=
"nom"
/><br/>
</s
:
iterator
>
<s
:
iterator
value=
"#parameters['prenom']"
var=
"prenom"
>
prenom : <s
:
property
value=
"prenom"
/><br/>
</s
:
iterator
>
<s
:
iterator
value=
"#parameters['age']"
var=
"age"
>
âge : <s
:
property
value=
"age"
/><br/>
</s
:
iterator
>
<h3><s
:
text
name=
"Context.session"
/></h3>
compteur : <s
:
property
value=
"#session['compteur']"
/>
<h3><s
:
text
name=
"Context.request"
/></h3>
info1 : <s
:
property
value=
"#request['info1']"
/>
</body>
</html>
- lignes 12-14 : affichent toutes les valeurs associées au paramètre nom
- lignes 15-17 : affichent toutes les valeurs associées au paramètre prenom
- lignes 18-20 : affichent toutes les valeurs associées au paramètre age
- ligne 22 : affiche la valeur associée à la clé compteur dans la session
- ligne 24 : affiche la valeur associée à la clé info1 dans la requête
XVI-F. Les tests▲
- en [1], Action1 est demandée sans paramètres
- en [2], [Context.jsp] n'a pas trouvé de paramètres
- en [3], [Context.jsp] a trouvé la clé compteur dans la session
- en [4], [Context.jsp] a trouvé la clé info1 dans la requête
- en [1], Action1 est demandée avec des paramètres
- en [2], [Context.jsp] affiche ces paramètres
- en [3], [Context.jsp] a trouvé la clé compteur dans la session. Le compteur a bien été incrémenté de 1 montrant par là qu'il y bien eu mémorisation entre les deux requêtes.
- en [4], [Context.jsp] a trouvé la clé info1 dans la requête
On se rappelle que la méthode [Action1.execute] écrivait sur la console du serveur web. Voilà un exemple :
2.
3.
4.
5.
6.
7.
Paramètres...
[prenom,y]
[prenom,y2]
[age,z]
[nom,x]
Session...
compteur=2
XVI-G. Conclusion▲
On se rappellera les points suivants :
- pour mémoriser des informations à partager par toutes les requêtes de tous les utilisateurs, on utilisera la mémoire de l'application. Nous allons en montrer un exemple bientôt.
- pour mémoriser des informations à partager par toutes les requêtes d'un même utilisateur, on utilisera la session de celui-ci.
- pour mémoriser des informations à partager par tous les éléments traitant une requête, on utilisera la mémoire de la requête.