Я пытаюсь удалить повторяющийся код из моих контроллеров Spring, в частности, устраняя необходимость выполнять validator.validate(form, bindingResult) с самого начала многих моих функций.
У меня есть несколько классов с соответствующими классами валидатора, которые реализуют интерфейс валидатора Spring. Я искал вокруг, чтобы попытаться найти ответ, но мне трудно найти тот, который действительно соответствует этому.
Фрагмент класса формы лица с аннотированными атрибутами
public class Person {
@Size(min=1, message = "Name missing")
private String name;
@Size(min=1, message = "Age missing")
private String age;
.... getters and setters etc.
Класс проверки личности
@Component
public class PersonValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return Person.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
errors.reject("No sir!");
}
}
В идеале я хотел бы иметь все ошибки, содержащиеся в BindingResult, включая ошибки из класса валидатора. Так что, когда я использую аннотацию @Validated, мой BindingResult полностью заполняется всеми ошибками как из простых аннотаций, так и из пользовательского валидатора.
Желаемый результат
@RequestMapping(value = "/save", method=RequestMethod.POST)
public @ResponseBody String save(@Validated @RequestBody Person personForm, BindingResult bindingResult, HttpServletRequest request)
{
bindingResult.getAllErrors(); <-- fully pop with annotation and custom validator errors
Вместо:
@RequestMapping(value = "/save", method=RequestMethod.POST)
public @ResponseBody String save(@Validated @RequestBody Person personForm, BindingResult bindingResult, HttpServletRequest request)
{
personValidator.validate(person, bindingResult) <-- Populate bindingResult with customer validator errors, if any
bindingResult.getAllErrors();
У кого-нибудь есть хорошие примеры, которыми они могут поделиться, чтобы обойти это?
Спасибо!




В качестве возможного решения вы можете определить свою собственную аннотацию и CustomConstraintValidator, которые будут реализовывать интерфейс ConstraintValidator<A extends Annotation, T>.
В конце BindingResult будет содержать либо валидатор по умолчанию, либо ваши собственные ошибки валидатора.
Здесь — хороший пример. Если я правильно понял ваш вопрос, конечно.
Вам нужно добавить валидатор в связыватель данных, чтобы несколько валидаторов работали. В коде добавьте метод @InitBinder и добавьте PersonValidator к WebDataBinder.
@InitBinder("personForm")
public void initBinder(WebDataBinder wdb) {
wdb.addValidators(personValidator);
}
Связывает валидатор с объектом модели personForm.
Это настроит глобальное правило, согласно которому этот валидатор применяется ко всем привязкам/конверсиям. Если вы хотите ограничить это определенной моделью, вы можете указать название модели в @InitBinder.
@InitBinder
public void initBinder(WebDataBinder wdb) {
wdb.addValidators(personValidator);
}
Спасибо - теперь это работает. Что произойдет, если мой контроллер имеет две функции, которые принимают разные типы форм? то есть PersonForm и AnimalForm. Я только что сделал это, и он выдает ошибку, когда я отправляю форму животного. После небольшого исследования кажется, что мне может понадобиться использовать ModelAttribute вместо RequestBody в объявлении моего метода. Однако я просто отправляю тело JSON, а не форму - немного не знаю, как действовать дальше! По крайней мере, я сейчас там на 75%!
@InitBinder принимает значение типов объектов, к которым оно применяется. Таким образом, вы можете сделать @InitBinder(PersonForm.class), чтобы ограничить привязку к этому типу.
можете ли вы передать более одного класса в аннотацию InitBinder? то есть @InitBinder(PersonForm.class AnimalForm.class)?
Да, если вы проверите документацию, вы увидите, что она принимает массив...
@InitBinder({"person"}) работает нормально, но когда я добавляю "животное" в этот массив строк и добавляю свой дополнительный валидатор в метод, я получаю сообщение об ошибке "Неверный тег для валидатора". Есть ли способ добавить несколько валидаторов здесь?
Все валидаторы должны проверять один и тот же объект, и я сомневаюсь, что person и animal относятся к одному и тому же типу объекта. Поэтому вам понадобится отдельный метод для animal.
Давайте продолжить обсуждение в чате.
Вы можете создать
Constraint annotationи реализоватьConstraintValidatorвместо того, чтобы создавать уникальный валидатор для каждого класса. СоздаваяConstraint, вы можете аннотировать класс или его поля-члены класса, а затем использовать@ValidиBindingResult