Skip to content

16. Ejemplo 13: el contexto de una acción

Esta aplicación tiene como objetivo mostrar que una acción tiene acceso:

  • a los parámetros de la consulta
  • a los atributos de la solicitud
  • a los atributos de la sesión del usuario

Image

16.1. El proyecto NetBeans

El proyecto NetBeans es el siguiente:

  • en [1], la vista [Context.jsp]
  • en [2], la acción [Action1.java] y el archivo de configuración de Struts [example.xml]

16.2. Configuration

La configuración del proyecto se realiza en [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>
  • línea 8: la solicitud de la URL [/example/Action1] provocará la instanciación de la clase [example.Action]. Como no se especifica ningún método, se ejecutará el método execute.
  • línea 9: solo se acepta una clave. La clave success da lugar a la visualización de la vista [Context.jsp].

La arquitectura simplificada para el procesamiento de una solicitud será la siguiente:

La solicitud será procesada por dos elementos de la aplicación web: la acción [Action1] [1] y la vista [Context.jsp] [2]. Estos dos elementos tienen acceso a datos de diferente naturaleza:

  • datos de ámbito Application, [3] y c.a.d. Datos accesibles a todas las solicitudes de todos los usuarios. Casi siempre son de solo lectura. A menudo, en estos datos se encuentra la configuración inicial de la aplicación. En este caso, [Action1] y [Context.jsp] tienen acceso a estos datos.
  • Datos de ámbito Session, [4], c.a.d. Datos accesibles a todas las solicitudes de un mismo usuario. Son de lectura/escritura. Aquí, [Action1] utilizará la sesión en modo lectura/escritura, mientras que [Context.jsp] la utilizará en modo lectura.
  • Datos de ámbito Requête [5], accesibles para todos los elementos que procesan la solicitud. Aquí, [Action1] almacenará un dato en esta memoria y [Context.jsp] lo recuperará. Los datos de ámbito «Consulta» permiten que un elemento N transmita información al elemento N+1.
  • Los parámetros de la solicitud [6] enviados por el cliente. Son de solo lectura para los elementos que procesan la solicitud.

16.3. La acción [Action1]

El código de la clase [Action1] es el siguiente:


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 {

  // constructor sin parámetros
  public Action1() {
  }
  // Sesión, Solicitud, Parámetros
  Map<String, Object> session;
  Map<String, Object> request;
  Map<String, String[]> parameters;

  @Override
  public String execute() {
    // lista de parámetros
    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));
      }
    }
    // sesión
    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));
    // solicitud
    request.put("info1", "information1");
    // visualización de página JSP
    return SUCCESS;
  }

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

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

  // parámetros
  public void setParameters(Map<String, String[]> parameters) {
    this.parameters = parameters;
  }
}
  • línea 10: la clase implementa las siguientes interfaces
  • SessionAware: para acceder al diccionario de atributos de la sesión (línea 16). Esta interfaz solo tiene un método, el de la línea 46.
  • RequestAware: para acceder al diccionario de atributos de la consulta (línea 17). Esta interfaz solo tiene un método, el de la línea 51.
  • ParameterAware: para acceder al diccionario de parámetros de la consulta (línea 18). Cabe destacar que a cada clave (el nombre del parámetro) le corresponde una tabla de valores. Esto es necesario para tener en cuenta los campos de entrada que envían varios valores, como por ejemplo una lista de selección múltiple. La interfaz ParameterAware solo tiene un método, el de la línea 56.
  • línea 21: el método execute, que se ejecuta cuando se solicita la acción [Action1]. Cuando se ejecuta, los interceptores ya han hecho su trabajo:
  • se ha llamado al método setParameters (línea 56) y el diccionario parameters de la línea 18 contiene todos los parámetros de la solicitud.
  • Se ha llamado al método setSession (línea 46) y el diccionario session de la línea 16 contiene todos los atributos de la sesión.
  • Se ha llamado al método setRequest (línea 51) y el diccionario request de la línea 17 contiene todos los atributos de la solicitud.
  • líneas 31-38: se escribe el valor asociado a la clave compteur en la sesión
  • líneas 32-34: se busca la clave compteur en la sesión. Si no se encuentra, se añade asociada al valor entero 0.
  • líneas 35-37: se busca la clave compteur en la sesión, se incrementa su valor y, a continuación, la clave se vuelve a guardar en la sesión.
  • línea 38: se muestra el valor asociado a la clave compteur. Dado que el incremento se realiza en cada consulta sobre la acción [Action1], deberíamos ver cómo aumenta el valor del contador a medida que se realizan las consultas.
  • línea 40: se inserta en el diccionario de atributos de la solicitud un atributo con la clave info1 y el valor information1. Los atributos de una solicitud son distintos de sus parámetros. Los parámetros son enviados por el cliente de la aplicación web. Los atributos de la solicitud, por su parte, permiten la comunicación entre los diferentes elementos de la aplicación web que la procesan. Así, tras la ejecución de [Action1], se mostrará la vista [Context.jsp]. Veremos que es capaz de recuperar los atributos de la solicitud.
  • Línea 42: el método execute devuelve la clave succes.

16.4. El archivo de mensajes

El archivo [messages.properties] es el siguiente:


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] tiene como función mostrar:

  • algunos parámetros de la consulta
  • el valor de la clave compteur en la sesión
  • el valor de la clave info1 en la consulta

Su código es el siguiente:


<%@ 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>
  • líneas 12-14: muestran todos los valores asociados al parámetro nom
  • líneas 15-17: muestran todos los valores asociados al parámetro prenom
  • líneas 18-20: muestran todos los valores asociados al parámetro age
  • línea 22: muestra el valor asociado a la clave compteur en la sesión
  • línea 24: muestra el valor asociado a la clave info1 en la consulta

16.6. Las pruebas

  • en [1], Action1 se solicita sin parámetros
  • en [2], [Context.jsp] no ha encontrado parámetros
  • en [3], [Context.jsp] ha encontrado la clave compteur en la sesión
  • en [4], [Context.jsp] ha encontrado la clave info1 en la consulta

Hagamos otra prueba:

  • en [1], se solicita Action1 con parámetros
  • en [2], [Context.jsp] muestra estos parámetros
  • en [3], [Context.jsp] ha encontrado la clave compteur en la sesión. El contador se ha incrementado correctamente en 1, lo que demuestra que se ha producido el almacenamiento entre las dos solicitudes.
  • En [4], [Context.jsp] ha encontrado la clave info1 en la solicitud

Recordemos que el método [Action1.execute] escribía en la consola del servidor web. He aquí un ejemplo:

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

16.7. Conclusion

Recordaremos los siguientes puntos:

  • para almacenar información que deben compartir todas las solicitudes de todos los usuarios, se utilizará la memoria de la aplicación. Pronto mostraremos un ejemplo.
  • Para almacenar información que deben compartir todas las solicitudes de un mismo usuario, se utilizará la sesión de este.
  • Para almacenar información que deben compartir todos los elementos que procesan una solicitud, se utilizará la memoria de la solicitud.