Tema Struts 2

69
Tema 4 - Apache Jakarta Struts Dr. Diego Lz. de Ipiña Gz. de Artaza http://paginaspersonales.deusto.es/dipina http://paginaspersonales.deusto.es/dipina/cursos/ J2EECesine.zip [email protected]

Transcript of Tema Struts 2

Page 1: Tema Struts 2

Tema 4 - Apache Jakarta Struts

Dr. Diego Lz. de Ipiña Gz. de Artazahttp://paginaspersonales.deusto.es/dipina

http://paginaspersonales.deusto.es/dipina/cursos/J2EECesine.zip

[email protected]

Page 2: Tema Struts 2

Contenido Patrón de diseño MVC La framework Apache Struts

Instalación Flujo de control en Struts

Procesamiento de peticiones Control de errores Manejo de Formularios

Librerías de etiquetas de Struts Internacionalización

Ejemplo de aplicación Struts Java Server Faces

Page 3: Tema Struts 2

Modelos de desarrollo de aplicaciones web en Java Los servlets son buenos ejecutando lógica de

negocio, pero no son tan buenos presentando información

JSPs son muy buenos presentando pero pésimos introduciendo lógica programática en ellos

La combinación Servlet/JSPs es lo más común hoy en día en el desarrollo de aplicaciones web

Dos arquitecturas: Model-1: JSPs para presentación y control y JavaBeans

para la lógica Model-2: Model-View-Controller = JavaBeans-JSPs-

Servlets MVC es tan común que se han desarrollado varias

infraestructuras en torno a este patrón de diseño: Apache Struts Java Server Faces

Page 4: Tema Struts 2

Arquitectura Model 1

Page 5: Tema Struts 2

Arquitectura Model 2

Page 6: Tema Struts 2

Modelo MVC 0

Page 7: Tema Struts 2

Modelo MVC I

El Controlador (Controller) Servlet central recibe peticiones, procesa

URL recibida y delega procesamiento a JavaBeans

Servlet guarda resultado de procesamiento realizado por JavaBeans en el contexto de la petición, la sesión o la aplicación

Servlet transfiere control a un JSP que lleva a cabo la presentación de resultados

Page 8: Tema Struts 2

Modelo MVC II

El Modelo (Model) JavaBeans (o EJBs para aplicaciones

más escalables) desempeña el rol de modelo:

Algunos beans ejecutan lógica Otros guardan datos

Normalmente: 1. Servlet controlador invoca un método en

bean lógico y éste devuelve un bean de datos

2. Autor de JSP tiene acceso a bean de datos

Page 9: Tema Struts 2

Modelo MVC III

La Vista (View) Rol ejecutado por JSPs Servlet Controlador transfiere control

al JSP después de haber guardado en un contexto el resultado en forma de un bean de datos

JSP usa jsp:useBean y jsp:getProperty para recuperar datos y formatear respuesta en HTML o XML

Page 10: Tema Struts 2

Modelo MVC IV

En resumen: Los beans o EJBs ejecutan la lógica de

negocio y guardan los resultados Los JSPs proveen la información

formateada Los servlets coordinan/controlan la

ejecución de los beans y los JSPs

Page 11: Tema Struts 2

Frameworks Las frameworks pueden ser vistas como

implementaciones de patrones de diseño que facilitan la reutilización de diseño y código

Dado que MVC ha sido utilizado en muchas aplicaciones web, el desarrollo de frameworks que den soporte a áreas comunes en todas las aplicaciones MVC es necesario Apache Struts es una de estas frameworks

Aplicaciones basadas en Struts consistirán de: Código Java Deployment descriptors que configuran la

framework para el uso de nuestra aplicación

Page 12: Tema Struts 2

Apache Jakarta Struts

Implementación del modelo 2/patrón de diseño MVC que facilita la creación de aplicaciones web en Java

Creada por Craig McClanahan y donada a la Apache Software Foundation en el 2000 (pertenece a Apache Jakarta)

Page 13: Tema Struts 2

¿Qué proporciona Struts? Un servlet (ActionServlet) que actúa como controlador

MVC totalmente configurable Clases base que son extendidas para implementar la

lógica de la aplicación web: Struts Action Struts ActionForm

Un rico conjunto de etiquetas personalizadas JSP que cooperan con el controlador para su uso en la capa view de MVC

Varias opciones para la validación de entrada de usuario en formularios HTML: ActionForm o Validator Framework

Mecanismos para el manejo y reporte de errores Soporte para la internacionalización (i18n) a través de

ficheros de recursos y Java Locales Soporte para fuentes de datos Y más …..

Page 14: Tema Struts 2

Instalando Apache Struts I Instalar Apache Tomcat 4.x o superior Bajar la última versión de Apache Struts de:

http://struts.apache.org/download.cgi Actualmente en la versión 1.2 (fichero jakarta-struts-

1.2.4.zip para Windows) Crear directorio de aplicación. E.j: myStrutsApp Copiar ficheros .tld en directorio

