Skip to content

17. Ejemplo 15 – Integración de Struts 2 y Spring

En el ejemplo anterior, no teníamos datos de ámbito Application compartidos por todas las solicitudes de todos los usuarios. Mostramos aquí un ejemplo. Para implementarlo, utilizamos el framework Spring [http://www.springsource.org/]. Spring es una herramienta de gran valor. En este ejemplo solo mostramos una pequeña parte. En un ejemplo posterior se utilizará de forma más intensiva.

El objetivo de esta aplicación es mostrar datos de ámbito Application.

17.1. El proyecto NetBeans

El proyecto NetBeans de la aplicación es el siguiente:

  • en [1]:
  • [web.xml], que configura la aplicación web, evolucionará con respecto a lo que era en las versiones anteriores
  • [applicationContext.xml] es el archivo de configuración de Spring
  • en [2]: la vista [Context.jsp] que mostrará los datos del ámbito Application
  • en [3]:
  • el archivo de mensajes [messages.properties]
  • el archivo de configuración principal de Struts [struts.xml]. Evolucionará con respecto a las aplicaciones anteriores.
  • en [4]:
  • la acción Struts [Action1.java]
  • la clase [Config.java] que almacenará los datos de ámbito de aplicación
  • el archivo de configuración secundario de Struts [example.xml]
  • en [5]: la biblioteca Struts 2
  • en [6]:
  • los archivos necesarios para Spring [spring-core, spring-context, spring-beans, spring-web, commons-logging]
  • el archivo del plugin de Spring para Struts 2. Permite la integración de Spring con Struts 2 [struts2-spring-plugin]

En comparación con las versiones anteriores:

  • hay que añadir archivos al proyecto
  • modificar los archivos [web.xml] y [struts.xml]

17.2. Configuration

17.2.1. El archivo [web.xml]

El archivo [web.xml] cambia de la siguiente manera:


<?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>/*</url-pattern>
  </filter-mapping>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

La modificación se produce en las líneas 12-14. Se añade un listener a la aplicación web. Cuando se inicie la aplicación web, se instanciará la clase que implementa este listener. Se trata de una clase de Spring. Esta clase utilizará el archivo [WEB-INF/applicationContext.xml]. Este es el siguiente:


<?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">
  
  <!-- configuración de beans de ámbito de aplicación -->
  <bean id="config" class="example.Config" >
    <property name="nbMaxUsers" value="10"/>
  </bean>

</beans>
  • El archivo de configuración de Spring tiene la etiqueta raíz <beans> (líneas 2 y 11). Podríamos traducir beans como «objetos». Spring instanciará todos los objetos (bean) que se encuentren en este archivo de configuración. Solo lo hace una vez, cuando se inicia Spring al arrancar la aplicación web.
  • Líneas 7-9: definen un bean denominado config (id). El bean «config» está asociado a la clase (class) [example.Config]. Spring creará una instancia de esta clase.
  • línea 8: define una propiedad de la clase [example.Config]. Spring llamará al método [example.Config].setNbMaxUsers(10). Por lo tanto, el método setNbMaxUsers debe existir en la clase. Este es el siguiente:

package example;

public class Config {

  private int nbMaxUsers;

  public int getNbMaxUsers() {
    return nbMaxUsers;
  }

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

Esta clase solo define un campo nbMaxUsers con sus get y set. Si hemos seguido bien lo dicho, al iniciar la aplicación web, se crea una instancia de la clase [Config] con el valor 10 para su campo nbMaxUsers. Solo hemos definido un único campo, pero es suficiente para nuestra demostración. Queremos mostrar que este campo, que podría representar un número máximo de usuarios, es un dato de ámbito Application accesible para todas las acciones. Esto es lo que demostraremos con la acción [Action1].

17.2.2. El archivo [struts.xml]

El archivo de configuración principal de Struts es el siguiente:


<?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>
  <!-- internacionalización -->
  <constant name="struts.custom.i18n.resources" value="messages" />
  <!-- integración de 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>

Solo la línea 10 difiere de las versiones anteriores de este archivo. Define una constante de Struts. Los objetos instanciados por Spring pueden inyectarse en otros objetos. Este es el principio fundamental de Spring. Aquí, una referencia al objeto de tipo [Config] creado por Spring podrá inyectarse en objetos Struts. Aquí es donde interviene el plugin de Spring para Struts 2, que garantiza la integración de Spring en Struts.

La línea 10 indica que la inyección de objetos Spring en un objeto Struts se realizará de forma automática (autowire) por nombre (value). Volvamos al archivo de configuración [applicationContext.xml]:


<!-- configuración de beans de ámbito de aplicación -->
  <bean id="config" class="example.Config" >
    <property name="nbMaxUsers" value="10"/>
  </bean>

Lo que Struts 2 denomina «nombre del bean» es, en realidad, id. Por lo tanto, en este caso, el bean de tipo [Config] instanciado tiene como nombre config.

La acción [Action1.java] es la siguiente:


package example;

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

  // constructor sin parámetros
  public Action1() {
  }
  
  // Sesión, solicitud, parámetros
  private Map<String, Object> session;
  private Map<String, Object> request;
  private Map<String, String[]> parameters;
  private Config config;

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

    // Visualización de la página JSP
    return SUCCESS;
  }
...
  public Config getConfig() {
    return config;
  }

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

La acción [Action1] es idéntica a la de la aplicación anterior, salvo por los siguientes detalles:

  • línea 15: se ha añadido un campo config. Dado que lleva el nombre de un bean instanciado por Spring, este campo recibirá automáticamente una referencia a dicho objeto. De este modo, la acción tiene acceso a la configuración de la aplicación o, más en general, a los datos de ámbito Application.
  • línea 31: Spring instanciará el campo config a través de su método set. Por lo tanto, este debe estar presente.
  • línea 21: la acción accede a la información del ámbito Application. Se incluye el número máximo de usuarios nbMaxUsers en la consulta para que la vista [Context.jsp] pueda mostrarlo.

17.2.3. El archivo [example.xml]

El archivo secundario de configuración de Struts es idéntico al de la versión 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. La vista [Context.jsp]

La vista [Context.jsp] es la siguiente:


<%@ 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. Las pruebas

Un ejemplo de ejecución es el siguiente:

Image