Para hacer este tutorial vamos a partir del proyecto web Holamundo realizado anteriormente
Holamundo
En este ejemplo se ven con eclipse la utilización de los Action y los ActionForm así como la configuración del struts- confing, utilización y carga de imágenes y utilización de archivos css en proyectos struts.
No hay conexión para base de datos se deja para otros post y no se utiliza el DynaActionForm que los veremos en otros post.
Se presenta el interfaz gráfico de la apliación para un mejor entendimiento, tenemos un formulario de registro que toma el nombre el apellido y otros dos campos clave y confirmación de clave, todos estos campos deben ser rellenados por el usuario y se comprueba que la clave y su confirmación son iguales. El usuario tiene la posibilidad de cancelar el registro y vover a la pagina de registro desde la de cancelación.
Ventana de registro

creación de la página login.jsp con eclipse las demás páginas se realizarán de la misma forma (“cambiamos el nombre del la página)

código correspondiente al fichero login.jsp es el código asociado a la “ventana de registro”
Una de las características de struts es que tiene su propios tags para html, vienen siempre con la palabra html: y despues el nombre de la etiqueta en cuestion.
Para la categoría de j2ee de este sitio web ya hicieron ejemplos de integración de css con j2ee, comento esto porque hay una diferencia importante con struts. Para mucha gente que viene de otros lenguajes o de hacer jsp estaran acostumbrados a colocar el archivo css en un determinado directorio y enlazarlo mediante la etiquela “link”. Bien para que las css o las imágenes las podamos incluir en un proyecto struts es necesario incluir en el head de la página jsp de struts la etiqueta
Si nos fijamos en las jsp vemos que aparecen en todas ellas, lo que hace esta etiqueta es establecer el punto de referencia de la página con respecto al resto al resto de recursos del proyecto.
Ejemplo, si yo soy la página login.jsp y me dicen que hay una css en “../css/estilo.css” entonces se que tengo que
buscar en mi directorio padre y bajar al directorio css y alli encuentro estilo.css. Si no tengo la referencia base no puedo encontrar los recursos css ni de imagen.
Además en la cabecera de la jsp debemos de incluir el <%@taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html:html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title> <bean:message key="titulo.login"/></title> <html:base/> <link rel="stylesheet" type="text/css" href="../css/estilo.css" /> </head> <body> <div id="contenedor"> <h2> <bean:message key="titulo.login"/> </h2> <div id="errores"> <html:errors/> </div> <div id="imagen"> <html:img srcKey="login.imagen" titleKey="login.imagen.alt"/> </div> <div id="contenido"> <html:form action="loginAction" focus="nombre" styleId="formulario" method="post"> <div class="campo"> <bean:message key="login.nombre"/> <html:text property="nombre"/> </div> <div class="campo"> <bean:message key="login.apellidos"/> <html:text property="apellidos"/> </div> <div class="campo"> <bean:message key="login.clave" /> <html:password property="clave" maxlength="8" size="8"/> </div> <div class="campo"> <bean:message key="login.claveConfirmacion" /> <html:password property="claveConfirmacion" maxlength="8" size="8"/> </div> <html:submit styleClass="boton" value="enviar"/> <html:cancel styleClass="boton" value="cancelar"/> </html:form> </div> <div id="pie"> <p> www.railsymas.com </p> </div> </div> </body> </html:html> |
Se crean dos carpetas nuevas al proyecto llamadas imagenes y css (“cada uno las puede llamar como quiera mientras mantenga la correspondencia con otras partes del proyecto”)
Imagen de creación, carpeta imagenes

El fichero css estilo.css es el que se va a utilizar para la maquetación del ejemplo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #contenedor { width:600px; margin-left:auto; margin-right:auto; } .campo { margin-top:10px; } #imagen { float:right; } .boton { margin: 10px 5px; background-color:#554444; color:#fff; width:100px; } #formulario { margin-top:60px; font-size:16px; } #errores { background-color:#e6dfd5; color:#424c56; } #errores ul li { list-style-image:url("../imagenes/flechaderecha.png"); } #errores ul { border-color:#f00; } h2 { text-align:center; } #pie { clear:both; height:30px; background-color:#424c56; } #pie p { text-align:right; font-size:14px; background-color:#e6dfd5; } |
Código del fichero de propiedades MessageResources_es_ES
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #claves para login titulo.login=Registro usuario login.nombre = nombre login.apellidos = apellidos login.claveConfirmacion=confirmación de password login.clave=password login.imagen.alt= icono usuario login.imagen = ../imagenes/usuario.png; #claves de error error.login.nombre = falta el campo nombre error.login.apellidos = falta el campo apellidos error.login.clave = falta el campo clave error.login.claveConfirmacion = falta el campo claveconfirmacion error.login2 = repite la clave #claves para satisfactoria satisfactoria.titulo = Resgistro correcto satisfactoria.imagen = ../imagenes/correcto.png satisfactoria.imagen.alt = imagen correcto satisfactoria.mensaje = Te has registrado correctamente #claves para cancelada cancelada.titulo = Registro cancelado cancelada.mensaje = No te has registrado en el sistema cancelada.imagen.alt = imagen cancelado cancelada.imagen = ../imagenes/cancelado.png cancelada.login = Cancelación #claves para welcome welcome.title=Holamundo Struts welcome.heading=Bienvenida! welcome.message=Holamundo Struts |
Creamos la nueva clase FormularioFrom dentro del package formularios