{StrutsDirectory}/contrib/struts-el/lib a myStrutsApp/WEB-INF:

c.tld struts-bean-el.tld struts-html-el.tld struts-logic-el.tld

Page 15: Tema Struts 2

Instalando Apache Struts II Copiar los ficheros .jar files de

{StrutsDirectory}/contrib/struts-el/lib a myStrutsApp/WEB-INF/lib directory:

commons-beanutils.jar commons-collections.jar commmons-digester.jar commons-logging.jar jstl.jar standard.jar struts-el.jar struts.jar

Lo mejor es tomar la aplicación struts-blank.war como punto de partida.

Page 16: Tema Struts 2

Documentación y ejemplos de Struts En el directorio webapps de la

distribución de Struts 1.2 se pueden encontrar varios ficheros .war muy útiles: struts-documentation.war

En el subdirectorio api/index.html se puede encontrar JavaDoc de Struts API

Si se ejecuta esta aplicación web en http://localhost:8080/struts-documentation/ se puede también obtener información detallada sobre el uso de Struts

Ejemplos de uso de Struts: struts-examples.war struts-blank.war base para la creación de

cualquier aplicación que use Struts etc.

Page 17: Tema Struts 2

Flujo de Control en Struts I

Page 18: Tema Struts 2

Flujo de Control en Struts II

Page 19: Tema Struts 2

Flujo de control en Struts III La clase org.apache.struts.action.ActionServlet es el eje de Struts.

Dada una petición de entrada HTTP: Crea un objeto ActionForm donde guarda y valida los parámetros de entrada Decide que objeto Action se debe invocar y le pasa el objeto ActionForm creado Transfiere control a la siguiente etapa de procesamiento de la petición

(típicamente un JSP). El fichero de configuración web.xml contiene los url mappings para enviar

las peticiones de llegada al ActionServlet, mientras que el fichero de configuración de Struts struts-config.xml contiene los mappings a acciones

Los form beans creados por ActionServlet deben ser implementados por el programador, extendiendo org.apache.struts.action.ActionForm.

El programador deberá definir un conjunto de getters y setter y sobreescribir los métodos validate() y reset()

Los objetos Action invocados deben ser desarrollados por el programador y extienden org.apache.struts.action.Action. Tienen un método execute() o (perform() en Struts 1.0) que ejecuta la lógica de negocio

La acción devuelve un objeto ActionForward al servlet que especifica el siguiente paso a ejecutar, normalmente se transfiere el control a un JSP para que visualice los resultados.

Page 20: Tema Struts 2

Pasos a seguir en el desarrollo de una aplicación en Struts

Diseña la aplicación en términos de las acciones, vistas y estados del modelo

Añade las librerías Java de Struts y los .tlds de sus etiquetas personalizadas a tu proyecto

Configura tu web.xml para que envíe peticiones HTTP al ActionServet

Configura el ActionServlet definiendo elementos <action-mappings> y <form-beans> en struts-config.xml

Define tus clases Action Define tus clases ActionForm Define clases adicionales Java representando la lógica de negocio Define tus páginas de presentación JSP Desplegar la aplicación La aplicación ejemplo suministrada con Struts, struts-

blank.war, es normalmente un buen punto de partida para desarrollar una nueva aplicación usando Struts

Page 21: Tema Struts 2

Actions en Struts Se crea una acción extendiendo la clase

org.apache.struts.action.Action El ActionServlet ejecuta acciones invocando el método

execute() tu clase Action El método execute() contiene código para manipular el

modelo Dentro del método execute() tienes acceso a:

Cabeceras y parámetros de peticiones HTTP Atributos/beans guardados en los contextos

application/session/request scope Struts ActionForm asociados con la acción (opcional) El ActionMapping associado a esta acción (opcional) El objeto httpResponse

El método execute() devuelve un objeto ActionForward que indica al ActionServlet a dónde transferir el control a continuación

Page 22: Tema Struts 2

Form Beans Un ActionForm es un JavaBean con propiedades que

corresponden a los controles de un formulario HTML. Los parámetros son mapeados a propiedades del bean.

Proveen un mecanismo de buffer/validate/convert que necesitamos para asegurarnos que el usuario introduce los datos esperados

Actúa como puente entre el navegador y el objeto de negocio El programador define un form bean extendiendo la clase

org.apache.struts.action.ActionForm (o de forma declarativa usando org.apache.struts.action.DynaActionForm)

Hay que definir cada una de las propiedades en la clase y escribir los getters/setters correspondientes, siguiendo las reglas de JavaBeans

Después de escribir el código del form bean, es necesario asociarlo con una o más acciones a través del fichero de configuración de Struts struts-config.xml

Cada vez que se llama a la acción , el ActionServlet poblará las propiedades con los valores de los parámetros recibidos en el formulario HTML

Las propiedades no sólo pueden ser escalares sino que también pueden ser colecciones de valores

Page 23: Tema Struts 2

