Post on 11-Jul-2015
mayo de 2005
Validación del input de usuario
Introducción Toda aplicación web debería chequear siempre la entrada del usuario
Los campos HTML son demasiado genéricos (aceptan todo) Struts proporciona dos vías de validación
Validación manual En los Action
Todo el control (tenemos acceso a lógica de negocio, etc.) Repetición de código en multiples Actions Escribir las reglas de validación uno mismo
En los ActionForm En los métodos set
Impedir valores “malignos” En validate()
No tan poderoso como en Action pero menos costoso Muestra página de entrada automáticamente si falla Requiere igualmente escribir reglas de validación
Validación automática Struts proporciona comprobaciones automáticas para casos comunes También validación automática en cliente (javascript)
Validación en el Action
Solución más flexible pero más costosa Procedimiento
Recuperar datos de ActionForm Por cada valor incorrecto o no presente
Añadir mensaje de error al propio ActionForm Utilizar mapping.findForward para devolver código de error en
cada caso
En struts-config.xml mapear todos los errores al mismo formulario de entrada
Utilizar bean:write para mostrar mensajes de error (si contienen código HTML usar filter=“false”)
Validación en el ActionForm
Lógica de validación dentro de validate() Si no hay errores devolver null o objeto ActionErrors vacío Por cada error
Añadir ActionMessage con nombre y clave a ActionErrors Cada clave corresponde a un mensaje de properties (i18n)
Si se devuelve ActionErrors no vacío Struts redirecciona automáticamente al formulario de entrada
Crear fichero properties con mensajes de error El fichero debe estar declarado en struts-config.xml
En el formulario utilizar el tag: <html:errors /> El Action no necesita lógica de validación
Validación en el ActionForm (II)
Varios Action pueden usar el mismo ActionForm
¿Qué ocurre si uno no requiere validación?
<action path="..."type="somePackage.SomeClass"name="someFormBean"scope="request"input="/somePath/original-form.jsp"validate="false">
<forward name="..." path"..."/></action>
Ejemplo 1: Elección de formato
Formulario que pide parámetros de formato de una página de resultados:
Tres tipos de letra (para title, heading, y body) Dos colores (fondo y letra) Se utiliza <html:errors/> para mostrar los mensajes
El ActionForm Recoge los datos del formulario y comprueba en validate()
Action No tiene código de validación
struts-config.xml Indica path a formulario de entrada en argumento del action
input.
Ejemplo 1: ActionForm
ActionForm FormatFormBean. Método validate():public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (isMissing(getTitleSize())) { errors.add("title", new ActionMessage("titleSize.required")); } if (isMissing(getHeadingSize())) { errors.add("heading", new ActionMessage("headingSize.required")); } if (isMissing(getBodySize())) { errors.add("body", new ActionMessage("bodySize.required")); } if (isMissing(getBgColor())) { errors.add("bg", new ActionMessage("bgColor.required")); } if (isMissing(getFgColor())) { errors.add("fg", new ActionMessage("fgColor.required")); } else if (getFgColor().equals(getBgColor())) { errors.add("fg", new ActionMessage("colors.notMatch")); } return(errors); }
Ejemplo 1: Mensajes de error
Fichero de properties con mensajes. MessageResources.properties:
# -- Standard errors --errors.header=<UL>errors.prefix=<LI><B><FONT COLOR="RED">errors.suffix=</FONT></B></LI>errors.footer=</UL># -- Custom validation messages --titleSize.required=Se requiere un tamaño para el título.headingSize.required=Se requiere un tamaño para el encabezado.bodySize.required=Se requiere un tamaño para el cuerpo.bgColor.required=Se requiere un color para el fondo.fgColor.required=Se requiere un color para el texto.colors.notMatch=Los colores de fondo y texto han de ser diferentes.
Ejemplo 1: Configuración Fichero de struts-config.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config> <form-beans> <form-bean name="formatFormBean" type="app.FormatFormBean"/> </form-beans> <action-mappings> <action path="/actions/showSample" type="app.ShowSampleAction" name="formatFormBean" scope="request" input="/forms/index.jsp"> <forward name="success" path="/WEB-INF/results/sample.jsp"/> </action> </action-mappings> <message-resources parameter="MessageResources" null="false"/></struts-config>
Ejemplo 1: Formulario Fichero de entrada forms/index.jsp:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE>Elige el formato</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><H1 ALIGN="CENTER">Elige el formato</H1>Elige el tamaño de letra y los colores para mostrar la información de su CV.<P><CENTER><%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %><html:errors/><html:form action="/actions/showSample"> Tamaño título: <html:text property="titleSize"/><BR> Tamaño encabezado: <html:text property="headingSize"/><BR> Tamaño cuerpo: <html:text property="bodySize"/><BR> Color fondo: <html:text property="bgColor"/><BR> Color letra: <html:text property="fgColor"/><BR> <html:submit value="Show Sample"/></html:form></CENTER></BODY></HTML>
Ejemplo 1: Action El fichero Action no requiere hacer ninguna validación.
package app;
import javax.servlet.http.*;import org.apache.struts.action.*;
public class ShowSampleAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return(mapping.findForward("success")); }}
Ejemplo 1: Resultados Tras construir el proyecto y desplegar el war
accedemos al formulario de entrada: http://localhost:8080/struts-manual-validation/forms/index.jsp
Ejemplo 1: Resultados (II)
Si dejamos sin rellenar algún campo nos lo indica y nos deja los que ya hemos rellenado
Ejemplo 1: Resultados (III) Si rellenamos todos los campos se muestra resultado con formato
(/WEB-INF/results/sample.jsp): Eligiendo por ejemplo tamaños de letra: 22,18 y 10, y colores ‘blue’ y ‘yellow’
obtendríamos:
Ejemplo 2: Mensajes parametrizados
Vamos a incorporar mensajes de error con parámetros Menos necesidad de mensajes de error Más información con valores de ejecución
En el fichero MessagesResource.properties: Insertamos en los mensajes {0}, {1}, {2}, … donde queramos
que vayan los parámetros Recoge los datos del formulario y comprueba en validate()
ActionForm En validation() habrá que pasar los argumentos en el
constructor de cada ActionMessage (hasta 4). Si se requieren más array
Ejemplo 2: ActionForm Creamos FormatFormBean2 partiendo de FormatFormBean. Vemos los
cambios de validate(): public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (isMissing(getTitleSize())) { errors.add("titleSizeMissing", new ActionMessage("value.required", "Tamaño del título")); } else if (!isInt(getTitleSize())) { errors.add("titleNotInt", new ActionMessage("value.int","tamaño del título",getTitleSize())); } if (isMissing(getHeadingSize())) { errors.add("headingSizeMissing", new ActionMessage("value.required","Tamaño del título")); } else if (!isInt(getHeadingSize())) { errors.add("headingNotInt", new ActionMessage("value.int", "tamaño del título",getHeadingSize())); } if (isMissing(getBodySize())) { errors.add("bodySizeMissing",new ActionMessage("value.required","tamaño del texto del cuerpo")); } else if (!isInt(getBodySize())) { errors.add("bodyNotInt",new ActionMessage("value.int","tamaño del texto del cuerpo",getBodySize())); } if (isMissing(getBgColor())) { errors.add("bgColorMissing", new ActionMessage("value.required","Color de fondo")); } if (isMissing(getFgColor())) { errors.add("fgColorMissing", new ActionMessage("value.required","Color de fuente")); } else if (getBgColor().equals(getFgColor())) { errors.add("colorsIdentical",new ActionMessage("colors.match",getBgColor())); } return(errors); }
Ejemplo 2: Mensajes de error
Creamos otro fichero de error MessageResources2.properties con las cadenas que aceptan argumentos:
# -- Standard errors --errors.header=<UL>errors.prefix=<LI><B><FONT COLOR="RED">errors.suffix=</FONT></B></LI>errors.footer=</UL># -- Custom validation messages --value.required=Se necesita {0}.value.int=Se requiere un número para {0}; "{1}" no es un entero.colors.match=Los colores de fondo y fuente son ambos "{0}".
Ejemplo 2: Configuración Añadimos entrada para nuevo message-resources esta vez indicándole un nombre con argumento key y una
entrada para otro Action que reaprovecha la clase de antes pero usa nuevo ActionForm
<struts-config> <form-beans> <form-bean name="formatFormBean" type="app.FormatFormBean"/> <form-bean name="formatFormBean2" type="app.FormatFormBean2"/> </form-beans> <action-mappings> <action path="/actions/showSample" type="app.ShowSampleAction" name="formatFormBean" scope="request" input="/forms/index.jsp"> <forward name="success" path="/WEB-INF/results/sample.jsp"/> </action> <action path="/actions/showSample2" type="app.ShowSampleAction" name="formatFormBean2" scope="request" input="/forms/index2.jsp"> <forward name="success" path="/WEB-INF/results/sample.jsp"/> </action> </action-mappings> <message-resources parameter="MessageResources" null="false"/> <message-resources parameter="MessageResources2" key="withArgs" null="false"/></struts-config>
Ejemplo 2: Formulario Creamos index2.jsp a partir de index.jsp
Cambiamos en <errors> la referencia al resource bundle. Esta vez no es el de por defecto Cambiamos action a showSample2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE>Elige el formato</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><H1 ALIGN="CENTER">Elige el formato</H1>Elige el tamaño de letra y los colores para mostrar la información de su CV.<P><CENTER><%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %><html:errors bundle="withArgs"/><html:form action="/actions/showSample2"> Tamaño título: <html:text property="titleSize"/><BR> Tamaño encabezado: <html:text property="headingSize"/><BR> Tamaño cuerpo: <html:text property="bodySize"/><BR> Color fondo: <html:text property="bgColor"/><BR> Color letra: <html:text property="fgColor"/><BR> <html:submit value="Show Sample"/></html:form></CENTER></BODY></HTML>
Ejemplo 2: Resultados
Ahora el formulario muestra errores más detallados
Validación automática
Struts dispone de un validador automático válido para muchas situaciones
Permite utilizar reglas de validación estándar
Funciona en el servidor y opcionalmente también en el cliente (javascript)
Se describe a través de ficheros XML
Validación en cliente vs Validación en servidor
Validación en cliente Javascript verifica campos Cuadros de diálgo muestran errores No se envían datos si hay algo incorrecto Es rápida pero puede saltarse deliberadamente (opciones
navegador) y no permite comprobaciones exhaustivas
Validación en servidor El código Java en el servidor verifica entrada del form. Obligatoria Permite volver a mostrar formulario con advertencias y
campos rellenados
Utilización de validación automática
Configuración adicional struts-config.xml Habilitar el validador automático
<plug-inclassName="org.apache.struts.validator.ValidatorPlugIn"><set-property property="pathnames"value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/></plug-in>
Utilización de validación automática (II)
Poner reglas de validación en validation.xml Utilizar form-bean para identificar ActionForm
<form name="beanNameFromStrutsConfig">
Utilizar <field property=“..” depends=“..”> para identificar propiedad del ActionForm y qué regla de chequeo usar<field property=“propName” depends=“ruleName”>
Utilizar <argX > para pasar argumentos a los mensajes de error<field property=“propName” depends=“ruleName”>
<arg0 key=“key.Name”/>
</field>
Estructura de validation.xml Etiquetas globales <form-validation> y <formset> Referencia a ActionForms declarados en struts-config.xml:
<form name=“beanName”/> Regla de validación por campo
<field property=“firstName” depends=“required”/> Tipos de comprobaciones (depends):
required. El cambo debe tener un valor mask. Debe seguir una expresión regular email. Campo de tipo email creditCard. Número de tarjeta de crédito válido (pruebas: 411111111111)
Utilizar <field property=“..” depends=“..”> para identificar propiedad del ActionForm y qué regla de chequeo usar<field property=“propName” depends=“ruleName”>
Utilizar <argX > para pasar argumentos a los mensajes de error<field property=“propName” depends=“ruleName”>
<arg0 key=“key.Name”/></field>
Dentro de field <arg0 key="property.subname"/>
Reemplaza {0} con el valor dado de la propiedad en mensaje property.subname
Utilización de validación automática (III)
Ejemplo de validation.xml<formset>
<form name="orderFormBean">
<field property="firstName"
depends="required">
<arg0 key="inputForm.firstName"/>
</field>
</form>
…
</formset>
Utilización de validación automática (IV)
Los bean de formulario han de extenderse de ValidatorForm en vez de ActionForm.
Para habilitar Javascript, añadir tags al JSP con formulario: <html:javascript formName="beanName"/> Y añadir a <html:form> el argumento:
onsubmit="return validateBeanName(this);"
Ejemplo 3: La tienda de pelis
Vamos a crear un sitio con un formulario de rellenado de datos para sitio de compra online
Habrá que definir un validation.xml Ahora AcitionForm (ValidatorForm en
realidad) y Action no tendrán lógica de comprobación
El formulario tendrá campos de varios tipos
Ejemplo 3: Action
Extremadamente simplepackage app;
import javax.servlet.http.*;import org.apache.struts.action.*;
public class Order extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return(mapping.findForward("success")); }}
Ejemplo 3: Configuración struts-config.xml
<struts-config> <form-beans> <form-bean name="orderFormBean" type="app.OrderFormBean"/> </form-beans> <action-mappings> <action path="/actions/order" type="app.Order" name="orderFormBean" scope="request" input="/forms/order-form.jsp"> <forward name="success" path="/WEB-INF/results/order-confirmation.jsp"/> </action> </action-mappings>
<message-resources parameter="MessageResources"/>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in></struts-config>
Ejemplo 3: Mensajes de error
MessageResources.properties# -- Custom messages for this application --inputForm.firstName=NombreinputForm.lastName=ApellidoinputForm.address=DireccióninputForm.zipCode=CP (5 dígitos)inputForm.creditCardNumber=Nº tarjeta créditoinputForm.email=Email# -- Standard errors --errors.header=<UL>errors.prefix=<LI><B><FONT COLOR="RED">errors.suffix=</FONT></B></LI>errors.footer=</UL># -- validator --errors.invalid={0} es incorrecto/a.errors.maxlength={0} no puede tener más de {1} caracteres.errors.minlength={0} no pude tener menos de {1} caracteres.errors.range={0} no está entre {1} y {2}.errors.required={0} es obligatorio/a.errors.byte={0} debe ser un byte.errors.date={0} no es una fecha.errors.double={0} debe ser un double.errors.float={0} debe ser un float.errors.integer={0} debe ser un entero.errors.long={0} debe ser un long.errors.short={0} debe ser un short.errors.creditcard={0} no es un nº de tarjeta de crédito válido.errors.email={0} no es un email correcto.# -- other --errors.cancel=Operación cancelada.errors.detail={0}errors.general=El proceso no se pudo completar. Detalles a continuación.errors.token=La peticion no se completó. Operación fuera de secuencia.
Ejemplo 3: Reglas de validación
validation.xml<form-validation> <formset> <form name="orderFormBean"> <field property="firstName" depends="required"> <arg0 key="inputForm.firstName"/> </field> <field property="lastName" depends="required"> <arg0 key="inputForm.lastName"/> </field> <field property="address" depends="required"> <arg0 key="inputForm.address"/> </field> <field property="zipCode" depends="required,mask"> <arg0 key="inputForm.zipCode"/> <var> <var-name>mask</var-name> <var-value>^\d{5}\d*$</var-value> </var> </field> <field property="creditCardNumber" depends="required,creditCard"> <arg0 key="inputForm.creditCardNumber"/> </field> <field property="email" depends="required,email"> <arg0 key="inputForm.email"/> </field> </form> </formset></form-validation>
Ejemplo 3: Bean de formulario
Esta vez extendido de ValidatorForm
package app;
import org.apache.struts.validator.*;
public class OrderFormBean extends ValidatorForm {….
public String getEmail() { return(email); }
public void setEmail(String email) { this.email = email; }…}
Ejemplo 3: Formulario Creamos dos: forms/order-form.jsp y forms/order-form2.jsp (sin javascript)
<HTML><HEAD><TITLE>TOP Cine</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><H1 ALIGN="CENTER">TOP Cine</H1>Gracias por comprar la filmografía completa de <b>Chiquito de la Calzada</b>por el asombroso precio de 100 euros. Para completar su pedido, por favorrellene y envíe la siguiente información.<P><CENTER><%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %><html:errors/><html:form action="/actions/order" onsubmit="return validateOrderFormBean(this);"> Nombre: <html:text property="firstName"/><BR> Apellido: <html:text property="lastName"/><BR> Dirección: <html:text property="address"/><BR> CP (5 dígitos): <html:text property="zipCode"/><BR> Nº tarj. crédito: <html:text property="creditCardNumber"/><BR> Email para confirmación: <html:text property="email"/><BR> <html:submit value="Enviar"/></html:form><html:javascript formName="orderFormBean"/></CENTER></BODY></HTML>
Ejemplo 3: Resultados Errores detectados en cliente (formulario con javascript)
http://localhost:8080/struts-automatic-validation/forms/order-form.jsp
Ejemplo 3: Resultados Errores detectados en servidor (formulario sin javascript)
http://localhost:8080/struts-automatic-validation/forms/order-form2.jsp