Със Spring MVC има 3 различни начина за извършване на валидиране: използване на анотация, ръчно или комбинация от двете. Няма уникален „най-чист и най-добър начин“ за валидиране, но вероятно има такъв, който пасва по-добре на вашия проект/проблем/контекст.
Нека имаме потребител:
public class User {
private String name;
...
}
Метод 1: Ако имате Spring 3.x+ и проста проверка за извършване, използвайте javax.validation.constraints
анотации (известни също като JSR-303 анотации).
public class User {
@NotNull
private String name;
...
}
Ще ви трябва JSR-303 доставчик във вашите библиотеки, като Hibernate Validator, който е референтният реализация (тази библиотека няма нищо общо с базите данни и релационното картографиране, тя просто прави валидиране :-).
Тогава във вашия контролер ще имате нещо като:
@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
}
}
Обърнете внимание на @Valid: ако случайно потребителят има нулево име, result.hasErrors() ще бъде true.
Метод 2: Ако имате сложно валидиране (като логика за валидиране на голям бизнес, условно валидиране в множество полета и т.н.) или по някаква причина не можете да използвате метод 1, използвайте ръчно валидиране. Добра практика е да отделите кода на контролера от логиката за валидиране. Не създавайте своя клас(ове) за валидиране от нулата, Spring предоставя удобен org.springframework.validation.Validator
интерфейс (от Spring 2).
Така че да кажем, че имате
public class User {
private String name;
private Integer birthYear;
private User responsibleUser;
...
}
и искате да направите някаква "сложна" проверка като: ако възрастта на потребителя е под 18 години, responseUser не трябва да е null и възрастта на responseUser трябва да е над 21.
Ще направите нещо подобно
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
}
}
Тогава във вашия контролер ще имате:
@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
}
}
Ако има грешки при валидиране, result.hasErrors() ще бъде вярно.
Забележка: Можете също да зададете валидатора в метод @InitBinder на контролера с "binder.setValidator(...)" (в който случай смесеното използване на метод 1 и 2 не би било възможно, защото замествате стандартния валидатор). Или можете да го инстанциирате в конструктора по подразбиране на контролера. Или имайте @Component/@Service UserValidator, който инжектирате (@Autowired) във вашия контролер: много полезно, тъй като повечето валидатори са сингълтони + подигравката с единичен тест става по-лесна + вашият валидатор може да извика други Spring компоненти.
Метод 3: Защо не използвате комбинация от двата метода? Валидирайте простите неща, като атрибута "име", с анотации (бързо се прави, стегнато е и по-четливо). Запазете тежките проверки за валидатори (когато ще отнеме часове за кодиране на персонализирани сложни анотации за валидиране или просто когато не е възможно да се използват анотации). Направих това на предишен проект, работи като чар, бързо и лесно.
Предупреждение: не бива да бъркате обработка на потвърждение с обработка на изключения. Прочетете тази публикация, за да знаете кога да ги използвате.
Препратки :
person
Community
schedule
27.08.2012