Spring MVC Validar Formularios

En el tutorial Spring Vistas JSP creamos nuestro primer formulario, en él podíamos ingresar los datos que posteriormente almacenamos en la base de datos, para mejorar el funcionamiento de nuestro formulario vamos a validar los datos de entrada, por ejemplo: no permitiremos textos vacíos, fechas con formato incorrecto, números no válidos, etc., con Spring Web MVC el uso y la validación  de los formularios es una tarea sencilla, veamos como se hace.

Para habilitar la validación de formularios necesitaremos un Bean Validation API en este tutorial usaremos: Hibernate Validator 5.3.4.Final, requerimos las siguientes dependencias para desarrollar nuestro proyecto de ejemplo.

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.3.4.Final</version>
    </dependency>
    
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
    </dependency>
</dependencies>

Vamos a simular una aplicación que registra usuarios, por lo crearemos las clase Usuario, usaremos las anotaciones correspondientes para validar cada uno de los campos, nuestra clase se ve de la siguiente manera:

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;

public class Usuario {

    @Size(min = 3, max = 20)
    private String nombre;

    @NotBlank
    private String apellido;

    @Email
    @NotBlank
    private String correo;

    @Pattern(regexp = "^[a-zA-Z]\\w{3,14}$")
    private String password;

    @Min(18)
    @NotNull
    private Integer edad;

    @NotNull
    private Boolean sexo;

    // getter, setter, ...

}

En esta clase tenemos las siguientes anotaciones de validación:

  • @Size(min=3, max=20): Indica la longitud mínima y máxima que debe tener el texto nombre.
  • @NotBlank: Impide que un campo de texto esté vacío.
  • @Email: Verifica que la dirección de correo electrónico tenga el formato correcto.
  • @Pattern(regexp="..."): El texto debe cumplir con la expresión regular indicada, en nuestro ejemplo la expresión regular establece que la contraseña debe contener letras y números.
  • @NotNull: Este campo no puede ser nulo.
  • @Min(18): El valor mínimo es 18.

Aun existen muchas otras anotaciones e incluso podemos crear validaciones personalizadas.

Nuestro controlador lo llamaremos UsuarioController este mostrara dos vistas, una que contiene el formulario que nos permitirá ingresar un usuario, y otra que simplemente nos mostrará un mensaje cuando el usuario se ingrese de manera correcta.

@Controller
@RequestMapping("/user")
public class UsuarioController {
    
    @RequestMapping("/form")
    public String showUserForm(Model model){
        model.addAttribute("usuario", new Usuario());
        return "userForm";
    }

    @RequestMapping("/create")
    public ModelAndView createUser(@Valid Usuario user, BindingResult result) {
        ModelAndView model = new ModelAndView();
        model.addObject("usuario", user);
        model.setViewName(result.hasErrors() ? "userForm" : "userReady");
        
        return model;
    }

}

Usamos la anotación @RequestMapping a nivel de clase y de método, en este controlador mapeamos las siguientes dos URL, /user/form nos llevará la vista que contiene el formulario, al presionar el botón Submit de dicho formulario este nos enviará a la URL /user/create que nos puede llevar a dos posibles vistas, si hay error regresamos al formulario, en caso contrario nos vamos a la vista userReady.

@RequestMapping("/create")
public ModelAndView createUser(@Valid Usuario user, BindingResult result) {
     ModelAndView model = new ModelAndView();
     model.addObject("usuario", user);
     model.setViewName(result.hasErrors() ? "userForm" : "userReady");
        
     return model;
}

Este es el método encargado de validar al usuario, para ello usamos la anotación @Valid, también agregamos un parámetro de tipo BindingResult, el mismo nos permite verificar si hubo o no un error en la validación del usuario, si existe un error cambiamos el nombre de la vista a userForm de lo contrario usamos userReady.

/WEB-INF/views/userForm.jsp