¿Por qué se necesitan Forms Beans? ¿Por qué no simplemente se accede a los parámetros de

una petición, en vez de usar un form bean como intermediario?

Razones: Los Form beans pueden ser validados antes de que una

acción sea invocada Si la propiedad validate de un elemento Action en el fichero struts-config.xml contiene el valor true (por defecto), el método validate será invocado

Si un form bean falla en la validación puede hacer que Struts envíe al usuario de vuelta a la vista (JSP) desde la que se realizó el POST en primer lugar, junto con un mensaje de error

Es importante asignar a la propiedad input del elemento action en struts-config.xml una referencia a la vista que entregó el formulario

Los form beans pueden ser usados por múltiples acciones o incluso una aplicación completa

Si se configura al ActionController para que guarde un form bean en el contexto de sesión se permitirá el uso del form bean en todas las peticiones web que llegan a la aplicación

Page 24: Tema Struts 2

Dynamic Action Forms Son ActionForms creados de manera declarativa en struts-

config.xml Una o varias propiedades dinámicas pueden ser pasadas a

una instancia de org.apache.struts.action.DynaActionForm

<form-bean name=“checkoutForm” type=“org.apache.struts.action.DynaActionForm”> <form-property name=“firstName” type=“java.lang.String”/> <form-property name=“lastName” type=“java.lang.String”/> <form-property name=“age” type=“java.lang.Integer” initial=“18”/></form-bean>

Page 25: Tema Struts 2

Recursos de String/Manejo de Errores

Recursos de String Todos los strings usados en mensajes en JSPs tanto de datos de

aplicación como de errores puedes ser colocados en un ficheros de recursos (ApplicationResources.properties)

Struts proporciona etiquetas personalizadas JSP tags para acceder a estos recursos<bean:message key="prompt.goodguess.heading"/>

Manejo de errores Se recomienda que el manejo de errores se lleve a cabo dentro

del método execute() y el control se transfiera a la vista apropiadaerrors.add("passphrase",new ActionError("error.passphrase.required"));

Struts proporciona un mecanismo separado para permitir la implementación de un manejador global de excepciones

Struts proporciona etiquetas JSP que ayudan en la visualización de los errores en tu JSP:<html:errors property=“passphrase”/>

Page 26: Tema Struts 2

Internationalization i18n Struts soporta internacionalización a través de ficheros de

recursos, sus librerías de etiquetas personalizadas y Java Locales Se pueden definir strings a visualizar en tu fichero de recursos, y

luego ser usados en tus JSPs Los strings del idioma por defecto se guardan en el fichero

ApplicationResources.properties Otros ficheros de recursos adicionales pueden ser definidos que

incluyen el idioma a usar en el nombre del fichero. Ejemplo:

ApplicationResources_eu.properties (Contiene mensajes en Euskera) ApplicationResources_es.properties (Contiene mensajes en Castellano) Para cambiar el idioma preferido en IE: ToolsInternet

OptionsLanguages Los navegadores envían la cabecera HTTP Accept-Language en

cada petición que indica cuál es el idioma preferido por el usuario Los ficheros de recursos deben colocarse en un lugar accesible

desde el CLASSPATH de la aplicación web, por ejemplo, debajo del directorio WEB-INF/classes

Page 27: Tema Struts 2

Ejemplo web.xml de aplicación usando Struts

<web-app> <!-- Action Servlet Configuration --> <servlet>

<servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-

class> <init-param>

<param-name>application</param-name> <param-value>

com.develop.ejsp.struts.resources.ApplicationResources </param-value>

</init-param> <init-param>

<!– etc. --> </init-param> <load-on-startup>1</load-on-startup>

</servlet> <!-- Action Servlet Mapping --> <servlet-mapping>

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

</servlet-mapping> </web-app>

Page 28: Tema Struts 2

Configurando Struts Como en toda framework se minimiza el código

Java a escribir y se maximiza la configuración a través de ficheros XML

Struts se configura a través struts-config.xml Leído por la framework cuando arranca

Contiene: Fuentes de datos (data-sources) Form beans, variaciones de JavaBeans.

Ejecutan una petición basado en una entrega de un formulario.

Son poblados por el controlador con los datos del formulario

Llevan a cabo validación de datos Son procesados por objetos Action

Global forwards y ActionMappings

Mapean el nombre de una acción a un objeto Action

Page 29: Tema Struts 2

Ejemplo struts-config.xml I<struts-config> <data-sources> <data-source name=“usuarios”> <set-property property= "autoCommit" value="false"/>

<set-property property= "description" value="MessageBoard"/> <set-property property= "driverClass" value="..SQLServerDriver"/> <set-property property= "maxCount" value="4"/> <set-property property= "minCount" value="2"/> <set-property property="password" value=""/> <set-property property= "url"value="someurl"/> <set-property property= "user" value="someuser"/>

