Investigamos en diferentes espacios para tenerte la solución para tu inquietud, si tienes dudas puedes dejarnos tu duda y te contestamos con gusto.
Solución:
Con Spring MVC, hay 3 formas diferentes de realizar la validación: usando anotación, manualmente o una combinación de ambas. No existe una única “manera más limpia y mejor” de 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 para 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 tu controlador tendrías 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 null name, result.hasErrors () será true.
Método 2: Si tiene una validación compleja (como la lógica de validación de grandes empresas, la validación condicional en varios 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 práctica org.springframework.validation.Validator
interfaz (desde Spring 2).
Entonces digamos que tienes
public class User
private String name;
private Integer birthYear;
private User responsibleUser;
...
y desea realizar una validación “compleja” como: si la edad del usuario es menor de 18 años, el usuario responsable no debe ser null 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 tu controlador tendrías:
@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á true.
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 del método 1 y 2, porque reemplaza el predeterminado validador). O puede 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 simulación de pruebas unitarias se vuelve más fácil + su validador podría llamar a otros componentes Spring.
Método 3:
¿Por qué no utilizar una combinación de ambos métodos? Validar las cosas simples, como el “nombre” attribute, con anotaciones (es rápido de hacer, 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ó como un encanto, rápido y fácil.
Advertencia : no debes equivocarte manejo de validación por manejo de excepciones. Lea esta publicación para saber cuándo usarlos.
Referencias:
- Una publicación de blog muy interesante sobre la validación de frijoles (el enlace original está muerto)
- Otra buena publicación de blog sobre validación (el enlace original está muerto)
- La última documentación de Spring sobre validación
Hay dos formas de validar la entrada del usuario: anotaciones y heredando la clase Validator de Spring. Para casos simples, las anotaciones son agradables. Si necesita validaciones complejas (como la validación de campo cruzado, por ejemplo, el campo “verificar dirección de correo electrónico”), o si su modelo está validado en varios lugares de su aplicación con diferentes reglas, o si no tiene la capacidad de modificar su modelo de objeto colocando anotaciones en él, el Validador basado en herencia de Spring es el camino a seguir. Mostraré ejemplos de ambos.
La parte de validación real es la misma independientemente del tipo de validación que esté utilizando:
RequestMapping(value="fooPage", method = RequestMethod.POST)
public String processSubmit(@Valid @ModelAttribute("foo") Foo foo, BindingResult result, ModelMap m)
if(result.hasErrors())
return "fooPage";
...
return "successPage";
Si está utilizando anotaciones, su Foo
la clase podría verse así:
public class Foo
@NotNull
@Size(min = 1, max = 20)
private String name;
@NotNull
@Min(1)
@Max(110)
private Integer age;
// getters, setters
Las anotaciones anteriores son javax.validation.constraints
anotaciones. También puede usar Hibernate’s
org.hibernate.validator.constraints
, pero no parece que esté utilizando Hibernate.
Alternativamente, si implementa Spring’s Validator, crearía una clase de la siguiente manera:
public class FooValidator implements Validator
@Override
public boolean supports(Class> clazz)
return Foo.class.equals(clazz);
@Override
public void validate(Object target, Errors errors)
Foo foo = (Foo) target;
if(foo.getName() == null)
errors.rejectValue("name", "name[emptyMessage]");
else if(foo.getName().length() < 1
Si usa el validador anterior, también debe vincular el validador al controlador Spring (no es necesario si usa anotaciones):
@InitBinder("foo")
protected void initBinder(WebDataBinder binder)
binder.setValidator(new FooValidator());
Consulte también los documentos de Spring.
Espero que ayude.
Me gustaría extender la buena respuesta de Jerome Dalbert. Encontré muy fácil escribir sus propios validadores de anotaciones en forma JSR-303. No está limitado a tener una validación de "un campo". Puede crear su propia anotación a nivel de tipo y tener una validación compleja (consulte los ejemplos a continuación). Prefiero esta forma porque no necesito mezclar diferentes tipos de validación (Spring y JSR-303) como lo hace Jerome. Además, estos validadores son "compatibles con Spring", por lo que puede usar @ Inject / @ Autowire de fábrica.
Ejemplo de validación de objetos personalizados:
@Target( TYPE, ANNOTATION_TYPE )
@Retention(RUNTIME)
@Constraint(validatedBy = YourCustomObjectValidator.class )
public @interface YourCustomObjectValid
String message() default "YourCustomObjectValid.message";
Class>[] groups() default ;
Class extends Payload>[] payload() default ;
public class YourCustomObjectValidator implements ConstraintValidator
@Override
public void initialize(YourCustomObjectValid constraintAnnotation)
@Override
public boolean isValid(YourCustomObject value, ConstraintValidatorContext context)
// Validate your complex logic
// Mark field with error
ConstraintViolationBuilder cvb = context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate());
cvb.addNode(someField).addConstraintViolation();
return true;
@YourCustomObjectValid
public YourCustomObject
Ejemplo de igualdad de campos genéricos:
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target( TYPE, ANNOTATION_TYPE )
@Retention(RUNTIME)
@Constraint(validatedBy = FieldsEqualityValidator.class )
public @interface FieldsEquality
String message() default "FieldsEquality.message";
Class>[] groups() default ;
Class extends Payload>[] payload() default ;
/**
* Name of the first field that will be compared.
*
* @return name
*/
String firstFieldName();
/**
* Name of the second field that will be compared.
*
* @return name
*/
String secondFieldName();
@Target( TYPE, ANNOTATION_TYPE )
@Retention(RUNTIME)
public @interface List
FieldsEquality[] value();
import java.lang.reflect.Field;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
public class FieldsEqualityValidator implements ConstraintValidator
private static final Logger log = LoggerFactory.getLogger(FieldsEqualityValidator.class);
private String firstFieldName;
private String secondFieldName;
@Override
public void initialize(FieldsEquality constraintAnnotation)
firstFieldName = constraintAnnotation.firstFieldName();
secondFieldName = constraintAnnotation.secondFieldName();
@Override
public boolean isValid(Object value, ConstraintValidatorContext context)
if (value == null)
return true;
try
Class> clazz = value.getClass();
Field firstField = ReflectionUtils.findField(clazz, firstFieldName);
firstField.setAccessible(true);
Object first = firstField.get(value);
Field secondField = ReflectionUtils.findField(clazz, secondFieldName);
secondField.setAccessible(true);
Object second = secondField.get(value);
if (first != null && second != null && !first.equals(second))
ConstraintViolationBuilder cvb = context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate());
cvb.addNode(firstFieldName).addConstraintViolation();
ConstraintViolationBuilder cvb = context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate());
cvb.addNode(someField).addConstraintViolation(secondFieldName);
return false;
catch (Exception e)
log.error("Cannot validate fileds equality in '" + value + "'!", e);
return false;
return true;
@FieldsEquality(firstFieldName = "password", secondFieldName = "confirmPassword")
public class NewUserForm
private String password;
private String confirmPassword;
valoraciones y comentarios
Si te sientes suscitado, eres capaz de dejar una noticia acerca de qué te ha parecido este ensayo.