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 de caracteres única que reenvía con cada nueva solicitud que realiza a la aplicación web. Esto permite a esta última reconocer el navegador cliente. A este token de sesió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 creando una memoria.
![]() |
En el ejemplo anterior, cada usuario (navegador) tiene su propia memoria, denominada sesión. Esta memoria es compartida por todas las solicitudes de un mismo usuario. También existe una memoria de nivel superior denominada 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 copiando el proyecto [exemple-05]. Vamos a cambiar algunos elementos para
- aprovechar la sesión del usuario.
- Añadir una nueva acción [Effacer] [1] para borrar el campo de entrada.
8.3. Configuration
El archivo [struts.xml] evoluciona 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 desarrolla 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 introduce 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-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. Cuando se ejecuta, 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 este modo, el nombre pasará a 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] evoluciona 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: introducimos un atributo value en la etiqueta <s:textfield>.. Este atributo establece el valor que se mostrará en el campo de entrada. En ausencia de este atributo, value = name. Aquí, 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 debe 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] establece el atributo nom en la sesión, se encontrará allí. Esto es lo que muestra la siguiente consulta:
![]() |
En [1], el nombre introducido fue ST. Sabemos que la acción [Confirmer] introdujo este nombre en la sesión. El enlace [2] nos lleva a la URL [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 va a buscar ese nombre en la sesión. Por lo tanto, debemos eliminar el nombre de la sesión. Eso es lo que hace el método execute.
Veamos qué pasa:
![]() |
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], observamos que la URL llamada ha sido la de la acción [Confirmer]. Esto se debe a la etiqueta <s:form> del formulario:
<s:form action="Confirmer">
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 ha enviado a la 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 introducir 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 articulación entre acciones y vistas
Una vez adquiridos estos conceptos, ya podemos abordar ejemplos más complejos. Comenzamos presentando las diferentes etiquetas que se pueden utilizar en un formulario.



