W Spring MVC istnieją 3 różne sposoby przeprowadzania walidacji: przy użyciu adnotacji, ręcznej lub mieszanej. Nie ma unikalnego „najczystszego i najlepszego sposobu” weryfikacji, ale prawdopodobnie jest taki, który lepiej pasuje do twojego projektu / problemu / kontekstu.
Miejmy użytkownika:
public class User {
private String name;
...
}
Metoda 1: Jeśli masz Spring 3.x + i prostą weryfikację do wykonania, użyj javax.validation.constraints
adnotacji (znanych również jako adnotacje JSR-303).
public class User {
@NotNull
private String name;
...
}
Będziesz potrzebował dostawcy JSR-303 w swoich bibliotekach, takiego jak Hibernate Validator, który jest implementacją referencyjną (ta biblioteka nie ma nic wspólnego z bazami danych i mapowaniem relacyjnym, po prostu wykonuje walidację :-).
Wtedy w kontrolerze miałbyś coś takiego:
@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
}
}
Zwróć uwagę na @Valid: jeśli użytkownik ma pustą nazwę, result.hasErrors () będzie true.
Metoda 2: Jeśli masz złożoną walidację (taką jak logika walidacji dużych firm, walidacja warunkowa w wielu polach itp.) Lub z jakiegoś powodu nie możesz użyć metody 1, użyj walidacji ręcznej. Dobrą praktyką jest oddzielenie kodu kontrolera od logiki walidacji. Nie twórz swoich klas walidacji od zera, Spring zapewnia wygodny org.springframework.validation.Validator
interfejs (od Spring 2).
Powiedzmy, że masz
public class User {
private String name;
private Integer birthYear;
private User responsibleUser;
...
}
i chcesz przeprowadzić „złożoną” walidację, na przykład: jeśli użytkownik ma mniej niż 18 lat, odpowiedzialnyUser nie może być zerowy, a odpowiedzialny użytkownik musi mieć ukończone 21 lat.
Zrobisz coś takiego
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
}
}
Wtedy w kontrolerze miałbyś:
@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
}
}
Jeśli wystąpią błędy walidacji, wartość result.hasErrors () będzie true.
Uwaga: Możesz również ustawić walidator w metodzie @InitBinder kontrolera, z "binder.setValidator (...)" (w takim przypadku użycie metody 1 i 2 nie byłoby możliwe, ponieważ zastępujesz domyślną walidator). Lub możesz utworzyć instancję w domyślnym konstruktorze kontrolera. Możesz też mieć @ Component / @ Service UserValidator, który wstrzykujesz (@Autowired) do kontrolera: bardzo przydatne, ponieważ większość walidatorów to pojedyncze + testy jednostkowe stają się łatwiejsze + Twój walidator może wywoływać inne komponenty Spring.
Metoda 3:
Dlaczego nie użyć kombinacji obu metod? Zweryfikuj proste rzeczy, takie jak atrybut „nazwa”, za pomocą adnotacji (jest to szybkie, zwięzłe i bardziej czytelne). Zachowaj ciężkie walidacje dla walidatorów (kiedy kodowanie niestandardowych złożonych adnotacji walidacyjnych zajmie wiele godzin lub tylko wtedy, gdy nie można użyć adnotacji). Zrobiłem to w poprzednim projekcie, zadziałało jak urok, szybko i łatwo.
Ostrzeżenie: nie należy pomyłka obsługa walidacji dla obsługi wyjątków . Przeczytaj ten post, aby dowiedzieć się, kiedy ich używać.
Bibliografia :