Con Spring MVC, hay 3 formas diferentes de realizar la validación: usando anotaciones, manualmente o una combinación de ambas. No existe una "forma más limpia y mejor" única para validar, pero probablemente haya una que se adapte mejor a su proyecto / problema / contexto.
Tengamos un usuario:
public class User {
private String name;
...
}
Método 1: si tiene Spring 3.x + y una validación simple que hacer, use javax.validation.constraints
anotaciones (también conocidas como anotaciones JSR-303).
public class User {
@NotNull
private String name;
...
}
Necesitará un proveedor JSR-303 en sus bibliotecas, como Hibernate Validator que es la implementación de referencia (esta biblioteca no tiene nada que ver con bases de datos y mapeo relacional, solo valida :-).
Luego, en su controlador, tendría algo como:
@RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, @Valid @ModelAttribute("user") User user, BindingResult result){
if (result.hasErrors()){
// do something
}
else {
// do something else
}
}
Observe el @Valid: si el usuario tiene un nombre nulo, result.hasErrors () será verdadero.
Método 2: Si tiene una validación compleja (como lógica de validación de grandes empresas, validación condicional en múltiples campos, etc.), o por alguna razón no puede usar el método 1, use la validación manual. Es una buena práctica separar el código del controlador de la lógica de validación. No cree su (s) clase (s) de validación desde cero, Spring proporciona una org.springframework.validation.Validator
interfaz práctica (desde Spring 2).
Entonces digamos que tienes
public class User {
private String name;
private Integer birthYear;
private User responsibleUser;
...
}
y desea hacer una validación "compleja" como: si la edad del usuario es menor de 18 años, el usuario responsable no debe ser nulo y la edad del usuario responsable debe ser mayor de 21 años.
Harás algo como esto
public class UserValidator implements Validator {
@Override
public boolean supports(Class clazz) {
return User.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
User user = (User) target;
if(user.getName() == null) {
errors.rejectValue("name", "your_error_code");
}
// do "complex" validation here
}
}
Entonces en su controlador tendría:
@RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, @ModelAttribute("user") User user, BindingResult result){
UserValidator userValidator = new UserValidator();
userValidator.validate(user, result);
if (result.hasErrors()){
// do something
}
else {
// do something else
}
}
Si hay errores de validación, result.hasErrors () será verdadero.
Nota: También puede configurar el validador en un método @InitBinder del controlador, con "binder.setValidator (...)" (en cuyo caso no sería posible un uso mixto de los métodos 1 y 2, ya que reemplaza el valor predeterminado validador). O podría crear una instancia en el constructor predeterminado del controlador. O tenga un @ Component / @ Service UserValidator que inyecte (@Autowired) en su controlador: muy útil, porque la mayoría de los validadores son singletons + la prueba de unidad se burla más fácilmente + su validador podría llamar a otros componentes Spring.
Método 3:
¿Por qué no usar una combinación de ambos métodos? Valide las cosas simples, como el atributo "nombre", con anotaciones (es rápido, conciso y más legible). Mantenga las validaciones pesadas para los validadores (cuando tomaría horas codificar anotaciones de validación complejas personalizadas, o simplemente cuando no es posible usar anotaciones). Hice esto en un proyecto anterior, funcionó de maravilla, rápido y fácil.
Advertencia: no debe confundir el manejo de validación con el manejo de excepciones . Lea esta publicación para saber cuándo usarlos.
Referencias