Skip to content

16. Exemplo 13 — o contexto de uma ação

Esta aplicação tem como objetivo mostrar que uma ação tem acesso:

  • aos parâmetros da consulta
  • aos atributos da solicitação
  • aos atributos da sessão do usuário
 

16.1. O projeto NetBeans

O projeto NetBeans é o seguinte:

  • em [1], a visualização [Context.JSP]
  • em [2], a ação [Action1.java] e o arquivo de configuração do Struts [example.xml]

16.2. Configuration

A configuração do projeto é feita em [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>
  • linha 8: a solicitação de URL [/example/Action1] provocará a instanciação da classe [example.Action]. Como nenhum método foi especificado, será executado o método execute.
  • linha 9: apenas uma chave é aceita. A chave success leva à exibição da visualização [Context.JSP].

A arquitetura simplificada para o processamento de uma solicitação será a seguinte:

A solicitação será processada por dois elementos da aplicação web: a ação [Action1] [1] e a visualização [Context.JSP] [2]. Esses dois elementos têm acesso a dados de diferentes tipos:

  • dados de escopo Application, [3] e c.a.d. Dados acessíveis a todas as solicitações de todos os usuários. Eles são, quase sempre, somente para leitura. Frequentemente, nesses dados, encontra-se a configuração inicial do aplicativo. Aqui, [Action1] e [Context.JSP] têm acesso a esses dados.
  • Dados de escopo Session, [4] e c.a.d. São dados acessíveis a todas as solicitações de um mesmo usuário. Estão em modo de leitura/gravação. Aqui, [Action1] utilizará a sessão em modo de leitura/gravação, enquanto [Context.JSP] a utilizará em modo de leitura.
  • Dados de escopo Requête e [5], acessíveis a todos os elementos que processam a consulta. Aqui, [Action1] inserirá um dado nessa memória e [Context.JSP] o recuperará. Os dados de escopo “Requisição” permitem que um elemento N transmita informações ao elemento N+1.
  • Os parâmetros da solicitação [6] enviados pelo cliente. Eles são utilizados apenas para leitura pelos elementos que processam a solicitação.

16.3. A ação [Action1]

O código da classe [Action1] é o seguinte:


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 {

  // construtor sem parâmetros
  public Action1() {
  }
  // Sessão, Solicitação, 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));
      }
    }
    // sessão
    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));
    // solicitação
    request.put("info1", "information1");
    // exibição da página JSP
    return SUCCESS;
  }

  // sessão
  public void setSession(Map<String, Object> session) {
    this.session = session;
  }

  // solicitação
  public void setRequest(Map<String, Object> request) {
    this.request = request;
  }

  // parâmetros
  public void setParameters(Map<String, String[]> parameters) {
    this.parameters = parameters;
  }
}
  • linha 10: a classe implementa as seguintes interfaces
    • SessionAware: para acessar o dicionário de atributos da sessão (linha 16). Essa interface possui apenas um método, o da linha 46.
    • RequestAware: para acessar o dicionário de atributos da consulta (linha 17). Essa interface possui apenas um método, o da linha 51.
    • ParameterAware: para acessar o dicionário de parâmetros da consulta (linha 18). Observe-se que a cada chave (o nome do parâmetro) corresponde uma matriz de valores. Isso é necessário para levar em conta os campos de entrada que enviam vários valores, como, por exemplo, uma lista de seleção múltipla. A interface ParameterAware possui apenas um método, o da linha 56.
  • linha 21: o método execute, que é executado quando se solicita a ação [Action1]. Quando ele é executado, os interceptadores já tiveram de cumprir sua função:
    • o método setParameters (linha 56) foi chamado e o dicionário parameters da linha 18 contém todos os parâmetros da solicitação.
    • o método setSession (linha 46) foi chamado e o dicionário session da linha 16 contém todos os atributos da sessão.
    • O método setRequest (linha 51) foi chamado e o dicionário request da linha 17 contém todos os atributos da solicitação.
  • linhas 31-38: grava-se o valor associado à chave compteur na sessão
  • linhas 32-34: a chave compteur é procurada na sessão. Se não for encontrada, ela é inserida na sessão associada ao valor inteiro 0.
  • linhas 35-37: a chave compteur é procurada na sessão, seu valor é incrementado e, em seguida, a chave é reinserida na sessão.
  • linha 38: o valor associado à chave compteur é exibido. Como o incremento é feito a cada consulta à ação [Action1], devemos observar o valor do contador aumentar à medida que as consultas são realizadas.
  • linha 40: insere-se no dicionário de atributos da solicitação um atributo com a chave info1 e o valor information1. Os atributos de uma solicitação são diferentes de seus parâmetros. Os parâmetros são enviados pelo cliente do aplicativo web. Os atributos da solicitação, por sua vez, permitem a comunicação entre os diferentes elementos da aplicação web que a processam. Assim, após a execução de [Action1], a visualização [Context.JSP] será exibida. Veremos que ela é capaz de recuperar os atributos da solicitação.
  • linha 42: o método execute retorna a chave succes.

16.4. O arquivo de mensagens

O arquivo [messages.properties] é o seguinte:


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. A visualização [Context.JSP]

A visualização [Context.JSP] tem como função exibir:

  • alguns parâmetros da consulta
  • o valor da chave compteur na sessão
  • o valor da chave info1 na consulta

Seu código é o seguinte:


<%@ 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>
  • linhas 12-14: exibem todos os valores associados ao parâmetro nom
  • linhas 15-17: exibem todos os valores associados ao parâmetro prenom
  • linhas 18-20: exibem todos os valores associados ao parâmetro age
  • linha 22: exibe o valor associado à chave compteur na sessão
  • linha 24: exibe o valor associado à chave info1 na consulta

16.6. Os testes

  • em [1], a consulta Action1 é solicitada sem parâmetros
  • em [2], [Context.JSP] não encontrou parâmetros
  • em [3], [Context.JSP] encontrou a chave compteur na sessão
  • em [4], [Context.JSP] encontrou a chave info1 na consulta

Vamos fazer outro teste:

  • em [1], Action1 é solicitado com parâmetros
  • em [2], [Context.JSP] exibe esses parâmetros
  • em [3], [Context.JSP] encontrou a chave compteur na sessão. O contador foi incrementado em 1, demonstrando assim que houve memorização entre as duas solicitações.
  • em [4], [Context.JSP] encontrou a chave info1 na solicitação

Lembramos que o método [Action1.execute] gravava no console do servidor web. Aqui está um exemplo:

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

16.7. Conclusion

É importante lembrar os seguintes pontos:

  • para armazenar informações a serem compartilhadas por todas as solicitações de todos os usuários, utilizaremos a memória do aplicativo. Mostraremos um exemplo disso em breve.
  • para armazenar informações a serem compartilhadas por todas as solicitações de um mesmo usuário, utilizaremos a sessão desse usuário.
  • Para armazenar informações a serem compartilhadas por todos os componentes que processam uma solicitação, utilizaremos a memória da solicitação.