Skip to content

16. Esempio 13 - Il contesto di un'azione

Questa applicazione ha lo scopo di dimostrare che un'azione ha accesso:

  • ai parametri della richiesta
  • agli attributi della richiesta
  • agli attributi della sessione dell’utente
 

16.1. Il progetto NetBeans

Il progetto NetBeans è il seguente:

  • in [1], la vista [Context.JSP]
  • in [2], l'azione [Action1.java] e il file di configurazione Struts [example.xml]

16.2. Configuration

La configurazione del progetto viene effettuata in [example.xml]:


<?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>
  • riga 8: la richiesta di URL [/example/Action1] provocherà l'istanziazione della classe [example.Action]. Poiché non viene specificato alcun metodo, verrà eseguito il metodo execute.
  • riga 9: è accettata una sola chiave. La chiave success porta alla visualizzazione della vista [Context.JSP].

L'architettura semplificata per l'elaborazione di una richiesta sarà la seguente:

La richiesta verrà elaborata da due elementi dell’applicazione web: l’azione [Action1] [1] e la vista [Context.JSP] [2]. Questi due elementi hanno accesso a dati di diversa natura:

  • dati di ambito Application, [3], c.a.d. Dati accessibili a tutte le richieste di tutti gli utenti. Sono quasi sempre in sola lettura. Spesso in questi dati si trova la configurazione iniziale dell’applicazione. In questo caso, [Action1] e [Context.JSP] hanno accesso a questi dati.
  • Dati con ambito Session, [4], c.a.d. Dati accessibili a tutte le richieste dello stesso utente. Sono in modalità lettura/scrittura. In questo caso, [Action1] utilizzerà la sessione in modalità lettura/scrittura, mentre [Context.JSP] la utilizzerà in modalità di sola lettura.
  • Dati con ambito Requête [5], accessibili a tutti gli elementi che elaborano la richiesta. In questo caso, [Action1] inserirà un dato in questa memoria e [Context.JSP] lo recupererà. I dati di ambito Richiesta consentono a un elemento N di trasmettere informazioni all’elemento N+1.
  • I parametri della richiesta [6] inviati dal client. Sono utilizzati in sola lettura dagli elementi che elaborano la richiesta.

16.3. L'azione [Action1]

Il codice della classe [Action1] è il seguente:


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 {

  // costruttore senza parametri
  public Action1() {
  }
  // Sessione, Richiesta, Parametri
  Map<String, Object> session;
  Map<String, Object> request;
  Map<String, String[]> parameters;

  @Override
  public String execute() {
    // elenco dei parametri
    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));
      }
    }
    // sessione
    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));
    // richiesta
    request.put("info1", "information1");
    // visualizzazione pagina JSP
    return SUCCESS;
  }

  // sessione
  public void setSession(Map<String, Object> session) {
    this.session = session;
  }

  // richiesta
  public void setRequest(Map<String, Object> request) {
    this.request = request;
  }

  // parametri
  public void setParameters(Map<String, String[]> parameters) {
    this.parameters = parameters;
  }
}
  • riga 10: la classe implementa le seguenti interfacce
    • SessionAware: per accedere al dizionario degli attributi della sessione (riga 16). Questa interfaccia ha un solo metodo, quello alla riga 46.
    • RequestAware: per accedere al dizionario degli attributi della richiesta (riga 17). Questa interfaccia ha un solo metodo, quello alla riga 51.
    • ParameterAware: per accedere al dizionario dei parametri della query (riga 18). Si noti che a una chiave (il nome del parametro) corrisponde un array di valori. Ciò è necessario per tenere conto dei campi di immissione che inviano più valori, come ad esempio un elenco a selezione multipla. L’interfaccia ParameterAware ha un solo metodo, quello alla riga 56.
  • riga 21: il metodo execute che viene eseguito quando si richiede l’azione [Action1]. Quando viene eseguito, gli intercettatori hanno già svolto il loro lavoro:
    • il metodo setParameters (riga 56) è stato chiamato e il dizionario parameters della riga 18 contiene tutti i parametri della richiesta.
    • è stato chiamato il metodo setSession (riga 46) e il dizionario session della riga 16 contiene tutti gli attributi della sessione.
    • è stato chiamato il metodo setRequest (riga 51) e il dizionario request della riga 17 contiene tutti gli attributi della richiesta.
  • righe 31-38: si scrive il valore associato alla chiave compteur nella sessione
  • righe 32-34: si cerca la chiave compteur nella sessione. Se non è presente, la si inserisce associandola al valore intero 0.
  • righe 35-37: si cerca la chiave compteur nella sessione, il suo valore viene incrementato e la chiave viene reinserita nella sessione.
  • riga 38: viene visualizzato il valore associato alla chiave compteur. Poiché l’incremento viene effettuato ad ogni richiesta sull’azione [Action1], si dovrebbe osservare un aumento del valore del contatore man mano che le richieste vengono effettuate.
  • riga 40: si inserisce nel dizionario degli attributi della richiesta un attributo con chiave info1 e valore information1. Gli attributi di una richiesta sono diversi dai suoi parametri. I parametri vengono inviati dal client dell’applicazione web. Gli attributi della richiesta consentono invece la comunicazione tra i diversi elementi dell’applicazione web che la elaborano. Pertanto, dopo l’esecuzione di [Action1], verrà visualizzata la vista [Context.JSP]. Vedremo che essa è in grado di recuperare gli attributi della richiesta.
  • riga 42: il metodo execute restituisce la chiave succes.

16.4. Il file dei messaggi

Il file [messages.properties] è il seguente:


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

16.5. La vista [Context.JSP]

La vista [Context.JSP] ha il compito di visualizzare:

  • alcuni parametri della richiesta
  • il valore della chiave compteur nella sessione
  • il valore della chiave info1 nella query

Il suo codice è il seguente:


<%@ 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>
  • righe 12-14: visualizzano tutti i valori associati al parametro nom
  • righe 15-17: visualizzano tutti i valori associati al parametro prenom
  • righe 18-20: visualizzano tutti i valori associati al parametro age
  • riga 22: visualizza il valore associato alla chiave compteur nella sessione
  • riga 24: visualizza il valore associato alla chiave info1 nella query

16.6. I test

  • in [1], Action1 viene richiesto senza parametri
  • in [2], [Context.JSP] non ha trovato parametri
  • in [3], [Context.JSP] ha trovato la chiave compteur nella sessione
  • in [4], [Context.JSP] ha trovato la chiave info1 nella query

Facciamo un altro test:

  • in [1], Action1 viene richiesto con parametri
  • in [2], [Context.JSP] visualizza questi parametri
  • in [3], [Context.JSP] ha trovato la chiave compteur nella sessione. Il contatore è stato correttamente incrementato di 1, dimostrando così che c’è stata effettivamente una memorizzazione tra le due richieste.
  • in [4], [Context.JSP] ha trovato la chiave info1 nella richiesta

Ricordiamo che il metodo [Action1.execute] scriveva sulla console del server web. Ecco un esempio:

1
2
3
4
5
6
7
Paramètres...
[prenom,y]
[prenom,y2]
[age,z]
[nom,x]
Session...
compteur=2

16.7. Conclusion

Ricordiamo i seguenti punti:

  • per memorizzare informazioni da condividere tra tutte le richieste di tutti gli utenti, si utilizzerà la memoria dell’applicazione. Ne mostreremo presto un esempio.
  • per memorizzare informazioni da condividere tra tutte le richieste dello stesso utente, si utilizzerà la sua sessione.
  • per memorizzare informazioni da condividere tra tutti gli elementi che elaborano una richiesta, si utilizzerà la memoria della richiesta.