Con Spring MVC, ci sono 3 modi diversi per eseguire la convalida: usare l'annotazione, manualmente o una combinazione di entrambi. Non esiste un unico "modo più pulito e migliore" per convalidare, ma ce n'è probabilmente uno che si adatta meglio al tuo progetto / problema / contesto.
Diamo un utente:
public class User {
private String name;
...
}
Metodo 1: se hai Spring 3.x + e una semplice validazione da fare, usa le javax.validation.constraints
annotazioni (note anche come annotazioni JSR-303).
public class User {
@NotNull
private String name;
...
}
Avrai bisogno di un provider JSR-303 nelle tue librerie, come Hibernate Validator che è l'implementazione di riferimento (questa libreria non ha nulla a che fare con i database e la mappatura relazionale, fa solo la validazione :-).
Quindi nel tuo controller avresti qualcosa del tipo:
@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
}
}
Nota @Valid: se l'utente ha un nome null, result.hasErrors () sarà true.
Metodo 2: se si dispone di una convalida complessa (come la logica di convalida delle grandi aziende, la convalida condizionale su più campi, ecc.) O per qualche motivo non è possibile utilizzare il metodo 1, utilizzare la convalida manuale. È buona norma separare il codice del controller dalla logica di convalida. Non creare da zero le tue classi di convalida, Spring offre un'interfaccia pratica org.springframework.validation.Validator
(dalla primavera 2).
Quindi diciamo che hai
public class User {
private String name;
private Integer birthYear;
private User responsibleUser;
...
}
e si desidera effettuare una convalida "complessa" come: se l'età dell'utente è inferiore a 18 anni, l'Utente responsabile non deve essere nullo e l'età dell'Utente responsabile deve essere superiore a 21 anni.
Farai qualcosa del genere
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
}
}
Quindi nel tuo controller avresti:
@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 sono presenti errori di convalida, result.hasErrors () sarà true.
Nota: è anche possibile impostare il validatore in un metodo @InitBinder del controller, con "binder.setValidator (...)" (nel qual caso un uso misto dei metodi 1 e 2 non sarebbe possibile, poiché si sostituisce il valore predefinito validatore). Oppure potresti istanziarlo nel costruttore predefinito del controller. O avere un UserValidator @ Component / @ Service che si inietta (@Autowired) nel controller: molto utile, perché la maggior parte dei validatori sono singletons + il test dell'unità di derisione diventa più facile + il validatore potrebbe chiamare altri componenti Spring.
Metodo 3:
perché non utilizzare una combinazione di entrambi i metodi? Convalida le cose semplici, come l'attributo "nome", con le annotazioni (è veloce, conciso e più leggibile). Mantieni le convalide pesanti per i validatori (quando occorrerebbero ore per codificare annotazioni di convalida complesse personalizzate o solo quando non è possibile utilizzare le annotazioni). L'ho fatto su un precedente progetto, ha funzionato come un fascino, veloce e facile.
Avviso: non si deve confondere la gestione della convalida con la gestione delle eccezioni . Leggi questo post per sapere quando usarli.
Riferimenti :