8. Ejemplo 06 – La sesión
8.1. El concepto de sesión
Cuando un navegador cliente se conecta por primera vez a una aplicación web, recibe un token de sesión, una secuencia única de caracteres que reenvía con cada nueva solicitud que realiza a la aplicación web. Esto le permite a la aplicación reconocer al navegador cliente. A este token de sesión, la aplicación puede asociarle datos. Estos datos pertenecen a un único navegador cliente. De este modo, a medida que el navegador cliente realiza solicitudes, se va formando una memoria.
![]() |
Como se muestra arriba, cada usuario (navegador) tiene su propia memoria, que se denomina «sesión». Esta memoria es compartida por todas las solicitudes de un mismo usuario. También existe una memoria de nivel superior llamada «memoria de la aplicación». Esta memoria es compartida por todas las solicitudes de todos los usuarios. Por lo general, es de solo lectura.
8.2. El proyecto NetBeans
![]() |
El proyecto [exemple-06] se obtiene al clonar el proyecto [exemple-05]. Vamos a modificar algunos elementos para
- aprovechar la sesión del usuario.
- agregar una nueva acción [Effacer] [1] para borrar el campo de entrada.
8.3. Configuration
El archivo [struts.xml] queda de la siguiente manera:
<?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>
<!-- internacionalización -->
<constant name="struts.custom.i18n.resources" value="messages" />
<!-- paquete predeterminado -->
<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>
<!-- paquete de acciones -->
<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>
Las líneas 27-29 definen una nueva acción [Effacer] asociada a una clase [Effacer]. La respuesta a esta acción es la vista [Saisie.JSP].
8.4. La acción [Confirmer]
Se modifica de la siguiente manera:
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Confirmer extends ActionSupport implements SessionAware{
// modelo
private String nom;
// sesión
private Map<String, Object> session;
// getter y setter
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(){
// se guarda el nombre en la sesión
session.put("nom",nom);
// navegación
return SUCCESS;
}
}
- línea 7: la clase [Confirmer] implementa la interfaz SessionAware. Esta interfaz solo tiene un método, el método setSession de las líneas 25 a 27. Antes de llamar al método execute, uno de los interceptores de la solicitud inyectará, a través del método setSession, la sesión del usuario en forma de un diccionario Map<String, Object> (línea 25). Decidimos almacenar este diccionario en el campo session de la línea 12.
- Líneas 30-34: el método execute de la acción. Al ejecutarse, el campo session ha sido inicializado por uno de los interceptores, así como el campo nom por otro interceptor. Se utiliza este diccionario session para almacenar en él el campo nom. De esta manera, el nombre formará parte de la memoria del usuario y estará disponible para todas sus consultas.
8.5. Las vistas [Confirmation.JSP] y [Saisie.JSP]
La vista [Confirmation.JSP] permanece sin cambios. La vista [Saisie.JSP] cambia de la siguiente manera:
<%@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>
- línea 12: agregamos un atributo value a la etiqueta <s:textfield>.. Este atributo establece el valor que se mostrará en el campo de entrada. Si no se incluye este atributo, value = name. En este caso, el valor del atributo es una expresión OGNL (Object-Graph Navigation Language) de la forma %{expression_à_évaluer}. En este caso, la expresión que se evaluará es #attr['nom']. El atributo nom se buscará en la acción actual, la página, la consulta, la sesión y la aplicación, en ese orden. Dado que la acción [Confirmer] coloca el atributo nom en la sesión, se encontrará allí. Esto es lo que muestra la siguiente consulta:
![]() |
En [1], el nombre ingresado fue ST. Sabemos que la acción [Confirmer] colocó este nombre en la sesión. El enlace [2] nos lleva a URL y [3]. Se muestra la vista [Saisie.JSP]. Para el campo de entrada, el atributo %{#attr['nom']} permite recuperar el nombre de la sesión.
- línea 14: el botón [Effacer], que activará la ejecución de la acción [Effacer] y la visualización de la vista [Saisie.JSP]
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.JSP</result>
</action>
8.6. La acción [Effacer]
El código de la acción [Effacer] es el siguiente:
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Effacer extends ActionSupport implements SessionAware{
// sesión
private Map<String, Object> session;
@Override
public String execute(){
// se recupera el nombre de la sesión
String nom=(String)session.get("nom");
// se elimina de la sesión si es necesario
if(nom!=null){
session.remove("nom");
}
// navegación
return SUCCESS;
}
@Override
public void setSession(Map<String, Object> map) {
this.session=map;
}
}
- línea 7: la clase [Effacer] implementa la interfaz [SessionAware], al igual que lo hacía la acción [Confirmer].
- línea 13: la acción [Effacer] debe borrar el contenido del campo de entrada del nombre en la vista [Saisie.JSP]. Sabemos que esta vista obtiene ese nombre de la sesión. Por lo tanto, debemos eliminar el nombre de la sesión. Eso es lo que hace el método execute.
Veamos cómo queda:
![]() |
En [1], queremos borrar el campo de entrada. Hacemos clic en el botón [Effacer].
<s:submit key="saisie.effacer" action="Effacer"/>
Se ejecutará la acción [Effacer]. En [2], se observa que la acción URL que se invocó fue la de la acción [Confirmer]. Esto se debe a la etiqueta <s:form> del formulario:
<s:form action="Confirmer">
lo que hace que el formulario se envíe a la acción [Confirmer]. Al hacer clic en el botón [Effacer], el parámetro
action:Effacer=Effacer
se envió a la acción URL [/actions/Confirmer.action]. Struts utiliza este parámetro para que la acción [Effacer] procese los datos enviados. Esta acción elimina el nombre de la sesión. La página [Saisie.JSP] es la respuesta de la acción [Effacer]:
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.JSP</result>
</action>
Esta, que muestra el nombre de la sesión, muestra entonces una cadena vacía: [3].
Hemos escrito varios ejemplos sencillos para presentar conceptos importantes de Struts 2:
- la internacionalización de las páginas
- la inyección de parámetros enviados en los campos de las acciones
- el concepto de sesión
- la relación entre acciones y vistas
Una vez adquiridos estos conceptos, ya estamos listos para abordar ejemplos más complejos. Comenzamos presentando las diferentes etiquetas que se pueden utilizar en un formulario.