</data-source> </data-sources> <!-- === Form Bean Definitions === --> <form-beans> <form-bean name="SigninForm" type= "com.develop.ejsp.struts.beans.SigninForm"/> </form-beans> <!-- === Global Forward Definitions === --> <global-forwards> <forward name="signin" path="/signin.jsp"/> </global-forwards>

Page 30: Tema Struts 2

Ejemplo struts-config.xml II

<!-- === Action Mapping Definitions === --> <action-mappings> <!-- Process a user logon --> <action path="/SigninAction“ type= "com.develop.ejsp.struts.actions.SigninAction“ name="SigninForm" scope="session“ input="/signin.jsp"> <forward name="succeeded" path="/groups.jsp"/> <forward name="failed" path="/groups.jsp"/> </action> <action path="/GotoReplyToAction“ type= "com.develop.ejsp.struts.actions.GotoMessageAction"> <forward name="succeeded" path="/newmessage.jsp"/> <forward name="failed" path="/groups.jsp"/> </action> </action-mappings> </struts-config>

Page 31: Tema Struts 2

Procesamiento de una petición en Struts I Si el cliente envía la petición:

http://server/app/GotoReplyToAction.do El ActionServlet de Struts quita la extensión

(.do) y mira la acción correspondiente en el fichero de configuración Struts para la acción GotoReplyToAction

Si la encuentra encontrará o creará una instancia del ‘tipo’ (type) indicado: com.develop.ejsp.struts.actions.GotoMessageAction

El método execute() será invocado en el objeto GotoMessageAction:

Este es el lugar donde la lógica de negocio de la petición es ejecutada

Page 32: Tema Struts 2

Procesamiento de petición en Struts II

public class GotoMessageAction extends org.apache.struts.action.Action {

public ActionForward execute( ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

// lots of code omitted for clarity, but here the // business logic should be implemented

ActionForward af = mapping.findForward("succeeded");

return af; }

}

Page 33: Tema Struts 2

Procesamiento de petición en Struts III De los cuatro parámetros recibidos en execute(), ActionMapping y ActionForm son específicos a Struts

El objeto ActionMapping contiene información de configuración proveniente de struts-config.xml file.

El objeto ActionForm contiene el bean del formulario que fue inicializado por el ActionServlet al procesar la petición

Page 34: Tema Struts 2

Procesamiento de petición en Struts IV En el mapeo de la acción GotoReplyToAction

hay dos posibles forward definidos: Uno con el nombre "succeeded" y otro "failed“

Si el método execute() se completa sin errores el método ActionMapping.findForward() es llamado, pasando el nombre del siguiente recurso a llamar.

El método findForward() devuelve un objeto ActionForward que es pasado al ActionServlet

El objeto ActionForward contiene detalles de a dónde debería el ActionServlet enviar la petición (contiene el path del JSP que va a visualizar los resultados)

Page 35: Tema Struts 2

Manejo de errores en Struts I Struts define la clase ActionErrors que mantiene una colección de

