8. Exemplo 06 – A Sessão
8.1. O conceito de sessão
Quando o navegador de um cliente se liga a uma aplicação web pela primeira vez, recebe um token de sessão, uma sequência única de caracteres que reenvia com cada novo pedido que faz à aplicação web. Isto permite que a aplicação web reconheça o navegador do cliente. A aplicação web pode então associar dados a este token de sessão. Estes dados pertencem a um único navegador de cliente. Assim, à medida que o navegador do cliente faz pedidos, vai-se acumulando uma memória.
![]() |
Conforme mostrado acima, cada utilizador (navegador) tem a sua própria memória, conhecida como sessão. Esta memória é partilhada por todas as solicitações do mesmo utilizador. Existe também uma memória de nível superior chamada memória da aplicação. Esta memória é partilhada por todas as solicitações de todos os utilizadores. Geralmente, é de leitura apenas.
8.2. O Projeto NetBeans
![]() |
O projeto [example-06] é criado a partir da cópia do projeto [example-05]. Iremos alterar alguns elementos para
- tirar partido da sessão do utilizador.
- Adicione uma nova ação [Limpar] [1] para limpar o campo de entrada.
8.3. Configuração
O ficheiro [struts.xml] é alterado da seguinte forma:
<?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>
<!-- internationalization -->
<constant name="struts.custom.i18n.resources" value="messages" />
<!-- default package -->
<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>
<!-- equity package -->
<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>
As linhas 27–29 definem uma nova ação [Delete] associada a uma classe [Delete]. A resposta a esta ação é a vista [Input.jsp].
8.4. A ação [Confirm]
Evolui da seguinte forma:
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Confirmer extends ActionSupport implements SessionAware{
// model
private String nom;
// session
private Map<String, Object> session;
// getters and setters
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(){
// put the name in the session
session.put("nom",nom);
// navigation
return SUCCESS;
}
}
- Linha 7: A classe [Confirm] implementa a interface SessionAware. Esta interface tem apenas um método, o método setSession nas linhas 25–27. Antes de o método execute ser chamado, um dos interceptores de pedidos irá injetar, através do método setSession, a sessão do utilizador na forma de um dicionário Map<String, Object> (linha 25). Optamos por armazenar este dicionário no campo session na linha 12.
- Linhas 30–34: o método `execute` da ação. Quando este é executado, o campo session já foi inicializado por um dos interceptores e o campo name por outro interceptor. Utilizamos este dicionário de sessão para armazenar o campo name. Assim, o nome fará parte da sessão do utilizador e estará disponível para todos os seus pedidos.
8.5. As vistas [Confirmation.jsp] e [Saisie.jsp]
A vista [Confirmation.jsp] permanece inalterada. A vista [Saisie.jsp] sofre as seguintes alterações:
<%@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>
- Linha 12: Adicionamos um atributo `value` à tag `<s:textfield>`. Este atributo define o valor a ser exibido no campo de entrada. Se este atributo for omitido, `value` assume por predefinição o valor `name`. Aqui, o valor do atributo é uma expressão OGNL (Object-Graph Navigation Language) na forma `%{expressão_a_avaliar}`. Aqui, a expressão a ser avaliada é #attr['name']. O atributo name será procurado na ação atual, na página, na solicitação, na sessão e na aplicação, nessa ordem. Como a ação [Confirm] coloca o atributo name na sessão, ele será encontrado lá. Isto é demonstrado pela seguinte solicitação:
![]() |
Em [1], o nome introduzido foi ST. Sabemos que a ação [Confirm] colocou este nome na sessão. O link [2] leva-nos para o URL [3]. A vista [Saisie.jsp] é apresentada. Para o campo de entrada, o atributo %{#attr['name']} recupera o nome da sessão.
- Linha 14: o botão [Limpar], que aciona a execução da ação [Limpar] e a exibição da vista [Saisie.jsp]
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
8.6. A ação [Apagar]
O código para a ação [Apagar] é o seguinte:
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Effacer extends ActionSupport implements SessionAware{
// session
private Map<String, Object> session;
@Override
public String execute(){
// retrieve the name from the session
String nom=(String)session.get("nom");
// remove it from the session if necessary
if(nom!=null){
session.remove("nom");
}
// navigation
return SUCCESS;
}
@Override
public void setSession(Map<String, Object> map) {
this.session=map;
}
}
- Linha 7: A classe [Delete] implementa a interface [SessionAware], tal como a ação [Confirm] fez.
- linha 13: A ação [Delete] deve limpar o conteúdo do campo de entrada de nome na vista [Input.jsp]. Sabemos que esta vista recupera este nome da sessão. Devemos, portanto, remover o nome da sessão. É isso que o método execute faz.
Vamos ver como isto funciona:
![]() |
Em [1], queremos limpar o campo de entrada. Clicamos no botão [Limpar].
<s:submit key="saisie.effacer" action="Effacer"/>
A ação [Limpar] será executada. Em [2], verificamos que o URL chamado foi o da ação [Confirmar]. Isto deve-se à tag <s:form> no formulário:
<s:form action="Confirmer">
o que faz com que o formulário seja enviado para a ação [Confirm]. Quando se clica no botão [Limpar], o parâmetro
action:Delete=Delete
foi enviado para o URL [/actions/Confirm.action]. O Struts utiliza este parâmetro para processar os dados enviados pela ação [Delete]. Esta ação remove o nome da sessão. A página [Input.jsp] é a resposta à ação [Delete]:
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
Esta, que exibe o nome da sessão, exibe em seguida uma string vazia [3].
Escrevemos vários exemplos simples para apresentar conceitos importantes do Struts 2:
- internacionalização de páginas
- injeção de parâmetros enviados em campos de ação
- o conceito de sessões
- a relação entre Ações e Visualizações
Agora que dominamos estes conceitos, estamos prontos para abordar exemplos mais complexos. Começaremos por apresentar as várias tags que podem ser utilizadas num formulário.



