Struts [parte I] Requerimientos Contenedor web Colocar en la carpeta “lib” de la aplicación a...

45
www.softclear.net Struts [parte I]

Transcript of Struts [parte I] Requerimientos Contenedor web Colocar en la carpeta “lib” de la aplicación a...

www.softclear.net

Struts

[parte I]

www.softclear.net

Módulo 1

Introducción a Struts

www.softclear.net

¿Qué es Struts?●Marco de trabajo MVC de Apache para la tecnología Java EE

●Marco de trabajo (framework): extensión de un lenguaje por medio de una jerarquía de librerías y/o clases

JVM

API

Framework

www.softclear.net

Visión Java EE + Struts

JVM

API Java SE

Contenedor

API Java EE

Struts Framework

www.softclear.net

Patrón MVC●Modelo-Vista-Controlador

●Separación de la lógica de negocio de la lógica de presentación

●Struts usa MVC en conjunto con Front Controller, Dispatcher, ...

www.softclear.net

Ventajas●Velocidad de desarrollo

●Controlador pre-programado

●Librerías de etiquetas para evitar “scriptlets”

●Flujo de acciones basado en XML

●Extensible con EL

●Permite el desarrollo separado de lógica de negocio y lógica de presentación con personal especializado

www.softclear.net

Requerimientos●Contenedor web

●Colocar en la carpeta “lib” de la aplicación a desarrollar:

● commons-*.jar, paquete de manipulación de archivos XML de Apache/Jakarta

● struts.jar, paquete de clases definidas en el marco de trabajo Struts

●Los archivos struts-*.tld, librerías de etiquetas Struts para interfaces web, deben agregarse y especificar su ruta en el descriptor de despliegue web.xml

Todos los archivos son descargables de la sección de Struts en www.apache.org

www.softclear.net

Carpetas y archivos

www.softclear.net

Clases principales●ActionServlet: Servlet pre-programado para el marco de trabajo Struts. Hace las veces de Front Controler.Su ruta es org.apache.struts.action.ActionServlet

●Action: clase que implementa el patrón Command a fin de ejecutar determinadas acciones sobre el modelo dependiendo de la petición que se le haga al ActionServlet. Hereda de org.apache.struts.action.Action

www.softclear.net

Clases principales●ActionForm: Java Bean que contiene los datos de la solicitud hecha por un formulario al ActionServlet y los valida. Hereda de org.apache.struts.action.ActionForm

●ActionMapping: representa las acciones y rutas escritas por el programador en el archivo de configuración de Struts. Su ruta es org.apache.struts.action.ActionMapping

www.softclear.net

Clases principales●ActionForward: representa el redireccionamiento de la petición HTTP a un url específico. Su ruta es org.apache.struts.action.ActionForward

●ActionError: representa un mensaje de error. Su ruta es org.apache.struts.action.ActionError.

(Esta clase está deprecada y se reemplaza por org.apache.struts.action.ActionMessage)

Más información: http://struts.apache.org/1.3.8/apidocs/index.html

www.softclear.net

Archivo web.xml<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>

<jsp-config> <taglib> <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> </jsp-config>

</web-app>

www.softclear.net

Módulo 2

Caso Práctico

www.softclear.net

Caso práctico

www.softclear.net

ActionForm

import org.apache.struts.action.ActionFormpublic class RegistroForm extends ActionForm{

protected String username;protected String password1;protected String password2;

public String getUsername() {return this.username;}public String getPassword1() {return this.password1;}public String getPassword2() {return this.password2;}

public void setUsername(String username) {this.username = username;}public void setPassword1(String password1) {this.password1 = password1;}public void setPassword2(String password2) {this.password2 = password2;}

}

www.softclear.net

Actionimport org.apache.struts.action.*;import javax.servlet.http.*;

public class RegistroAction extends Action{public ActionForward execute(ActionMapping mapping, ActionForm form,

HttpServletRequest request, HttpServletResponse response){

RegistroForm rf = (RegistroForm) form;

String username = rf.getUsername();String password1 = rf.getPassword1();String password2 = rf.getPassword2();

if(password1.equals(password2)){try{

UserDirectory.getInstance().setUser(username, password1);return mapping.findForward(“exito”);

}catch(Exception e){e.printStackTrace();return mapping.findForward(“fracaso”);

}}else{

return mapping.findForward(“fracaso”);}

}}

www.softclear.net

struts-config.xml

<struts-config>

