Перейти на сервис в валидатор
-
01-10-2019 - |
Вопрос
Этот пример поврежден; Я упростил его, чтобы удалить посторонние детали и сосредоточиться на проблеме, у меня есть. У меня есть валидатор, который выглядит так:
@Component
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Autowired
UsernameService usernameService;
@Override
public void initialize(UniqueUsername uniqueUsername) {
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return !usernameService.exists(s);
}
}
Я называю валидатора от моего контроллера, как это:
@RequestMapping
public void checkUsername(Model model, User user) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username");
model.addAttribute("error", constraintViolations.size() > 0);
}
Тем не менее, я продолжаю получать NullPointerException
исключение. Я добавил точку останова в моем валидатере и увидел, что usernameService
было null
. Отказ Почему это не получает отключение? Изначально я думал, что это потому, что я не аннотировал валидатор с @Component
, Но у меня все еще есть та же проблема даже после аннотации. То UsernameService
класс уже аннотирован с @Service
И я могу проверить, что его конструктор вызывается.
Я новичок до весны, поэтому я даже не уверен, если это нормально, чтобы провозить услугу в валидатор. Что я делаю неправильно?
Решение
Весной вам нужно получить ValidatorFactory
(или Validator
сама) через LocalValidatorFactoryBean
вместо Validation.buildDefaultValidatorFactory()
, как описано в ссылке.
@Autowired
Validator validator;
@RequestMapping
public void checkUsername(Model model, User user) {
Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username");
model.addAttribute("error", constraintViolations.size() > 0);
}
-
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
РЕДАКТИРОВАТЬ: Но, возможно, лучший способ сделать это для использования автоматической проверки весны MVC с @Valid
Аннотация:
@RequestMapping
public void checkUsername(Model model, @Valid User user, BindingResult result) {
if (result.hasErrors()) {
...
}
}
Это также требует <mvc:annotation-driven/>
на конфиге.
Другие советы
Вместо того, чтобы создать новый валидатор, вы должны авторизовать или ввести его для контроллера. То NPE
От службы, не вводимого, поскольку ваш валидатор не создается / управляется весной.