[英]Spring MVC validator annotation + custom validation
I'm working on spring mvc application, where I should aplly validation based on Spring MVC validator. 我正在开发spring mvc应用程序,我应该基于Spring MVC验证器进行验证。 I first step for that I added annotation for class and setup controller and it works fine. 我第一步为我添加了类和设置控制器的注释,它工作正常。 And now I need to implement custom validator for perform complex logic, but i want to use existing annotation and just add additional checking. 现在我需要实现自定义验证器来执行复杂的逻辑,但我想使用现有的注释,只需添加额外的检查。
My User class: 我的用户类:
public class User
{
@NotEmpty
private String name;
@NotEmpty
private String login; // should be unique
}
My validator: 我的验证员:
@Component
public class UserValidator implements Validator
{
@Autowired
private UserDAO userDAO;
@Override
public boolean supports(Class<?> clazz)
{
return User.class.equals(clazz) || UsersForm.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors)
{
/*
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "NotEmpty.user");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "login", "NotEmpty.user");
*/
User user = (User) target;
if (userDAO.getUserByLogin(user.getLogin()) != null) {
errors.rejectValue("login", "NonUniq.user");
}
}
}
My controller: 我的控制器:
@Controller
public class UserController
{
@Autowired
private UserValidator validator;
@InitBinder
protected void initBinder(final WebDataBinder binder)
{
binder.setValidator(validator);
}
@RequestMapping(value = "/save")
public ModelAndView save(@Valid @ModelAttribute("user") final User user,
BindingResult result) throws Exception
{
if (result.hasErrors())
{
// handle error
} else
{
//save user
}
}
}
So, Is it possible to use custom validator and annotation together? 那么,是否可以一起使用自定义验证器和注释? And if yes how? 如果是的话怎么样?
I know this is a kind of old question but, for googlers... 我知道这是一个老问题,但对于谷歌......
you should use addValidators
instead of setValidator
. 你应该使用addValidators
而不是setValidator
。 Like following: 如下:
@InitBinder
protected void initBinder(final WebDataBinder binder) {
binder.addValidators(yourCustomValidator, anotherValidatorOfYours);
}
PS: addValidators
accepts multiple parameters (ellipsis) PS: addValidators
接受多个参数(省略号)
if you checkout the source of org.springframework.validation.DataBinder
you will see: 如果你签出org.springframework.validation.DataBinder
的来源,你会看到:
public class DataBinder implements PropertyEditorRegistry, TypeConverter {
....
public void setValidator(Validator validator) {
assertValidators(validator);
this.validators.clear();
this.validators.add(validator);
}
public void addValidators(Validator... validators) {
assertValidators(validators);
this.validators.addAll(Arrays.asList(validators));
}
....
}
as you see setValidator
clears existing (default) validator so @Valid
annotation won't work as expected. 如您所见, setValidator
清除现有(默认)验证器,因此@Valid
注释将无法按预期工作。
If I correctly understand your problem, as soon as you use you custom validator, default validation for @NotEmpty
annotation no longer occurs. 如果我正确理解您的问题,只要您使用自定义验证器,就不再出现@NotEmpty
注释的默认验证。 That is common when using spring : if you override a functionnality given by default, you have to call it explicitely. 这在使用spring时很常见:如果你覆盖默认情况下给出的函数,你必须明确地调用它。
You have to generate a LocalValidatorFactoryBean
and inject it with your message source (if any). 您必须生成一个LocalValidatorFactoryBean
并将其与您的消息源(如果有)一起注入。 Then you inject that basic validator in you custom validator and delegate annotation validation to it. 然后在自定义验证器中注入该基本验证器并将注释验证委托给它。
Using java configuration it could look like : 使用java配置它可能看起来像:
@Configuration
public class ValidatorConfig {
@Autowired
private MessageSource messageSource;
@Bean
public Validator basicValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource);
return validator;
}
}
Then you modify UserValidator
to use it : 然后修改UserValidator
以使用它:
@Component
public class UserValidator implements Validator
{
@Autowired
@Qualifier("basicValidator")
private Validator basicValidator;
@Autowired
private UserDAO userDAO;
// ...
@Override
public void validate(Object target, Errors errors)
{
basicValidator.validate(target, errors);
// eventually stop if any errors
// if (errors.hasErrors()) { return; }
User user = (User) target;
if (userDAO.getUserByLogin(user.getLogin()) != null) {
errors.rejectValue("login", "NonUniq.user");
}
}
}
Well for me you have to delete the 好吧,我必须删除
@InitBinder
protected void initBinder(final WebDataBinder binder)
{
binder.setValidator(validator);
}
Leave the 离开了
@Valid @ModelAttribute("user") final User user,
BindingResult result
And after in the function make 并且在函数make之后
validator.validate(user,result)
This way you will use the validation basic with the @Valid and after you will put make the more complex validation. 这样,您将使用@Valid的验证基础,并在您进行更复杂的验证之后。
Because with the initBinder you are setting the validation with your complex logic and putting a way the basic logic. 因为使用initBinder,您可以使用复杂的逻辑设置验证并为基本逻辑设置方法。
Maybe is wrong, i use always the @Valid without any validator. 也许是错的,我总是在没有任何验证器的情况下使用@Valid。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.