Skip to content

8. Exemplo 06 – A sessão

8.1. O conceito de sessão

Quando um navegador cliente se liga pela primeira vez a uma aplicação web, recebe um token de sessão, uma sequência única de caracteres que reenvia em cada nova solicitação que faz à aplicação web. Isto permite que esta reconheça o navegador cliente. A este token de sessão, a aplicação pode então associar dados. Estes dados pertencem a um único navegador cliente. Assim, à medida que o navegador do cliente envia pedidos, vai-se constituindo uma memória.

No exemplo acima, cada utilizador (navegador) tem a sua própria memória, a que se chama sessão. Esta memória é partilhada por todas as solicitações de um mesmo utilizador. Existe também uma memória de nível superior, denominada memória da aplicação. Esta memória é partilhada por todas as solicitações de todos os utilizadores. Em geral, é de leitura única.

8.2. O projeto NetBeans

O projeto [exemple-06] é obtido por cópia do projeto [exemple-05]. Vamos alterar alguns elementos para

  • tirar partido da sessão do utilizador.
  • adicionar uma nova ação [Effacer] [1] para limpar o campo de introdução de dados.

8.3. Configuration

O ficheiro [struts.xml] passa a ter o seguinte aspeto:


<?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>
  <!-- internacionalização -->
  <constant name="struts.custom.i18n.resources" value="messages" />
  <!-- pacote padrão -->
  <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>
  <!-- pacote de ações -->
  <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 [Effacer] associada a uma classe [Effacer]. A resposta a esta ação é a vista [Saisie.JSP].

8.4. A ação [Confirmer]

A evolução desta ação é a seguinte:


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;
  // sessão
  private Map<String, Object> session;
  
  // getters e 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(){
    // colocamos o nome na sessão
    session.put("nom",nom);
    // navegação
    return SUCCESS;
  }
  
}
  • linha 7: a classe [Confirmer] implementa a interface SessionAware. Esta interface tem apenas um método, o método setSession das linhas 25-27. Antes da chamada ao método execute, um dos interceptores da solicitação irá inserir, através do método setSession, a sessão do utilizador sob a forma de um dicionário Map<String, Object> (linha 25). Optamos por armazenar este dicionário no campo session da linha 12.
  • linhas 30-34: o método execute da ação. Quando é executado, o campo session foi inicializado por um dos interceptores, assim como o campo nom por outro interceptor. Utiliza-se este dicionário session para armazenar o campo nom. Desta forma, o nome passará a fazer parte da memória do utilizador e estará disponível para todas as suas consultas.

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: introduzimos um atributo value na baliza <s:textfield>.. Este atributo define o valor a apresentar na área de introdução de dados. Na ausência deste atributo, value = name. Aqui, o valor do atributo é uma expressão OGNL (Object-Graph Navigation Language) da forma %{expression_à_évaluer}. Aqui, a expressão a avaliar é #attr['nom']. O atributo nom será procurado na ação atual, na página, na consulta, na sessão e na aplicação, por esta ordem. Como a ação [Confirmer] insere o atributo nom na sessão, este será encontrado aí. É isso que mostra a seguinte consulta:

Na ação [1], o nome introduzido foi ST. Sabemos que a ação [Confirmer] inseriu esse nome na sessão. O link [2] leva-nos a URL e [3]. É apresentada a vista [Saisie.JSP]. No campo de introdução de dados, o atributo %{#attr['nom']} permite recuperar o nome da sessão.

  • linha 14: o botão [Effacer], que irá desencadear a execução da ação [Effacer] 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 [Effacer]

O código da ação [Effacer] é 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{
  
  // sessão
  private Map<String, Object> session;
  
  @Override
  public String execute(){
    // recuperar o nome da sessão
    String nom=(String)session.get("nom");
    // remove-se da sessão, se necessário
    if(nom!=null){
      session.remove("nom");
    }
    // navegação
    return SUCCESS;
  }

  @Override
  public void setSession(Map<String, Object> map) {
    this.session=map;
  }
}
  • linha 7: a classe [Effacer] implementa a interface [SessionAware], tal como fazia a ação [Confirmer].
  • linha 13: a ação [Effacer] deve apagar o conteúdo do campo de introdução do nome na vista [Saisie.JSP]. Sabemos que esta vista vai buscar esse nome à sessão. Por isso, temos de remover o nome da sessão. É isso que faz o método execute.

Vamos ver como fica:

Na [1], queremos apagar o campo de introdução. Clicamos no botão [Effacer].


<s:submit key="saisie.effacer" action="Effacer"/>

A ação [Effacer] será executada. Em [2], verifica-se que a ação URL chamada foi a da ação [Confirmer]. Isto deve-se à baliza <s:form> do formulário:


<s:form action="Confirmer">

que faz com que o formulário seja enviado para a ação [Confirmer]. Ao clicar no botão [Effacer], o parâmetro

action:Effacer=Effacer

foi enviado para a ação URL [/actions/Confirmer.action]. O Struts utiliza este parâmetro para que os dados enviados sejam processados pela ação [Effacer]. Esta ação remove o nome da sessão. A página [Saisie.JSP] é a resposta da ação [Effacer]:


<action name="Effacer" class="actions.Effacer">
      <result name="success">/vues/Saisie.JSP</result>
</action>

Esta ação, que apresenta o nome da sessão, exibe então uma cadeia vazia: [3].

Escrevemos vários exemplos simples para apresentar conceitos importantes do Struts 2:

  • a internacionalização das páginas
  • a injeção de parâmetros enviados nos campos das ações
  • o conceito de sessão
  • a articulação entre Ações e Visualizações

Com estes conceitos assimilados, estamos agora aptos a abordar exemplos mais complexos. Começamos por apresentar as diferentes tags que podem ser utilizadas num formulário.