Validación de Spring MVC

En Spring MVC es posible validar campos de formulario utilizando Bean Validation API (JSR 303 para Bean Vaidation 1.0 y [JSR 349](https: //jcp.org/en/jsr/detail?id=349) para Bean Validation 1.1) que se utiliza para definir las restricciones de validación del objeto JavaBean.

Hibernate Validator es una implementación de referencia de la API de validación de Bean. Hibernate Validator ofrece un valor adicional además de las características requeridas por Bean Validation. Por ejemplo, una [API de configuración de restricciones programáticas] (http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-programmatic-api) así como un [procesador de anotaciones] (http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-annotation-processor) que se conecta al proceso de compilación y genera errores de compilación cada vez que las anotaciones de restricción se usan incorrectamente.

Validación de formulario Spring MVC con API de validación de Bean

Este ejemplo muestra cómo validar formularios en Spring MVC usando Bean Validation API usando anotaciones de Java, sin ningún xml. Se le propondrá al usuario que ingrese sus datos de registro y el validador verificará su validez.

Agregar dependencias

En primer lugar, agregue las siguientes dependencias en su proyecto:

  • [API de validación de bean] (http://mvnrepository.com/artifact/javax.validation/validation-api) y

  • Motor de validación de Hibernate

    dependencies { compile group: ‘javax.validation’, name: ‘validation-api’, version: ‘1.1.0.Final’ compile group: ‘org.hibernate’, name: ‘hibernate-validator’, version: ‘5.2.4.Final’ }

Crear clase de modelo

Cree la clase de modelo Usuario como se muestra a continuación:

import org.hibernate.validator.constraints.Email;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import java.util.Date;

public class User {

    @NotNull(message = "Please input your email.")
    @Email(message = "Email format is wrong.")
    private String email;

    @NotNull(message = "{user.password.notNull}")
    @Size(min = 8, max = 16, message = "{user.password.size}")
    private String password;

    @NotNull(message = "{user.age.notNull}")
    @Min(18)
    @Max(100)
    private Integer age;

    @NotNull(message = "{user.birthday.notNull}")
    @DateTimeFormat(pattern = "dd.MM.yyyy")
    @Past(message = "{user.birthday.past}")
    private Date birthday;

    // getters, setters
}

Aquí se utilizan algunas de las anotaciones JSR 303: @NotNull, @Size, @Min, @Max y @Past, así como algunas anotaciones adicionales proporcionadas por la implementación del validador de hibernación: @Email , @DateTimeFormat.

Tenga en cuenta que los mensajes de error para el campo email se especifican dentro de sus anotaciones. Mientras que los mensajes de error para los campos contraseña, edad y cumpleaños se especifican en un archivo messages.properties para demostrar la externalización de los mensajes de error de validación. Estos archivos deben colocarse en la carpeta resources:

user.password.notNull = Password field cannot be empty.
user.password.size = Password must be between {min} and {max} characters in length.
user.age.notNull = Please enter your age.
user.birthday.notNull = Please enter your birthday.
user.birthday.past = That's impossible.

typeMismatch=Please use dd.MM.yyyy format

Para esta capacidad messageSource() con bean.setBasename("classpath:messages"); código y validator() beans también deben configurarse, así como la anotación:

@Configuration
@PropertySource("application.properties")
public class AppConfig extends WebMvcConfigurerAdapter {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
        bean.setBasename("classpath:messages");
        bean.setDefaultEncoding("UTF-8");
        return bean;
    }

    @Bean
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }

    @Override
    public Validator getValidator() {
        return validator();
    }
}

También la clase de configuración debe anotarse con @PropertySource("application.properties") y la ruta a las páginas jsp debe agregarse a este archivo como se muestra a continuación:

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

Crear clase FormController

Ahora, en la clase de controlador, anote el objeto modelo que respalda el formulario mediante la anotación @Valid del paquete javax.validation.

Spring MVC validará el objeto modelo anotado por la anotación @Valid después de vincular sus propiedades con las entradas del formulario JSP que usa las etiquetas de formulario de Spring. Cualquier violación de restricción se expondrá como errores en el objeto BindingResult, por lo que podemos verificar la violación en el método del controlador.

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

@Controller
public class FormController {

    private Map<String, User> users = null;

    public FormController() {
        users = new HashMap<String, User>();
    }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String viewRegister(Map<String, Object> model) {
        User user = new User();
        model.put("user", user);
        return "register";
    }

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String doRegister(@Valid User user, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "register";
        }
        model.addAttribute("user", user);
        users.put(user.getEmail(), user);
        return "registerSuccess";
    }
}

Crear formulario de entrada JSP

Agregue el archivo register.jsp con el siguiente contenido:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Form Page</title>
<style>
.error {
    color: #ff0000;
    font-weight: bold;
}
</style>
</head>
<body>
    <form:form method="POST" commandName="user" action="register">
        <table>
            <tr>
                <td>Email:</td>
                <td><form:input path="email" placeholder="Email"/></td>
                <td><form:errors path="email" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><form:password path="password" placeholder="Password"/></td>
                <td><form:errors path="password" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Age:</td>
                <td><form:input path="age" placeholder="Age"/></td>
                <td><form:errors path="age" cssClass="error" /></td>
            </tr>
            <tr>
                <td>Birthday:</td>
                <td><form:input path="birthday" placeholder="dd.MM.yyyy"/></td>
                <td><form:errors path="birthday" cssClass="error" /></td>
            </tr>
            <tr>
                <td colspan="3"><input type="submit" value="Register"></td>
            </tr>
        </table>

    </form:form>

</body>
</html>

Por lo general, devolveríamos el formulario de entrada al usuario cuando ocurriera algún error de validación. Y en el formulario JSP, podemos mostrar mensajes de error de validación usando la etiqueta de errores de formulario de Spring como <form:errors path="email"/>.

Crear página de éxito JSP

La página registerSuccess.jsp se mostrará en caso de que el usuario ingrese todos los datos válidos. Aquí está el código:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%@ page session="false" %>
<html>
<head>
    <title>Success</title>
</head>
<body>
<h3>User Registered Successfully.</h3>

<strong>User Email: ${user.email}</strong><br>
<strong>User Age: ${user.age}</strong><br>
<strong>User Birthday: <fmt:formatDate value="${user.birthday}" type="date" pattern="dd.MM.yyyy"/></strong><br>

</body>
</html>

Aplicación de prueba

Después de todo, la estructura del proyecto debería verse así:

ingrese la descripción de la imagen aquí

Inicie la aplicación, vaya a http://localhost:8080/ e intente ingresar datos no válidos:

ingrese la descripción de la imagen aquí

Cuando se ingresan datos válidos, el usuario será redirigido a la página de éxito:

ingrese la descripción de la imagen aquí