Código de la clase java “para el ActionForm” la llamamos FormularioForm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | package formularios; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionMessage; import javax.servlet.http.HttpServletRequest; public class FormularioForm extends ActionForm { static final long serialVersionUID = 1L; private String nombre; private String apellidos; private String clave; private String claveConfirmacion; //métodos getters y setters del formulario public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getApellidos() { return apellidos; } public void setApellidos(String apellidos) { this.apellidos = apellidos; } public String getClave() { return clave; } public void setClave(String clave) { this.clave = clave; } public String getClaveConfirmacion() { return claveConfirmacion; } public void setClaveConfirmacion(String claveConfirmacion) { this.claveConfirmacion = claveConfirmacion; } //método que permite la validación de los campos del formulario public ActionErrors validate ( ActionMapping mapping, HttpServletRequest request ) { //creamos un nuevo objeto ActionErrors ActionErrors errores = new ActionErrors(); if ( nombre == null ||nombre.length() == 0) { errores.add("nombre", new ActionMessage("error.login.nombre")); } if ( apellidos == null ||apellidos.length() == 0 ) { errores.add("apellidos", new ActionMessage("error.login.apellidos")); } if ( clave ==null || clave.length() == 0) { errores.add("clave", new ActionMessage("error.login.clave")); } if ( claveConfirmacion == null ||claveConfirmacion.length() == 0 ) { errores.add("claveConfirmacion", new ActionMessage("error.login.claveConfirmacion")); } if ( !clave.equals(claveConfirmacion) ) { errores.add("confirmacion", new ActionMessage("error.login2")); } return errores; } //método para resetear los campos del formulario public void reset () { this.nombre = null; this.apellidos = null; this.claveConfirmacion = null; this.clave = null; } } |
Cremos una nueva clase Action dentro del package Acciones

Código java de la clase “Action” la llamamos AccionLogin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package acciones; import org.apache.struts.action.Action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; import formularios.*; //clase action public class AccionLogin extends Action { private String resultado; // creación del método execute public ActionForward execute ( ActionMapping mapping, ActionForm form ,HttpServletRequest request, HttpServletResponse response ) throws Exception { //si el usuario pulsa el botón de cancelado if ( this.isCancelled(request) ) { //como tenemos en el método execute el objeto ActionMapging podemos mandar a un reenvio del struts-config return mapping.findForward("cancelada"); } else { //creamos un objeto formularioForm FormularioForm formularioform = (FormularioForm) form; return mapping.findForward("satisfactoria"); } } } |
Si intentamos ejecutar una clase Action sin su correspondiente ActionForm nos da el siguiente error al ejecutar el proyeto (“sale mucho más por pantalla pero son las dos líneas claves”)
1 2 3 | javax.servlet.ServletException: Form bean not specified on mapping for action: "loginAction" org.apache.jasper.JasperException: Exception in JSP: /pages/login.jsp |
Ventana de errores campos vacíos

Error de clave (“no son iguales”)

En la segunda parte de este ejemplo formulario login struts 2 parte eclipse
Se ven las páginas cancelada.jsp y satisfactoria.jsp así como la cofiguración del struts-config.xml y explicaciones correspondientes.
Agradecimientos por las imágenes utilizadas a vía www.webintenta.com
http://www.smashingmagazine.com/2008/08/27/on-stage-a-free-icon-set/
http://nick7even.deviantart.com/gallery/

No se que ventaja le ve la gente a Struts, el ejemplo que explicas aquí me parece mucho más complicado de codificar que por ejemplo con php que serían muy pocas lineas.
Quizás sea lo que demanden las empresas y lo que tiendan a enseñar después de cursos de universidad, pero a mi no me parece nada práctico.
La curva de aprendizaje de cualquier framework es superior al lenguaje base del que parte. Es más facil saber j2ee que struts, de la misma manera que es más facil saber de php que symfony o cakephp o zendframework. Los frameworks tienen una serie de reglas muy fijas y eso tiene una ventaja en proyectos con muchos programadores, porque al compartir el conocimiento de esas reglas se facilita el que otras personas puedan entender el código rápidamente. Los frameworks suelen tener diferentes capas de abstración posibilitando que diferentes programadores esten trabajando en distintas capas de ahí el MVC, el llamado “modelo vista controlador”.
Donde radica la diferencia es en los diferentes frameworks y la rapidez y el nivel de abstración entre las capas y eso es lo que hace a unos frameworks mejores unos que otros.
Basicamente la principal ventaja de Struts, es que tienes un codigo mucho mas modularizado y facil de mantener por mas que este crezca a lo largo del tiempo.
Esto no pasa cuando no se utiliza un framework. Provocando que cada programador trabaje a su “manera”.
Muy buen Tutorial…
Excenle tutorial muy didáctico