Introduction à STRUTS2 par l'exemple


précédentsommairesuivant

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

Image non disponible

XVI-A. Le projet Netbeans

Le projet Netbeans est le suivant :

Image non disponible

  • 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] :

 
Sélectionnez
1.
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 :

Image non disponible

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 :

 
Sélectionnez
1.
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 :

 
Sélectionnez
1.
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 :

 
Sélectionnez
1.
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

Image non disponible

  • 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

Faisons un autre test :

Image non disponible

  • 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 :

 
Sélectionnez
1.
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.

précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2012 Serge Tahe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.