Skip to content

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

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

  • aos parâmetros da solicitação
  • aos atributos da solicitação
  • aos atributos da sessão do utilizador
 

16.1. O projeto NetBeans

O projeto NetBeans é o seguinte:

  • em [1], a vista [Context.JSP]
  • em [2], a ação [Action1.java] e o ficheiro 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: o pedido do URL [/example/Action1] irá provocar a instanciação da classe [example.Action]. Como não é especificado nenhum método, será executado o método execute.
  • linha 9: é aceite apenas uma chave. A chave success leva à exibição da vista [Context.JSP].

A arquitetura simplificada do processamento de um pedido será a seguinte:

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

  • dados de âmbito Application, [3] e c.a.d. Dados acessíveis a todas as solicitações de todos os utilizadores. Estes são, na maioria das vezes, de leitura única. É frequente encontrar nestes dados a configuração inicial da aplicação. Neste caso, [Action1] e [Context.JSP] têm acesso a estes dados.
  • Dados de âmbito Session, [4] e c.a.d. São dados acessíveis a todas as solicitações de um mesmo utilizador. Estão em modo de leitura/escrita. Aqui, [Action1] utilizará a sessão em modo de leitura/escrita, enquanto [Context.JSP] a utilizará em modo de leitura.
  • Dados de âmbito Requête [5], acessíveis a todos os elementos que processam a consulta. Aqui, [Action1] irá colocar um dado nesta memória e [Context.JSP] irá recuperá-lo. Os dados de âmbito «Requête» permitem que um elemento N transmita informação ao elemento N+1.
  • Os parâmetros da solicitação [6] enviados pelo cliente. São utilizados em modo de leitura apenas 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, Pedido, 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));
    // pedido
    request.put("info1", "information1");
    // exibição da página JSP
    return SUCCESS;
  }

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

  // pedido
  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 aceder ao dicionário de atributos da sessão (linha 16). Esta interface tem apenas um método, o da linha 46.
    • RequestAware: para aceder ao dicionário de atributos da consulta (linha 17). Esta interface tem apenas um método, o da linha 51.
    • ParameterAware: para aceder ao dicionário de parâmetros da consulta (linha 18). Note-se que a cada chave (o nome do parâmetro) corresponde um tabuleiro de valores. Isto é necessário para ter em conta os campos de introdução de dados que enviam vários valores, como, por exemplo, uma lista de seleção múltipla. A interface ParameterAware tem apenas um método, o da linha 56.
  • linha 21: o método execute, que é executado quando se solicita a ação [Action1]. Quando este é executado, os interceptores já tiveram de fazer o seu trabalho:
    • 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 do pedido.
  • linhas 31-38: grava-se o valor associado à chave compteur na sessão
  • linhas 32-34: procura-se a chave compteur na sessão. Se não for encontrada, é adicionada à sessão associada ao valor inteiro 0.
  • linhas 35-37: procura-se a chave compteur na sessão, o seu valor é incrementado e, em seguida, a chave é novamente inserida na sessão.
  • linha 38: o valor associado à chave compteur é apresentado. Como o incremento é efetuado em cada consulta à ação [Action1], deverá ser possível observar o valor do contador a aumentar à medida que as consultas são efetuadas.
  • 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 dos seus parâmetros. Os parâmetros são enviados pelo cliente da aplicação 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 vista [Context.JSP] será apresentada. Veremos que ela é capaz de recuperar os atributos da solicitação.
  • linha 42: o método execute devolve a chave succes.

16.4. O ficheiro de mensagens

O ficheiro [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 vista [Context.JSP]

A vista [Context.JSP] tem como função apresentar:

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

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

16.6. Os testes

  • em [1], Action1 é solicitado 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] apresenta esses parâmetros
  • em [3], [Context.JSP] encontrou a chave compteur na sessão. O contador foi efetivamente incrementado em 1, demonstrando assim que houve, de facto, memorização entre as duas solicitações.
  • em [4], [Context.JSP] encontrou a chave info1 na solicitação

Recorde-se que o método [Action1.execute] escrevia na consola do servidor web. Eis 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 ter em conta os seguintes pontos:

  • para armazenar informações a partilhar por todas as solicitações de todos os utilizadores, utilizar-se-á a memória da aplicação. Mostraremos um exemplo em breve.
  • para armazenar informações a partilhar por todas as solicitações de um mesmo utilizador, utilizar-se-á a sessão desse utilizador.
  • Para armazenar informações a partilhar por todos os elementos que processam uma solicitação, utilizar-se-á a memória da solicitação.