<%@page contentType="text/html; charset=ISO-8859-1" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<html>
    <head>
        <title>Spring MVC Form Validation</title>
        <style type="text/css">
            .formFieldError { background-color: #FFC; }
        </style>
    </head>
    <body>
        <h2>Registrar Usuario:</h2>
        <mvc:form modelAttribute="usuario" action="create">
            <table>
                <tr>
                    <td><mvc:label  path="nombre">Nombre: </mvc:label></td>
                    <td><mvc:input  path="nombre" cssErrorClass="formFieldError" /></td>
                    <td><mvc:errors path="nombre" /></td>
                </tr>
                <tr>
                    <td><mvc:label  path="apellido">Apellido: </mvc:label></td>
                    <td><mvc:input  path="apellido" cssErrorClass="formFieldError" /></td>
                    <td><mvc:errors path="apellido" /></td>
                </tr>
                <tr>
                    <td><mvc:label  path="correo">EMail: </mvc:label></td>
                    <td><mvc:input  path="correo" cssErrorClass="formFieldError" /></td>
                    <td><mvc:errors path="correo" /></td>
                </tr>
                <tr>
                    <td><mvc:label  path="password">Contraseña: </mvc:label></td>
                    <td><mvc:input  path="password" cssErrorClass="formFieldError" /></td>
                    <td><mvc:errors path="password" /></td>
                </tr>
                <tr>
                    <td><mvc:label  path="edad">Edad: </mvc:label></td>
                    <td><mvc:input  path="edad" cssErrorClass="formFieldError" /></td>
                    <td><mvc:errors path="edad" /></td>
                </tr>
                <tr>
                    <td><mvc:label  path="sexo">Sexo: </mvc:label></td>
                    <td><mvc:input  path="sexo" cssErrorClass="formFieldError" /></td>
                    <td><mvc:errors path="sexo" /></td>
                </tr>            
                <tr>
                    <td colspan="1">
                        <input type="submit" value="Submit" />
                    </td>
                </tr>
            </table>
        </mvc:form>
    </body>
</html>

Los detalles de como se crean y usan los formularios en Spring MVC los vimos en el tutorial anterior, lo que no vimos fue como manejar los errores, para ello usamos la etiqueta <mvc:errors path="..." /> en path indicamos la propiedad de la cual queremos obtener el error.

Spring MVC validacion de formularios

Usando el atributo cssErrorClass podemos establecer la clase CSS que se aplica a los controles del formulario cuando se detecta algún error.

/WEB-INF/views/userReady.jsp

<%@page contentType="text/html; charset=ISO-8859-1" %>
<!DOCTYPE html>
<html>
    <head>
        <title>Spring MVC Form Validation</title>
    </head>
    <body>
        <h2>Usuario creado correctamente:</h2>
        <p>${usuario.nombre}, ${usuario.apellido}</p>
        <a href="${pageContext.servletContext.contextPath}/user/form">Crear usuario</a>
    </body>
</html>

Esta vista es simple solo nos mostrará un mensaje de éxito al ingresar los datos de manera correcta, al final añadimos un enlace que nos permitirá volver al formulario de registro de usuarios.

Si deseamos personalizar el mensaje que se muestra en cada uno de los campos con error podemos usar message="..." para establecer nuestro propio mensaje de error, ejemplo:

public class Usuario {

    @Size(min = 3, max = 20, message = "El nombre debe tener mas de 3 letras y menos de 20.")
    private String nombre;

    @NotBlank(message = "Debe indicar el apellido del usuario.")
    private String apellido;

    @Min(value = 18, message = "El usuario debe tener 18+")
    @NotNull
    private Integer edad;

    // el resto...

}

Otra cosa que podemos hacer obtener una lista de todos los mensajes de error que se han producido, lo hacemos usando <mvc:errors path="*" element="div" /> al utilizar path="*" obtenemos todos los errores y con element="div" indicamos que los mismos deben crearse dentro de un elemento HTML div.

<mvc:form modelAttribute="usuario" action="create">
    <mvc:errors path="*" cssClass="errorblock" element="div"/>
    <table>
        <tr>
            <td><mvc:label  path="nombre">Nombre: </mvc:label></td>
            <td><mvc:input  path="nombre" cssErrorClass="formFieldError" /></td>
            <td><mvc:errors path="nombre" /></td>
        </tr>

       <!-- mas... --> 
          
        <tr>
            <td colspan="1">
                <input type="submit" value="Submit" />
            </td>
        </tr>
    </table>
</mvc:form>

Con este par de modificaciones tendremos lo siguiente:

Spring MVC Validación formularios

Otra forma de cambiar los mensajes de error es usando los archivo de internacionalización (I18N), por ejemplo para español messages_es.properties y para el inglés messages_en.properties.

# archivo messages_es.properties
# definicion de los mensajes de error para las respectivas anotaciones

Email=La dirección de correo no es válida
NotNull=No puede ser nulo

Usamos el nombre de la anotación sin el @ para definir el mensaje de la misma, recordemos que para que funcione correctamente debemos agregar el siguiente bean a nuestra configuración web.

@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages");
    return messageSource;
}

Spring MVC cambiar mensaje de validacion

Como hemos visto la validación de datos en los formularios es bastante simple con Spring MVC, a la vez también es una característica bastante potente de la cual podemos sacar mucho provecho a la hora de desarrollar aplicaciones web con Spring MVC.

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

Histogramas OpenCV Python

Spring MVC Thymeleaf formularios

tkinter Canvas

JavaFX Gráficos 3D