<form-beans><form-bean name=”registroForm” type=”RegistroForm”/>

</form-beans>

<action-mappings><action path=”/registro” name=”registroForm”

type=”RegistroAction” input=”/registro.jsp”><forward name=”exito” path=”/exito.html” /><forward name=”fracaso” path=”/fracaso.html” />

</action></action-mappings>

</struts-config>

www.softclear.net

exito.html y fracaso.html

exito.html<html>

<body><h1>Exito!</h1>

</body></html>

fracaso.html<html>

<body><h1>

<font color=”#ff0000”>Fracaso!

</font></h1>

</body></html>

www.softclear.net

registro.jsp

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

<body>

<html:form action=”registro.do”>Login: <html:text property=”username”/> <br/>Password: <html:password property=”password1”/> <br/>Confirme su password: <html:password property=”password1”/> <br/><html:submit value=”Registro”/>

</html:form></body>

</html>

www.softclear.net

Validación en el ActionForm[hasta Struts 1.2]

import javax.servlet.http.*;import org.apache.struts.action.*;

public class RegistroForm extends ActionForm{protected String username;//...

public String getUsername() {return this.username;}//...

public void setUsername(String username) {this.username = username;}//...

public ActionErrors validate (ActionMapping mapping, HttpServletRequest request){

ActionErrors errors = new ActionErrors();if((username == null) || (username.trim().equals(“”)){

ActionError error = new ActionError(“username.requerido”);errors.add(“username”, error);

}return errors;

}}

www.softclear.net

Validación en el ActionForm[desde Struts 1.2]

import javax.servlet.http.*;import org.apache.struts.action.*;

public class RegistroForm extends ActionForm{protected String username;//...

public String getUsername() {return this.username;}//...

public void setUsername(String username) {this.username = username;}//...

public ActionErrors validate (ActionMapping mapping, HttpServletRequest request){

ActionErrors errors = new ActionErrors();if((username == null) || (username.trim().equals(“”)){

ActionMessage error = new ActionMessage(“username.requerido”);errors.add(“username”, error);

}return errors;

}}

www.softclear.net

Validación en el ActionForm

<struts-config>

<form-beans><form-bean name=”registroForm” type=”RegistroForm”/>

</form-beans>

<action-mappings><action path=”/registro” name=”registroForm”

type=”RegistroAction” input=”/registro.jsp”validate=”true”>

<forward name=”exito” path=”/exito.html” /><forward name=”fracaso” path=”/fracaso.html” />

</action></action-mappings>

</struts-config>

www.softclear.net

Mensajes en i18n●El archivo por defecto de todos los mensajes es ApplicationResources.properties

●Ejemplo del contenido de un archivo ApplicationResources.properties:

username.requerido = <b>Por favor, ingrese el login</b>username.default = Pedro Perez

●La ruta del archivo de propiedades debe ser especificada en el archivo de configuración de struts y es relativa a la carpeta classes dentro de WEB-INF:

<struts-config><message-resources parameter="com/myapp/struts/ApplicationResource" />

</struts-config>

www.softclear.net

Mensajes e i18n●Para usar internacionalización solo se debe crear el archivo del idioma especificando en el nombre de este el acrónimo que representa dicho idioma. El archivo debe ser almacendo junto al archivo por defecto ApplicationResources.properties. Ej: ApplicationResources_es.properties

●El browser del cliente está definido por lo general para un idioma de preferencia, si existe el archivo ApplicationResources_XX.properties para dicho idioma, este es seleccionado, en caso contrario se selecciona el archivo de propiedades por defecto

●Ejemplo para ApplicationResources_en.properties:

username.requerido = <b>Please, insert a login</b>username.default = John Doe

www.softclear.net

Módulo 3

Librerías de etiquetas

www.softclear.net

Grupos de etiquetas●HTML: struts-html.tld, de uso frecuente en la creación de formularios HTML que introducen datos al marco de trabajo.

[http://struts.apache.org/1.2.7/userGuide/struts-html.html]

●Bean: struts-bean.tld, manipulación de Java Beans análogo a los JSTL.

[http://struts.apache.org/1.2.7/userGuide/dev_bean.html]

●Logic: struts-logic.tld, manejo dinámico de condiciones análogo a los JSTL.

[http://struts.apache.org/1.2.7/userGuide/dev_logic.html]

www.softclear.net

Grupos de etiquetas●Tiles: struts-tiles.tld, etiquetas especializadas en el manejo de plantillas.

[http://struts.apache.org/1.2.7/userGuide/dev_tiles.html]

●Nested: struts-nested.tld, extensión utilitaria de las etiquetas anteriores.

[ http://struts.apache.org/1.2.7/userGuide/dev_nested.html]

www.softclear.net

Ejemplo clásico de errores<%@ taglib prefix="html" uri="/struts-html.tld" %><%@ taglib uri=”/WEB-INF/struts-html.tld” prefix=”html”>

<html><body>

<html:form action=”registro.do”>

<!--Imprimir solo los errores de login--><!--La propiedad username en insertada--><!--al adjuntar el error en el ActionForm-->

<div align="center"><html:errors property=”username”/>

</div>

Login: <html:text property=”username”/> <br/>Password: <html:password property=”password1”/> <br/>Confirme su password: <html:password property=”password1”/> <br/>

<html:submit value=”Registro”/>

</html:form></body>

</html>

www.softclear.net

...un último pasoPara que los errores salgan en la página del formulario que la originó, no es necesario tener un forward asociado:

<struts-config>

<form-beans><form-bean name=”registroForm” type=”RegistroForm”/>

</form-beans>

<action-mappings><action path=”/registro” name=”registroForm”

type=”RegistroAction” input=”/registro.jsp”><forward name=”exito” path=”/exito.html” />

</action></action-mappings>

</struts-config>

www.softclear.net

Ejemplo clásico de errores<%@ taglib prefix="html" uri="/struts-html.tld" %><%@ taglib uri=”/WEB-INF/struts-html.tld” prefix=”html”>

<html><body>

<!--Imprimir todos los errores --><div align="center">

<html:errors/></div>

<html:form action=”registro.do”>

Login: <html:text property=”username”/> <br/>Password: <html:password property=”password1”/> <br/>Confirme su password: <html:password property=”password1”/> <br/>

<html:submit value=”Registro”/>

</html:form></body>

</html>

www.softclear.net

Módulo 4

Ejercicios propuestos

www.softclear.net

RetosA fin de obtener una mayor experticia en el marco de trabajo Struts, se recomienda llevar a cabo los siguientes retos:

●Crear una aplicación basada en Struts que imprima en una página JSP una lista de objetos colocados en la sesión por un Action y sus errores, con la menor cantidad de código posible utilizando Expression Language, JSTL y Struts Tag Libraries.

●Modificar el idioma del site por medio de Struts una vez que un usuario seleccione su idioma de una lista sin depender del idioma del browser

●Realizar un request en Ajax a un url esperado por el ActionServlet de Struts

●Realizar una solicitud de información en un dispositivo móvil por medio de un HttpConnection a un ActionServlet

www.softclear.net

Módulo 5

Struts + XDoclet

www.softclear.net

DRY●DRY – Don´t Repeat Yourself

●Principio de diseño

●Java EE posee graves problemas sobre este principio

●Struts no escapa del problema● Programar los Action y ActionForm es repetitivo● Los tags xml del archivo de configuración de Struts son

repetitivos● Al crear un Action o un ActionForm hay que alterar el archivo

de configuración, por lo que la información está en dos lugares● El Action no sabe el flujo a recorrer, él consulta el archivo de

configuración xml

www.softclear.net

XDoclet●Motor de plantilla de metadatos [programación orientada a atributos]

●Originalmente creado para solventar el problema de DRY en los EJB

●Opera como tareas de Ant [similar a “make”] que facilita la ejecución de tareas rutinarias

●Sitio web: http://www.xdoclet.org/

●En los últimos años ha extendido su comportamiento en pro de facilitar el desarrollo de diversos componentes, entre ellos Struts

www.softclear.net

Problema●¿Qué pasa si eliminamos un Action o un ActionForm?Hay que eliminar a mano los tags correspondientes del archivo de configuración

●¿Qué pasa si olvidamos eliminar los tags en el archivo de configuración?Error

●Este proceso es frecuente y depende mucho del ser humano, del desarrollador

www.softclear.net

Solución●XDoclet provee un mecanismo simple para la generación del archivo de configuración y la consolidación de información en un solo lugar: la clase correspondiente

●De esta forma la clase contiene toda la información pertinente a ella y solo a ella

●Al ser eliminada la clase, también es eliminada toda información relativa a ella puesto que no se generará de nuevo el archivo de configuración con la información que ella provee

www.softclear.net

Solución●XDoclet provee un mecanismo simple para la generación del archivo de configuración y la consolidación de información en un solo lugar: la clase correspondiente

●De esta forma la clase contiene toda la información pertinente a ella y solo a ella

●Al ser eliminada la clase, también es eliminada toda información relativa a ella puesto que no se generará de nuevo el archivo de configuración con la información que ella provee

www.softclear.net

Ejemplo - build.xml<!--archivo de ant build.xml-->

<target name="webdoclet" depends="init">

<taskdef name="webdoclet" classname="xdoclet.modules.web.WebDocletTask"><classpath>

<path refid="xdoclet.classpath" /></classpath>

</taskdef>

<!--correr con "-Dxdoclet.force=true" para forzar la creacion de arch.-->

<webdoclet destdir="${build.web.dir}/WEB-INF" force="${xdoclet.force}" mergedir="metadata">

<fileset dir="src" />

<strutsconfigxml version="1.1" xmlencoding="ISO-8859-1" validateXML="true" templateFile="metadata/struts/struts_config_xml.xdt" mergeDir="metadata/struts" />

<strutsvalidationxml /></webdoclet>

</target>

www.softclear.net

Ejemplo - build.xml<!--archivo de ant build.xml-->

<target name="webdoclet" depends="init">

<taskdef name="webdoclet" classname="xdoclet.modules.web.WebDocletTask"><classpath>

<path refid="xdoclet.classpath" /></classpath>

</taskdef>

<!--correr con "-Dxdoclet.force=true" para forzar la creacion de arch.-->

<webdoclet destdir="${build.web.dir}/WEB-INF" force="${xdoclet.force}" mergedir="metadata">

<fileset dir="src" />

<strutsconfigxml version="1.1" xmlencoding="ISO-8859-1" validateXML="true" templateFile="metadata/struts/struts_config_xml.xdt" mergeDir="metadata/struts" />

<strutsvalidationxml /></webdoclet>

</target>

Localización de los archivos .jar

Directorio destino

Directorio fuente

Directorio de archivos a incluir en el struts-config.xml

Genera el archivo validate.xml

www.softclear.net

Merge <strutsconfigxml version="1.1" xmlencoding="ISO-8859-1" validateXML="true" templateFile="metadata/struts/struts_config_xml.xdt" mergeDir="metadata/struts" />

●El directorio indicado por “mergeDir” es la fuente de los tags xml que no serán mantenidos por XDoclet

●Los archivos que contiene son:● struts-data-sources.xml● struts-forms.xml● global-exceptions.xml● global-forwards.xml● struts-actions.xml● struts-controller.xml● struts-message-resources.xml● struts-plugins.xml

www.softclear.net

Action/** * @struts.action name="registroForm" path="/registro" * scope="request" validate="true" input="/registro.jsp" * * @struts.action-forward name="exito" path="/exito.html" * * @struts.action-forward name="fracaso" path="/fracaso.html" */import org.apache.struts.action.*;import javax.servlet.http.*;

public class RegistroAction extends Action{

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

RegistroForm rf = (RegistroForm) form;

String username = rf.getUsername();String password1 = rf.getPassword1();

UserDirectory.getInstance().setUser(username, password1);return mapping.findForward(“exito”);

}}

www.softclear.net

ActionForm/** * @struts.form name="registroForm" */import javax.servlet.http.*;import org.apache.struts.action.*;

public class RegistroForm extends ActionForm{

protected String username;//...

public String getUsername() {return this.username;}//...

public void setUsername(String username) {this.username = username;}//...

public ActionErrors validate (ActionMapping mapping, HttpServletRequest request){

ActionErrors errors = new ActionErrors();if((username == null) || (username.trim().equals(“”)){

ActionMessage error = new ActionMessage(“username.requerido”);errors.add(“username”, error);

}return errors;

}}

www.softclear.net

Validación en el ActionForm

<struts-config>

<form-beans><form-bean name=”registroForm” type=”RegistroForm”/>

</form-beans>

<action-mappings><action path=”/registro” name=”registroForm”

type=”RegistroAction” input=”/registro.jsp”validate=”true”>

<forward name=”exito” path=”/exito.html” /><forward name=”fracaso” path=”/fracaso.html” />

</action></action-mappings>

</struts-config>

www.softclear.net

Requerimientos e instalación●Ant 1.5 en adelante

●“tools.jar” debe estar en <directorio jdk>/lib para manipular del jdk