Этот пример немного надуманный; Я упростил это, чтобы удалить посторонние детали и сосредоточиться на проблеме, с которой я столкнулся. У меня есть валидатор, который выглядит следующим образом:
@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
было пусто
. Почему он не подключается автоматически? Сначала я думал, что это потому, что я не аннотировал валидатор с помощью @Component
, но у меня все еще остается та же проблема, даже после того, как я ее аннотировал. Класс UsernameService
уже аннотирован с помощью @Service
, и я могу убедиться, что его конструктор вызывается.
Я новичок в Spring, поэтому я ' Я даже не уверен, можно ли подключить сервис к валидатору. Что я делаю неправильно?
В Spring вам необходимо получить 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"/>
РЕДАКТИРОВАТЬ: Но, возможно, лучший способ сделать это — использовать автоматическую проверку Spring MVC с аннотацией @Valid
:
@RequestMapping
public void checkUsername(Model model, @Valid User user, BindingResult result) {
if (result.hasErrors()) {
...
}
}
Для этого также требуется
в конфиг.
Вместо того, чтобы создавать новый валидатор, вы должны автоматически подключить или внедрить его в контроллер. NPE
из службы не внедряется, так как ваш валидатор не создается/управляется Spring.