objetos ActionError.ActionErrors errors = new ActionErrors();errors.add (ActionErrors.GLOBAL_ERROR, new ActionError("error.signing.connect"));saveErrors(request,errors);return (new ActionForward (mapping.findForward(“failed"))); El código añade un sólo objeto ActionError a la colección, pero si se

llevase a cabo validación de los campos de un formulario varios errores podrían ser mostrados.

Luego devuelve una instancia de ActionForward que redirige a "failed".

El ActionServlet guardará en el objeto request el objeto ActionErrors bajo un nombre bien conocido por Struts:

request.setAttribute( Action.ERROR_KEY, errors); Este objeto ActionErrors es ahora disponible a cualquier página o

acción consecutiva. La página JSP “failed” anterior debería tener un área donde se

mostrasen los errores producidos. El string usado para construir un objeto ActionError no es un

mensaje de error sino que un identificador de un recurso (i18n Struts)

Page 36: Tema Struts 2

Manejo de errores en Struts IIpublic class GotoMessageAction extends org.apache.struts.action.Action { public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException { ActionErrors errors = new ActionErrors(); try { // business logic omitted for clarity } catch(SQLException e) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.sqlerror")); }

if (!errors.empty()) { saveErrors(request, errors); ActionForward af = mapping.findForward("failed"); return af; }

request.setAttribute(Message.MESSAGE_NAME, message); ActionForward af = mapping.findForward("succeeded"); return af; }}

Page 37: Tema Struts 2

Manejo de Formularios I La otra acción definida en el fichero de configuración de Struts

era:<action path="/SigninAction" type="com.develop.ejsp.struts. actions.SigninAction" name="SigninForm" scope="session" input="/signin.jsp">

<forward name="succeeded" path="/groups.jsp"/> <forward name="failed" path="/groups.jsp"/>

</action> Esta acción está asociada con el formulario llamado

SigningForm, también definido en el fichero de configuración:<form-beans>

<form-bean name="SigninForm" type="com.develop.ejsp.struts. beans.SigninForm"/> </form-beans>

Page 38: Tema Struts 2

Manejo de Formularios II Si una acción tiene un formulario

asociado a ella (atributo name en action mapping), el ActionServlet crea un form bean

Todo form bean hereda de org.apache.struts.action.ActionForm, que es un JavaBean serializable.

Dos métodos en ActionForm pueden ser sobreescritos: validate() y reset()

Page 39: Tema Struts 2

Manejo de Formularios IIIpublic ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {

ActionErrors errors = new ActionErrors();if ((username == null) || (username.length() < 1))

errors.add ("username",new ActionError("error.username.required"));

if ((password == null) || (password.length() < 1))errors.add("password",new ActionError("error.password.required"));

return errors;} El FormBean es poblado por el ActionServlet con los parámetros de

la petición de entrada llamando a los métodos setXXX() correspondientes.

Una vez poblado, el form bean es validado: Si el objeto ActionErrors devuelto es null o vacío significa que la

validación tuvo éxito y una instancia del form bean creado, en este caso SigningForm, es pasado al objeto SigningAction

Si la validación falla, la petición será re-direccionada por Struts a la página que contenía el formulario inicialmente el formulario, dada por el atributo input del elemento action en struts-config.xml

Page 40: Tema Struts 2

Manejo de Formularios IVpublic class SigninForm extends ActionForm { String userName = null; String password = null;

public SigninForm() {} public void setUsername(String userName) {

this.userName = userName; }

public String getUserName() { return this.userName; }

public void setPassword(String password) { this.password = password;

}

public String getPassword() { return this.password; }

...

Page 41: Tema Struts 2

Manejo de Formularios V // accessors and mutator omitted for clarity public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest

httpServletRequest) { ActionErrors errors = new ActionErrors(); if ((password == null) || (password.length() < 1)) errors.add("password", new

ActionError("error.password.required")); if ((userName == null) || (userName.length() < 1)) errors.add("username", new

ActionError("error.username.required")); return errors; }

public void reset(ActionMapping actionMapping, HttpServletRequest httpServletRequest) { username = ""; password=""; }}

Page 42: Tema Struts 2

Manejo de Formularios VIpublic class SigninAction

extends org.apache.struts.action.Action {

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException {

try { String username = ((SigninForm) form). getUserName(); String password = ((SigninForm) form). getPassword(); // etc. } }}

Page 43: Tema Struts 2

DataSources en Strutstry { DataSource ds = servlet.findDataSource(“usuarios”); message = new Message(); message.getMessage(ds, request.getParameter( Message.MESSAGE_ID)), request.getParameter( GROUP_ID_NAME)) } El código arriba muestra otra característica de Struts, la habilidad de

configurar y usar referencias a javax.jdbc.DataSources El extracto de struts-config.xml anteriormente mostrado tiene una

sección <data-sources> para configurar las data sources de la aplicación.

Struts provee las clases GenericDataSource y GenericConnection que son wrappers sobre los objetos JDBC Connections y DataSources definidos en el fichero de configuración.

Page 44: Tema Struts 2

Struts Tag Libraries Documentadas en

http://www.onjava.com/lpt/a/4034 La framework Struts proporciona un conjunto de

6 librerías de etiquetas, que asisten en la tarea de la creación de la vista de MVC para evitar incluir código Java en los JSPs:

Bean Tags HTML Tags Logic Tags Nested Tags Template Tags Tiles Tags

Las funcionalidad de las etiquetas definidas en las librerías Bean y Logic es también provista por las librerías core y fmt de JSTL

Se recomienda el uso de las librerías en JSTL

Page 45: Tema Struts 2

HTML Tags Estas etiquetas son principalmente usadas para:

Crear formularios de entrada de datos y Otras utilidades para visualizar interfaces basados en

HTML. Algunas de las acciones más útiles son:

base genera un elemento HTML <base> errors condicionalmente visualiza un conjunto

acumulado de mensajes de error form define un formulario de entrada text visualiza un campo de entrada de tipo texto messages condicionalmente visualiza un conjunto

de mensajes acumulados submit visualiza un botón de entrega Etc.

Page 46: Tema Struts 2

Logic Tags Usadas para:

Iterar sobre colecciones Generación condicional de salida, y Flujo de aplicación

Algunas de las acciones más útiles son: present genera el contenido de marcado dentro

de esta etiqueta si el valor indicado es encontrado en esta petición

notPresent lo opuesto a present iterate repite el contenido anidado dentro de

esta etiqueta al iterar sobre una colección forward transfiere control a la página

especificada por la entrada ActionForward. Etc.

Page 47: Tema Struts 2

Tiles Tags (Framework) La librería de etiquetas Tiles es un super-conjunto de la

librería Templates Intenta evitar la duplicación de contenido de lenguaje

de marcado dentro de una aplicación web con respecto al look-and-feel de un portal:

Un mecanismo normalmente utilizado es usar la directiva jsp:include para añadir cabeceras/menús y pies de páginas a un portal web

Tiles reduce el tamaño de código redundante en una aplicación web y separa el contenido de la visualización del mismo de manera más eficiente

Tiles define Layout Managers para JSPs Su objetivo principal es evitar en los JSPs contenido de

marcado que corresponda con el layout del portal factoriza este marcado, de tal manera que la modificación del layout sea sencilla y eficiente

Page 48: Tema Struts 2

JSP Templates Un template es una página JSP que usa

una librería de etiquetas personalizadas para describir la disposición (layout) de los componentes de la página Define cómo aparecerán las páginas JSP de

una aplicación, sin especificar el contenido Esta definición es utilizada por todos los

JSPs sin necesidad de mezclar layout con contenido

Page 49: Tema Struts 2

Ejemplo Tiles: index.jsp I<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<html:html><head><title><bean:message key="global.title"/></title><html:base/><script language=javascript src="include/scripts.js"></script><link rel="stylesheet" href="stylesheets/format_win_nav_main.css"

type="text/css"></head>

<body topmargin="0" leftmargin="0" bgcolor="#FFFFFF">

<!-- Header Page Information --><%@ include file="include/head.inc"%>

<!-- Nav Bar --><%@ include file="include/menubar.inc"%>

Page 50: Tema Struts 2

Ejemplo Tiles: index.jsp II<%@ include file="include/mainoffer.inc"%><!-- Featured Items Header Row --><table width="645" cellpadding="0" cellspacing="0" border="0"> <tr> <td width="21"><html:img height="1" alt="" page="/images/spacer.gif" width="1"

border="0"/></td> <td width="534"><html:img page="/images/week_picks.gif"

altKey="label.featuredproducts"/></td> <td width="1" bgcolor="#9E9EFF"><html:img height="1" alt="" page="/images/spacer.gif"

width="1" border="0"/></td> <td width="1" bgcolor="#9E9EFF"><html:img height="1" alt=""

page="/images/spacer.gif" width="1" border="0"/></td> <td width="90" bgcolor="#9E9EFF" align="right"><html:img height="1" alt=""

page="/images/spacer.gif" width="90" border="0"/></td> </tr> <tr> <td><html:img height="1" alt="" page="/images/spacer.gif" width="21"

border="0"/></td> <td colspan="4" bgcolor="#9E9EFF"><html:img height="1" alt=""

page="/images/spacer.gif" width="1" border="0"/></td> </tr></table><html:img height="10" alt="" page="/images/spacer.gif" width="1" border="0"/><br><!-- THIS WEEK'S FEATURES --><%@ include file="include/featureditems.inc"%><%@ include file="include/copyright.inc"%></body></html:html>

Page 51: Tema Struts 2

Ejemplo Tiles: storefront DefaultLayout.jsp

<%@ taglib uri=“/WEB-INF/struts-html.tld” prefix=“html” %><%@ taglib uri=“/WEB-INF/struts-bean.tld” prefix=“bean” %><%@ taglib uri=“/WEB-INF/tiles.tld” prefix=“tiles” %><html:html>

<head><title><bean:message key=“global.title”/></title><html:base/>

</head><body topmargin=“0” leftmargin=“0” bgcolor=“#FFFFFF”>

<tiles:insert attribute=“header”/><tiles:insert attribute=“menubar”/><tiles:insert attribute=“body-content”/><tiles:insert attribute=“copyright”/>

</body></html:html>

Page 52: Tema Struts 2

Ejemplo Tiles: storefront-defs.jsp

<%@ taglib uri=“/WEB-INF/tiles.tld” prefix=“tiles” %><tiles:definition

id=“storefront.default”page=“/layouts/storefrontDefaultLayout.jsp”scope=“request”>

<tiles:put name=“header” value=“/common/header.jsp”/>

<tiles:put name=“menubar” value=“/common/menubar.jsp”/>

<tiles:put name=“copyright” value=“/common/copyright.jsp”/>

</tiles:definition>

Page 53: Tema Struts 2

Ejemplo Tiles: index.jsp

<%@ taglib uri=“/WEB-INF/tiles.tld” prefix=“tiles” %><%@ include file=“../common/storefront-defs.jsp” %>

<tiles:insert beanName=“storefront.default” beanScope=“request”>

<tiles:put name=“body-content” value=“index-body.jsp”/></tile:insert>

Para más información sobre Tiles Framework ir a: http://www.lifl.fr/~dumoulin/tiles/index.html

Para instalar Tiles en Struts es necesario añadir una sección plug-in en struts-config.xml para la clase: org.apache.struts.tiles.TilesPlugin

Page 54: Tema Struts 2

Mi primera aplicación con Apache Struts Aplicación para llevar a cabo login

Una vez que el usuario ha hecho login las páginas cambian para indicar tal circunstancia

Consiste de dos pantallas: Página Welcome que saluda al usario y ofrece

enlaces a la aplicación Página Logon que permite al usuario introducir

username y password Esta página lleva a cabo la validación que los datos

introducidos son correctos

Page 55: Tema Struts 2

Welcome.html<HTML><HEAD><TITLE>Welcome World!!</TITLE><base

href="http://localhost:8080/logon/pages/Welcome.jsp"></HEAD><BODY><H3>Welcome World!</H3><UL><LI><a href="/logon/logon.do">Sign in</a></LI></UL><IMG src='struts-power.gif' alt='Powered by Struts'></BODY></HTML>

Page 56: Tema Struts 2

Welcome.jsp I<%@ taglib uri="/tags/struts-bean" prefix="bean" %><%@ taglib uri="/tags/struts-html" prefix="html" %><%@ taglib uri="/tags/struts-logic" prefix="logic" %><HTML><HEAD><TITLE>Welcome World!!</TITLE><html:base/></HEAD><BODY><logic:present name="user"><H3>Welcome <bean:write name="user" property="username"/>!</H3></logic:present><logic:notPresent scope="session" name="user"><H3>Welcome World!</H3></logic:notPresent><html:errors/><UL><LI><html:link forward="logon">Sign in</html:link></LI><logic:present name="user"><LI><html:link forward="logoff">Sign out</html:link></LI></logic:present></UL><IMG src='struts-power.gif' alt='Powered by Struts'></BODY></HTML>

Page 57: Tema Struts 2

Welcome.jsp II <html:base/> garantiza que referencias a imágenes o otros

recursos son relativas a la localización del JSP<logic:present name="user">

<H3>Welcome <bean:write name="user" property="username"/>!</H3>

</logic:present> Esta etiqueta personalizada asegura que el usuario solamente

es saludado si ha efectuado login <logic:notPresent> tiene el comportamiento opuesto<LI><html:link forward="logon">Sign in</html:link></LI> Struts reescribe automáticamente los enlaces para mantener

la sesión del usuario. También permite dar a los enlaces un nombre lógico y luego guardar los enlaces reales en un fichero de configuración.

Page 58: Tema Struts 2

Logon.html<HTML><HEAD><TITLE>Sign in, Please!</TITLE></HEAD><BODY><form name="logonForm" method="POST" action="/logon/LogonSubmit.do"><TABLE border="0" width="100%"><TR><TH align="right">Username:</TH><TD align="left"><input type="text" name="username" value=""></TD></TR><TR><TH align="right">Password:</TH><TD align="left"><input type="password" name="password" value=""></TD></TR><TR><TD align="right"><input type="submit" name="submit" value="Submit"></TD><TD align="left"><input type="reset" name="reset" value="Reset"></TD></TR></TABLE></form><script language="JavaScript" type="text/javascript"><!--document.forms["logonForm"].elements["username"].focus()// --></script></BODY></HTML>

Page 59: Tema Struts 2

Logon.jsp I<%@ taglib uri="/tags/struts-html" prefix="html" %><HTML><HEAD><TITLE>Sign in, Please!</TITLE></HEAD><BODY><html:errors/><html:form action="/LogonSubmit" focus="username"><TABLE border="0" width="100%"><TR><TH align="right">Username:</TH><TD align="left"><html:text property="username"/></TD></TR><TR><TH align="right">Password:</TH><TD align="left"><html:password property="password"/></TD></TR><TR><TD align="right"><html:submit/></TD><TD align="left"><html:reset/></TD></TR></TABLE></html:form></BODY></HTML>

Page 60: Tema Struts 2

Logon.jsp II<%@ taglib uri="/tags/struts-html"

prefix="html"%> La librería de etiquetas html definida por Struts es

disponible a la página <html:errors/> garantiza si ha habido algún error

durante el login, que estos errores sean visualizados<html:form action="/LogonSubmit"

focus="username"> Produce un formulario HTML para la entrada de datos.

También genera JavaScript para mover el cursor al campo username del formulario

La propiedad action hace referencia a un componente ActionMapping en el fichero de configuración de Struts dice al formulario que JavaBean (derivado de ActionForm) debe usar para poblar los controles de HTML.

Page 61: Tema Struts 2

Logon.jsp III

<html:text property="username"/> Crea un control de entrada HTML para un

campo de texto. Asignará a este campo la propiedad username del JavaBean de ayuda antes mencionado.

<html:password> crea un campo de entrada <html:submit> y <html:reset> generan

botones HTML Submit y Reset. Dos objetos serán invocados cuando se usen estos botones:

ActionForm Action

Page 62: Tema Struts 2

Configuración de la acción logon I

Configuración para la pantalla de logon: JSP hace referencia al /LogonSubmit ActionMapping

ActionMapping hace referencia a los objetos:

app.LogonForm describe propiedades usadas por el formulario logon

app.LogonAction lleva a cabo el procesamiento del formulario

Page 63: Tema Struts 2

Configuración de la acción logon II<html:form action="/LogonSubmit" focus="username"> La configuración asociada al atributo acción en Struts sería:<action path="/LogonSubmit" type="app.LogonAction" name="logonForm" scope="request" validate="true" input="/pages/Logon.jsp"/> path identicador único para el mapping type acción a invocar cuando el formulario es entregado name el helper JavaBean (ActionForm) a usarse con el formulario

HTML scope indica en qué contexto debe guardarse el ActionForm validate indica si es necesario invocar al método validate del

ActionForm antes de invocar al objeto Action input indica a donde ir si validate devuelve falso<form-bean name="logonForm" type="app.LogonForm"/> Este extracto del fichero de configuración relaciona el nombre lógico

logonForm con la clase app.LogonForm

Page 64: Tema Struts 2

LogonForm: un ejemplo de un ActionFormpublic ActionErrors validate(ActionMapping mapping,

HttpServletRequest request) {ActionErrors errors = new ActionErrors();if ((username == null) || (username.length() < 1))

errors.add ("username",new ActionError("error.username.required"));

if ((password == null) || (password.length() < 1))errors.add("password",new ActionError("error.password.required"));

return errors;} Si validate no devuelve null, entonces el ActionController servlet

guardará el objeto ActionErrors devuelto en el contexto request, bajo una clave conocida por la etiqueta html:errors

Los tokens error.username.required y error.password.required son claves que son utilizadas para mirar los strings correspondientes en el fichero de recursos de Struts

Recordar que cada Locale contiene su propio fichero de recursos lo que hace que los mensajes sean fácilmente localizables.

Page 65: Tema Struts 2

LogonAction: un ejemplo de un LogonAction Ipackage app;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import org.apache.struts.action.ActionServlet;

public final class LogonAction extends Action {// Validate credentials with business tierpublic boolean isUserLogon (String username,

String password) throws UserDirectoryException {return

(UserDirectory.getInstance().isValidPassword(username,password));} // end isUserLogon

Page 66: Tema Struts 2

LogonAction: un ejemplo de un LogonAction IIpublic ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,

HttpServletResponse response)throws IOException, ServletException {// Obtain username and password from web tierString username = ((LogonForm) form).getUsername();String password = ((LogonForm) form).getPassword();// Validate credentialsboolean validated = false;try { validated = isUserLogon(username,password);} catch (UserDirectoryException ude) { // couldn't connect to user directory ActionErrors errors = new ActionErrors();

errors.add (ActionErrors.GLOBAL_ERROR, new ActionError("error.logon.connect")); saveErrors(request,errors); // return to input page return (new ActionForward (mapping.getInput()));

}// Save our logged-in user in the session, because we use it again later.HttpSession session = request.getSession();session.setAttribute(Constants.USER_KEY, form);// Log this event, if appropriateif (servlet.getDebug() >= Constants.DEBUG) { StringBuffer message = new StringBuffer("LogonAction: User '"); message.append(username);

message.append("' logged on in session "); message.append(session.getId()); servlet.log(message.toString);

}// Return success

return (mapping.findForward (Constants.WELCOME));} // end perform} // end LogonAction

Page 67: Tema Struts 2

LogonAction: un ejemplo de un LogonAction III// Validate credentialsboolean validated = false;try {

validated = isUserLogon(username,password);} catch (UserDirectoryException ude) {

// couldn't connect to user directoryActionErrors errors = new ActionErrors();errors.add (ActionErrors.GLOBAL_ERROR,

new ActionError("error.logon.connect")); saveErrors(request,errors); // return to input page return (new ActionForward(mapping.getInput()));} Si un error es encontrado mientras se lleva a cabo la validación de la entrada del

usuario y una excepción es lanzada, entonces el error es transformado en un ActionError y el control es devuelto a la página de entrada. Lo mismo se lleva a cabo si se puede contactar al servicio de directorio pero el login del usuario no es correcto

return (mapping.findForward (Constants.WELCOME)); Un objeto de tipo ActionForward será devuelto al ActionServlet si todo va bien. En

este caso se envía control al forward success declarado en el fichero de configuración como:

<forward name=“success” path=“/pages/Welcome.jsp”/>

Page 68: Tema Struts 2

Modificaciones a realizar en guessing1. Modificar action /guess en struts-config.xml, haciendo que esa

acción esté asociada a la clase es.deusto.guessing.action.GuessingAction y al formulario es.deusto.guessing.form.GuessingForm.

2. Asegurarse que existe correspondencia entre clase guessing.jsp y GuessingForm

3. Asegurarse que un usuario después de haber hecho login pueda jugar una partida, el usuario podrá realizar intentos infinitamente, pero esos intentos hay que contabilizarlos y visualizarlos cada vez que el usuario falla o adivina el número

4. El número a adivinar es asociado a la sesión del usuario y generado la primera vez que la acción execute se ejecuta para un usuario

5. Idealmente crear una clase llamada Game que contenga el número a adivinar y el número de intentos fallidos

6. Modificar la aplicación de manera que nuevos usuarios puedan ser definidos y los datos de login de esos usuarios se salven en un fichero .properties.

Page 69: Tema Struts 2

Más Ejemplos

Para más ejemplos del uso de Struts visitar: http://struts.sourceforge.net/