Com o Spring MVC, existem três maneiras diferentes de executar a validação: usando anotação, manualmente ou uma mistura de ambas. Não existe uma "maneira mais limpa e melhor" única de validar, mas provavelmente existe uma que se adapte melhor ao seu projeto / problema / contexto.
Vamos ter um usuário:
public class User {
private String name;
...
}
Método 1: Se você tiver o Spring 3.x + e uma validação simples, use as javax.validation.constraints
anotações (também conhecidas como anotações JSR-303).
public class User {
@NotNull
private String name;
...
}
Você precisará de um provedor JSR-303 em suas bibliotecas, como o Hibernate Validator, que é a implementação de referência (esta biblioteca não tem nada a ver com bancos de dados e mapeamento relacional, apenas validação :-).
Então, no seu controlador, você teria 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 o @Valid: se o usuário tiver um nome nulo, result.hasErrors () será verdadeiro.
Método 2: se você possui validação complexa (como lógica de validação de grandes empresas, validação condicional em vários campos etc.) ou, por algum motivo, não pode usar o método 1, use a validação manual. É uma boa prática separar o código do controlador da lógica de validação. Não crie suas classes de validação do zero, org.springframework.validation.Validator
pois o Spring fornece uma interface prática (desde o Spring 2).
Então, digamos que você tenha
public class User {
private String name;
private Integer birthYear;
private User responsibleUser;
...
}
e você deseja fazer uma validação "complexa", como: se a idade do usuário for menor de 18 anos, o responsávelUsuário não deve ser nulo e a idade do responsável responsável deve ser superior a 21.
Você fará algo assim
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
}
}
Então, no seu controlador, você teria:
@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
}
}
Se houver erros de validação, result.hasErrors () será verdadeiro.
Nota: Você também pode definir o validador no método @InitBinder do controlador, com "binder.setValidator (...)" (nesse caso, o uso misto dos métodos 1 e 2 não seria possível, porque você substitui o padrão validador). Ou você pode instancia-lo no construtor padrão do controlador. Ou tenha um @ Component / @ Service UserValidator que você injeta (@Autowired) em seu controlador: muito útil, porque a maioria dos validadores são singletons + a simulação de teste de unidade se torna mais fácil + seu validador pode chamar outros componentes do Spring.
Método 3:
Por que não usar uma combinação dos dois métodos? Valide as coisas simples, como o atributo "nome", com anotações (é rápido, conciso e mais legível). Mantenha as validações pesadas dos validadores (quando levaria horas para codificar anotações de validação complexas personalizadas ou apenas quando não é possível usar anotações). Eu fiz isso em um projeto anterior, funcionou como um encanto, rápido e fácil.
Aviso: você não deve confundir manipulação de validação com manipulação de exceção . Leia este post para saber quando usá-los.
Referências :