Skip to content

17. Exemplo 15 – Integração Struts 2 / Spring

No exemplo anterior, não tínhamos dados com o âmbito Application partilhados por todas as solicitações de todos os utilizadores. Apresentamos aqui um exemplo. Para o implementar, utilizamos o framework Spring [http://www.springsource.org/]. O Spring é uma ferramenta de grande valor. Neste exemplo, mostramos apenas uma pequena parte das suas capacidades. Um exemplo posterior irá utilizá-lo de forma mais intensiva.

O objetivo desta aplicação é apresentar os dados da série Application.

17.1. O projeto NetBeans

O projeto NetBeans da aplicação é o seguinte:

  • em [1]:
    • [web.xml], que configura a aplicação web, irá sofrer alterações em relação ao que era nas versões anteriores
    • [applicationContext.xml] é o ficheiro de configuração do Spring
  • em [2]: a vista [Context.JSP] que apresentará os dados do âmbito «Application»
  • em [3]:
    • o ficheiro de mensagens [messages.properties]
    • o ficheiro de configuração principal do Struts [struts.xml]. Irá evoluir em relação às aplicações anteriores.
  • em [4]:
    • a ação Struts [Action1.java]
    • a classe [Config.java], que irá armazenar os dados de âmbito da aplicação
    • o ficheiro de configuração secundário do Struts [example.xml]
  • em [5]: a biblioteca Struts 2
  • em [6]:
    • os arquivos necessários para o Spring [spring-core, spring-context, spring-beans, spring-web, commons-logging]
    • o arquivo do plugin Spring para o Struts 2. Permite a integração do Spring com o Struts 2 [struts2-spring-plugin]

Em relação às versões anteriores:

  • é necessário adicionar arquivos ao projeto
  • alterar os ficheiros [web.xml] e [struts.xml]

17.2. Configuration

17.2.1. O ficheiro [web.xml]

O ficheiro [web.xml] sofre as seguintes alterações:


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Exemple 14</display-name>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <URL-pattern>/*</padrão-URL>
  </filter-mapping>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

A alteração ocorre nas linhas 12-14. É adicionado um ficheiro listener à aplicação web. Quando a aplicação web for iniciada, a classe que implementa este ficheiro listener será instanciada. Trata-se de uma classe do Spring. Esta classe irá utilizar o ficheiro [WEB-INF/applicationContext.xml]. Este é o seguinte:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
  
  <!-- configuração dos beans de âmbito da aplicação -->
  <bean id="config" class="example.Config" >
    <property name="nbMaxUsers" value="10"/>
  </bean>

</beans>
  • O ficheiro de configuração do Spring tem a baliza raiz <beans> (linhas 2 e 11). Poderíamos traduzir beans por «objetos». O Spring irá instanciar todos os objetos (bean) encontrados neste ficheiro de configuração. Faz isso apenas uma vez, quando o Spring é iniciado no arranque da aplicação web.
  • linhas 7-9: definem um bean denominado config (id). O bean «config» está associado à classe (class) [example.Config]. O Spring irá instanciar esta classe.
  • linha 8: define uma propriedade da classe [example.Config]. O Spring irá chamar o método [example.Config].setNbMaxUsers(10). Por isso, é necessário que o método setNbMaxUsers exista na classe. Este é o seguinte:

package example;

public class Config {

  private int nbMaxUsers;

  public int getNbMaxUsers() {
    return nbMaxUsers;
  }

  public void setNbMaxUsers(int nbMaxUsers) {
    this.nbMaxUsers = nbMaxUsers;
  }
  
}

Esta classe define apenas um campo nbMaxUsers com os seus get e set. Se tivermos seguido corretamente o que foi explicado, ao iniciar a aplicação web, é instanciada uma instância da classe [Config] com o valor 10 para o seu campo nbMaxUsers. Definimos apenas um único campo, mas isso é suficiente para a nossa demonstração. Pretendemos mostrar que este campo, que poderia representar o número máximo de utilizadores, é um dado de âmbito Application acessível a todas as ações. É isso que iremos demonstrar com a ação [Action1].

17.2.2. O ficheiro [struts.xml]

O ficheiro de configuração principal do Struts é o seguinte:


<?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" />
  <!-- integração com o Spring -->
  <constant name="struts.objectFactory.spring.autoWire" value="name" />

  <include file="example/example.xml"/>

  <package name="default" namespace="/" extends="struts-default">
    <default-action-ref name="index" />
    <action name="index">
      <result type="redirectAction">
        <param name="actionName">Action1</param>
        <param name="namespace">/example</param>
      </result>
    </action>
  </package>

</struts>

Apenas a linha 10 difere das versões anteriores deste ficheiro. Ela define uma constante do Struts. Os objetos instanciados pelo Spring podem ser injetados noutros objetos. Este é o próprio fundamento do Spring. Aqui, uma referência ao objeto do tipo [Config] criado pelo Spring poderá ser injetada em objetos Struts. É aqui que entra o plugin Spring para Struts 2, que assegura a integração do Spring pelo Struts.

A linha 10 indica que a injeção de objetos Spring num objeto Struts será feita automaticamente (autowire) por nome (value). Voltemos ao ficheiro de configuração [applicationContext.xml]:


<!-- configuração de beans com âmbito de aplicação -->
  <bean id="config" class="example.Config" >
    <property name="nbMaxUsers" value="10"/>
  </bean>

O que o Struts 2 designa como nome do bean é, na verdade, o id. Assim, neste caso, o bean do tipo [Config] instanciado tem como nome config.

A ação [Action1.java] é a seguinte:


package example;

import com.opensymphony.xwork2.ActionSupport;
...
public class Action1 extends ActionSupport implements SessionAware, RequestAware, ParameterAware {

  // construtor sem parâmetros
  public Action1() {
  }
  
  // Sessão, Pedido, Parâmetros
  private Map<String, Object> session;
  private Map<String, Object> request;
  private Map<String, String[]> parameters;
  private Config config;

  @Override
  public String execute() {
  ....
    // pedido
    request.put("nbMaxUsers", config.getNbMaxUsers());

    // Exibição da página JSP
    return SUCCESS;
  }
...
  public Config getConfig() {
    return config;
  }

  public void setConfig(Config config) {
    this.config = config;
  }
}

A ação [Action1] é idêntica à que existia na aplicação anterior, com as seguintes diferenças:

  • linha 15: foi adicionado um campo config. Como tem o nome de um bean instanciado pelo Spring, este campo receberá automaticamente uma referência a esse objeto. Assim, a ação tem acesso à configuração da aplicação ou, de forma mais geral, aos dados de âmbito Application.
  • linha 31: o Spring irá instanciar o campo config através do seu método set. Por isso, este método tem de estar presente.
  • linha 21: a ação acede às informações do âmbito Application. Colocamos o número máximo de utilizadores nbMaxUsers na consulta para que a vista [Context.JSP] possa exibi-lo.

17.2.3. O ficheiro [example.xml]

O ficheiro secundário de configuração do Struts é idêntico ao da versão anterior:


<?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>

17.3. A vista [Context.JSP]

A vista [Context.JSP] é a 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>
    nom : <s:property value="#parameters['nom']"/><br/>
    age : <s:property value="#parameters['age']"/>
    <h3><s:text name="Context.session"/></h3>
    compteur : <s:property value="#session['compteur']"/>
    <h3><s:text name="Context.request"/></h3>
    nbMaxUsers : <s:property value="#request['nbMaxUsers']"/>
  </body>
</html>

17.4. Os testes

Um exemplo de execução é o seguinte: