Skip to content

1. Generalidades

El PDF del documento está disponible |AQUÍ|.

1.1. Objetivos

Aquí nos proponemos descubrir un método de desarrollo llamado STRUTS. Jakarta Struts es un proyecto de la Apache Software Foundation (www.apache.org) cuyo objetivo es proporcionar un marco estándar para el desarrollo de aplicaciones web en Java que respete la arquitectura denominada MVC (Modelo-Vista-Controlador).

1.2. El modelo MVC

El modelo MVC busca separar las capas de presentación, procesamiento y acceso a los datos. Una aplicación web que respete este modelo tendrá la siguiente arquitectura:

Esta arquitectura se denomina de tres capas o de tres niveles:

  • la interfaz de usuario es la V (la vista)
  • la lógica de aplicación es la C (el controlador)
  • las fuentes de datos son la M (modelo)

La interfaz de usuario suele ser un navegador web, pero también puede ser una aplicación independiente que, a través de la red, envía solicitudes HTTP al servicio web y da formato a los resultados que este le devuelve. La lógica de la aplicación está formada por los scripts que procesan las solicitudes del usuario. La fuente de datos suele ser una base de datos, pero también pueden ser simples archivos planos, un directorio LDAP, un servicio web remoto, etc. Al desarrollador le conviene mantener una gran independencia entre estas tres entidades para que, si una de ellas cambia, las otras dos no tengan que cambiar, o lo hagan mínimamente.

Cuando se intenta aplicar este modelo con servlets y páginas JSP, se obtiene la siguiente arquitectura:

En el bloque [Logique Applicative], se distingue

  • el servlet, que es la puerta de entrada de la aplicación y al que también se denomina controlador
  • el bloque [Classes métier], que agrupa las clases Java necesarias para la lógica de la aplicación.
  • el bloque [Classes d'accès aux données], que agrupa las clases Java necesarias para obtener los datos que necesita el servlet, a menudo datos persistentes (BD, archivos, servicio WEB, ...)
  • el bloque de páginas JSP que constituye las vistas de la aplicación.

1.3. Un enfoque de desarrollo MVC mediante servlets y páginas JSP

Hemos definido un enfoque para el desarrollo de aplicaciones web Java que respeta el modelo MVC anterior. Lo recordamos aquí.

  1. Comenzaremos por definir todas las vistas de la aplicación. Estas son las páginas web que se muestran al usuario. Por lo tanto, nos pondremos en su lugar para diseñar las vistas. Se distinguen tres tipos de vistas:
    • el formulario de entrada, cuyo objetivo es obtener información del usuario. Este suele disponer de un botón para enviar la información introducida al servidor.
    • la página de respuesta, que solo sirve para proporcionar información al usuario. A menudo cuenta con un enlace que permite al usuario continuar con la aplicación en otra página.
    • la página mixta: el servlet ha enviado al cliente una página que contiene información generada por él. Esa misma página servirá al cliente para proporcionar al servlet otra información.
  1. Cada vista dará lugar a una página JSP. Para cada una de ellas:
    • se definirá el aspecto de la página
    • se determinarán cuáles son las partes dinámicas de la misma:
      • la información destinada al usuario que deberá proporcionar el servlet como parámetros a la vista JSP
      • los datos introducidos que deberán transmitirse al servlet para su procesamiento. Estos deberán formar parte de un formulario HTML.
  1. Se pueden esquematizar las E/S de cada vista
    • las entradas son los datos que deberá proporcionar el servlet a la página JSP, ya sea en la solicitud (request) o en la sesión (session).
    • Las salidas son los datos que deberá proporcionar la página JSP al servlet. Forman parte de un formulario HTML y el servlet los recuperará mediante una operación del tipo request.getparameter(...).
  1. Escribiremos el código Java/JSP de cada vista. Por lo general, tendrá la siguiente forma:
<%@ page ... %>    // importaciones de clases más frecuentes
<%!
     // variables de instancia de la página JSP (=globales)
     // necesario solo si la página JSP tiene métodos que comparten variables (poco frecuente)     
    ...    
%>
<%
     // recuperación de los datos enviados por el servlet
     // ya sea en la solicitud (request) o en la sesión (session)
    ...
%>

<html>
...
         // aquí se intentará minimizar el código Java
</html>
  1. A continuación, podemos pasar a las primeras pruebas. El método de implementación que se explica a continuación es específico del servidor Tomcat:
    • el contexto de la aplicación debe crearse en el archivo server.xml de Tomcat. Podemos empezar por probar este contexto. Sea C este contexto y DC la carpeta asociada al mismo. Crearemos un archivo estático test.html que colocaremos en la carpeta DC. Tras iniciar Tomcat, accederemos con un navegador a URL http://localhost:8080/DC/test.html.
    • Se puede probar cada página JSP. Si una página JSP se llama formulaire.jsp, se solicitará con un navegador la página URL http://localhost:8080/DC/formulaire.jsp. La página JSP espera valores del servlet que la llama. Aquí se llama directamente, por lo que no recibirá los parámetros esperados. Para que las pruebas sean posibles de todos modos, inicializaremos nosotros mismos en la página JSP los parámetros esperados con constantes. Estas primeras pruebas permiten verificar que las páginas JSP son sintácticamente correctas.
  1. A continuación, escribimos el código del servlet. Este tiene dos métodos bien diferenciados:
    • el método init, que sirve para:
      • recuperar los parámetros de configuración de la aplicación en el archivo web.xml de la misma
      • crear, si es necesario, instancias de clases de negocio que se utilizarán posteriormente
      • gestionar una posible lista de errores de inicialización que se devolverá a los futuros usuarios de la aplicación. Esta gestión de errores puede llegar hasta el envío de un correo electrónico al administrador de la aplicación para avisarle de un fallo
    • el método doGet o doPost, dependiendo de cómo reciba el servlet sus parámetros de sus clients. Si el servlet gestiona varios formularios, es recomendable que cada uno de ellos envíe una información que lo identifique de forma única. Esto se puede hacer mediante un atributo oculto en el formulario del tipo <input type="hidden" name="action" value="...">. El servlet puede empezar por leer el valor de este parámetro y, a continuación, delegar el procesamiento de la solicitud a un método privado interno encargado de gestionar este tipo de solicitudes.
    • Se evitará en la medida de lo posible incluir código de negocio en el servlet. No está diseñado para eso. El servlet es una especie de jefe de equipo (controlador) que recibe solicitudes de sus clients (clients web) y las hace ejecutar por las personas más adecuadas (las clases de negocio). Al escribir el servlet, se determinará la interfaz de las clases de negocio que hay que escribir (constructores, métodos). Esto si dichas clases de negocio están por crear. Si ya existen, entonces el servlet debe adaptarse a la interfaz existente.
    • Se compilará el código del servlet.
  1. Se escribirá el esqueleto de las clases de negocio necesarias para el servlet. Por ejemplo, si el servlet utiliza un objeto de tipo proxyArticles y esta clase debe tener un método getCodes que devuelva una lista (ArrayList) de cadenas de caracteres, en un primer momento basta con escribir:
public ArrayList getCodes(){
    String[] codes= {"code1","code2","code3"};
    ArrayList aCodes=new ArrayList();
    for(int i=0;i<codes.length;i++){
        aCodes.add(codes[i]);
    }
        return aCodes;
}
  1. A continuación, se puede pasar a las pruebas del servlet.
    • Se debe crear el archivo de configuración web.xml de la aplicación. Debe contener toda la información que espera el método init del servlet (<init-param>). Además, se configura el URL a través del cual se accederá al servlet principal (<servlet-mapping>).
    • Todas las clases necesarias (servlet, clases de negocio) se colocan en WEB-INF/classes.
    • Todas las bibliotecas de clases (.jar) necesarias se colocan en WEB-INF/lib. Estas bibliotecas pueden contener clases de negocio, controladores JDBC, etc.
    • Las vistas JSP se colocan en la raíz de la aplicación o en una carpeta propia. Se hace lo mismo con los demás recursos (html, imágenes, sonido, vídeos, ...)
    • Una vez hecho esto, se prueba la aplicación y se corrigen los primeros errores. Al final de esta fase, la arquitectura de la aplicación está operativa. Esta fase de pruebas puede resultar complicada, ya que no se dispone de herramientas de depuración con Tomcat. Para ello, sería necesario que Tomcat estuviera integrado en una herramienta de desarrollo (JBuilder Developer, Sun One Studio, etc.). Podemos ayudarnos de las instrucciones System.out.println("....") que escriben en la ventana de Tomcat. Lo primero que hay que comprobar es que el método init recupere correctamente todos los datos procedentes del archivo web.xml. Para ello, se puede escribir el valor de estos en la ventana de Tomcat. Se comprobará de la misma manera que los métodos doGet y doPost recuperan correctamente los parámetros de los diferentes formularios HTML de la aplicación.

Se escriben las clases de negocio que necesita el servlet. Se trata, por lo general, del desarrollo clásico de una clase Java, que suele ser independiente de cualquier aplicación web. En primer lugar, se probará fuera de este entorno con una aplicación de consola, por ejemplo. Una vez escrita una clase de negocio, se puede integrar en la arquitectura de implementación de la aplicación web y comprobar su correcta integración en la misma. Se procederá de esta manera para cada clase de negocio.

1.4. El proceso de desarrollo STRUTS

Los creadores de la metodología STRUTS han tratado de definir un método de desarrollo estándar que respete la arquitectura MVC para las aplicaciones web escritas en Java. El proyecto STRUTS tiene dos aspectos:

  • el método de desarrollo. Veremos que es bastante similar al descrito anteriormente para los servlets y las páginas JSP
  • las herramientas que nos permiten aplicar este método de desarrollo. Se trata de bibliotecas de clases Java que se pueden encontrar en el sitio web de la Fundación Apache (www.apache.org).

1.4.1. El método de desarrollo

La arquitectura MVC utilizada por STRUTS es la siguiente:

  • El controlador es el núcleo de la aplicación. Todas las solicitudes del cliente pasan por él. Se trata de un servlet genérico proporcionado por STRUTS. En algunos casos, puede ser necesario derivarla. Para los casos sencillos, no es necesario. Este servlet genérico toma la información que necesita de un archivo que suele llamarse struts-config.xml.
  • Si la solicitud del cliente contiene parámetros de formulario, estos se colocan en un objeto Bean. Se dice que una clase es de tipo bean si cumple unas reglas de construcción que veremos más adelante. Los objetos bean creados a lo largo del tiempo se almacenan en la sesión o en la solicitud del cliente. Este punto es configurable. No es necesario volver a crearlos si ya se han creado.
  • en el archivo de configuración struts-config.html, a cada URL que deba ser procesada por el programa (y que, por lo tanto, no corresponde a una vista JSP que se pudiera solicitar directamente) se le asocia cierta información:
    • el nombre de la clase de tipo Action encargada de procesar la solicitud. En este caso también, el objeto Action instanciado puede conservarse en la sesión o en la solicitud.
    • si la URL solicitada está parametrizada (caso del envío de un formulario al controlador), se indica el nombre del bean encargado de memorizar la información del formulario.
  • Con esta información proporcionada por su archivo de configuración, al recibir una solicitud de URL por parte de un cliente, el controlador es capaz de determinar si hay que crear un bean y cuál. Una vez instanciado, el bean puede verificar si los datos que ha almacenado y que proceden del formulario son válidos o no. El controlador invoca automáticamente un método del bean llamado validate. El bean es creado por el desarrollador. Por lo tanto, este incluye en el método validate el código que comprueba la validez de los datos del formulario. Si los datos resultan inválidos, el controlador no seguirá adelante. Pasará el control a una vista cuyo nombre encontrará en su archivo de configuración. El intercambio habrá finalizado entonces. Cabe señalar que el desarrollador puede solicitar que no se compruebe la validez del formulario. También lo hace en el archivo struts-config.html. En este caso, el controlador no invoca el método validate del bean.
  • Si los datos del bean son correctos, o si no hay verificación, o si no hay bean, el controlador cede el control al objeto de tipo Action asociado a URL. Lo hace solicitando la ejecución del método execute de dicho objeto, al que transmite la referencia del bean que haya construido. Es aquí donde el desarrollador realiza lo que debe hacer: eventualmente deberá recurrir a clases de negocio o a clases de acceso a datos. Al final del procesamiento, el objeto Action devuelve al controlador el nombre de la vista que debe enviar como respuesta al cliente.
  • El controlador envía esta respuesta. El intercambio con el cliente ha finalizado.

Empieza a perfilarse la metodología de desarrollo STRUTS:

  • la definición de las vistas. Se distingue entre las vistas que son formularios y las demás.
    • Cada vista de formulario da lugar a una definición en el archivo struts-config.xml. En él se define la siguiente información:
      • el nombre de la clase Bean que contendrá los datos del formulario, así como la indicación de si los datos deben verificarse o no. Si deben verificarse y resultan inválidos, hay que indicar la vista que se enviará al cliente en ese caso.
      • el nombre de la clase Action encargada de procesar el formulario.
      • el nombre de todas las vistas que pueden enviarse al cliente una vez que se haya procesado la solicitud. La clase Action elegirá una de ellas en función del resultado del procesamiento.
    • Cada vista es objeto de una página JSP. Veremos que en las vistas, especialmente en las vistas de formulario, a veces se utiliza una biblioteca de etiquetas propias de Struts.
  • la escritura de las clases JavaBean correspondientes a las vistas de formulario
  • la escritura de las clases Action encargadas de procesar los formularios
  • la escritura de las posibles clases de negocio o de acceso a datos

1.4.2. Las herramientas de desarrollo STRUTS

El proyecto STRUTS es uno de los proyectos de la Apache Software Foundation. Varios de estos proyectos se agrupan bajo la denominación Jakarta y están disponibles en URL http://jakarta.apache.org:

Image

Se recomienda leer esta página. Muchos de los proyectos son de interés para los desarrolladores de Java. Si seguimos el enlace de Struts anterior, llegamos a la página de inicio del proyecto:

Image

Aquí también se recomienda leer la página de inicio. Para descargar las bibliotecas Java de Struts, seguimos el enlace Binaries anterior:

Image

Para el entorno Windows, utilizaremos el enlace 1.1.zip y 1.1.tar.gz para el entorno Unix (noviembre de 2003). Una vez descomprimido el archivo 1.1.zip, obtenemos la siguiente estructura de directorios:

Image

En esta estructura de directorios se encuentran las bibliotecas de clases Java necesarias para el desarrollo STRUTS. Estas se encuentran en archivos .jar o .war, archivos análogos a los archivos .zip. Se pueden abrir con las mismas utilidades. La mayoría de las bibliotecas necesarias se encuentran en la carpeta lib mencionada anteriormente:

Image

Además de las bibliotecas de clases .jar, hay archivos .dtd (Document Type Definition) que contienen reglas de validez para los archivos XML. Un archivo XML puede hacer referencia en su contenido a un archivo de este tipo, DTD. El programa (denominado analizador) que analiza el contenido del archivo XML utilizará las reglas de validez encontradas en el archivo DTD al que se hace referencia para determinar si el archivo XML es sintácticamente correcto. Así, por ejemplo, el archivo struts-config_1_1.dtd establece las reglas de construcción del archivo de configuración struts-config.xml para Struts 1.1 version.

Veamos ahora dónde colocar los diferentes elementos del árbol de Struts para implementar una aplicación Struts en el servidor Tomcat.

1.5. Implementación de una aplicación Struts

Una aplicación Struts es una aplicación web como cualquier otra. Por lo tanto, sigue las reglas de implementación del contenedor en el que se ejecuta. En este caso, una aplicación, a la que llamaremos strutspersonne, se ejecutará en un servidor Tomcat version 4.x. En el anexo se incluye el procedimiento de implementación para Tomcat version 5.x. Aquí seguimos las reglas de implementación de Tomcat 4.x:

  1. Definimos el contexto strutspersonne en el archivo de configuración server.xml de Tomcat:
                <Context path="/strutspersonne" docBase="e:/data/serge/web/struts/personne" />

Una vez hecho esto, reiniciamos Tomcat para que tenga en cuenta el nuevo contexto. Podemos comprobar la validez del contexto solicitando el URL http://localhost:8080/strutspersonne:

Image

Si no aparece una página de error, significa que el contexto es correcto.

  1. Creamos en la carpeta física asociada al contexto strutspersonne la subcarpeta WEB-INF.
  2. En la carpeta WEB-INF de la aplicación, definimos el archivo de configuración web.xml de la aplicación:

Image

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <servlet>
      <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
      <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

</web-app>
  • La clase del controlador (servlet) de la aplicación es una clase predefinida de Struts, llamada ActionServlet. Se encuentra en el archivo struts.jar. Para que Tomcat pueda encontrar esta clase, colocaremos struts.jar en la carpeta <tomcat>\common\lib, que es una de las carpetas que Tomcat explora cuando busca clases. De hecho, colocaremos allí todos los archivos .jar que se encuentren en la carpeta <struts>\lib, donde <struts> es la carpeta raíz del árbol de Struts.

Image

  • También se colocarán los archivos struts-el.jar y jstl.jar que se encuentran en <struts>\contrib\struts-el\lib:

Image

  • Aquí tenemos acceso al servidor web. No siempre es así. Si se implementa una aplicación web/Java en un contenedor web que no se administra uno mismo, es preferible que la aplicación traiga consigo todas las bibliotecas que necesita. Estas deben colocarse en la carpeta WEB-INF/lib, que hay que crear.
  • Hemos indicado que el controlador necesitaba cierta información que normalmente encontraba en un archivo struts-config.xml ubicado en la misma carpeta que web.xml. De hecho, el nombre de este archivo es configurable. Es el parámetro config, mencionado anteriormente, el que establece este nombre.
  • La etiqueta <servlet-mapping> indica que se accederá al controlador a través de todos los URL que terminen con el sufijo .do. Esta asociación es requerida por Struts. A continuación, estas URL serán filtradas por el controlador, que solo aceptará las URL declaradas en su archivo de configuración struts-config.xml

Por ahora, nuestro archivo web.xml es suficiente.

  1. Vamos a solicitar el URL /main.do a la aplicación strutspersonne. Según el archivo web.xml anterior, este URL se transmitirá al servlet org.apache.struts.action. Se instanciará la clase ActionServlet y se llamará a su método init. Este intenta leer el archivo de configuración definido por el parámetro config. Por lo tanto, este debe existir. Creamos el siguiente archivo struts-config.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
    <action-mappings>
      <action
          path="/main"
          parameter="/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>
</struts-config>

Cabe señalar que el archivo DTD de struts-config.xml no es el mismo que el del archivo web.xml, lo que indica que no tienen la misma estructura. Para cada URL que el controlador debe gestionar, debemos definir una etiqueta <action>. Esta sirve para indicar al controlador qué debe hacer cuando se le solicita este URL. Aquí indicamos los siguientes elementos:

  1. path="/main": define el nombre de la acción configurada por la etiqueta <action>. El sufijo .do es implícito.
  2. type="org.apache.struts.actions.ForwardAction": define el nombre de la clase Action que debe gestionar la solicitud. Aquí se utiliza una clase Action predefinida en Struts. No hace nada por sí misma y reenvía la solicitud del cliente a la URL indicada en el atributo parameter.
  3. parameter="/main.html": el nombre del URL al que debe reenviarse la solicitud. En este caso, se trata de un archivo HTML estático.

En resumen, cuando el usuario solicite el URL /main.do, obtendrá el URL /main.html.

  1. El archivo main.html será el siguiente:
<html>
    <head>
      <title>Application strutspersonne</title>
  </head>
  <body>
      Application strutspersonne active ....
  </body>
</html>

Este archivo se encuentra en la carpeta de la aplicación strutspersonne/vues:

Image

Se puede solicitar directamente con el URL http://localhost:8080/strutspersonne/main.html :

Image

En este caso, el controlador Struts de la aplicación no ha intervenido, ya que solo interviene si se solicita el URL de tipo *.do. Sin embargo, aquí se ha solicitado el URL /vues/main.html.

  1. El archivo struts-config.xml creado anteriormente debe colocarse en la misma carpeta WEB-INF que el archivo web.xml:

Image

  1. Ahora vamos a comprobar el correcto funcionamiento del controlador de la aplicación strutspersonne solicitando el URL /main.do tras haber reiniciado Tomcat, si es necesario.

Image

Aquí ha intervenido el controlador Struts, ya que hemos solicitado un URL de tipo *.do. Hemos obtenido correctamente la página esperada (main.html). Por lo tanto, disponemos de los elementos básicos para el funcionamiento de nuestra aplicación: el contexto strutspersonne, los archivos de configuración web.xml y struts-config.xml, y las bibliotecas Struts.

¿Qué habría pasado si hubiéramos solicitado un URL de tipo /toto.do? Según el archivo web.xml de la aplicación strutspersonne, se llama entonces al controlador Struts para procesarlo. Este consulta entonces su archivo de configuración struts-config.html y no encuentra ninguna configuración para el URL /toto. ¿Qué hace entonces? Probemos:

Image

Obtenemos una página de errores, lo cual parece normal. Ahora podemos empezar a escribir una aplicación.