I'm working on spring mvc application, where I should aplly validation based on Spring MVC validator. 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.
我正在开发spring mvc应用程序,我应该基于Spring MVC验证器进行验证。我第一步为我添加了类和设置控制器的注释,它工作正常。现在我需要实现自定义验证器来执行复杂的逻辑,但我想使用现有的注释,只需添加额外的检查。
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?
那么,是否可以一起使用自定义验证器和注释?如果是的话怎么样?
3 个解决方案
#1
54
I know this is a kind of old question but, for googlers...
我知道这是一个古老的问题,但对于谷歌......
you should use addValidators
instead of setValidator
. Like following:
你应该使用addValidators而不是setValidator。如下:
@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注释将无法按预期工作。
#2
9
If I correctly understand your problem, as soon as you use you custom validator, default validation for @NotEmpty
annotation no longer occurs. That is common when using spring : if you override a functionnality given by default, you have to call it explicitely.
如果我正确理解您的问题,只要您使用自定义验证器,就不再出现@NotEmpty注释的默认验证。这在使用spring时很常见:如果你覆盖默认情况下给出的函数,你必须明确地调用它。
You have to generate a LocalValidatorFactoryBean
and inject it with your message source (if any). Then you inject that basic validator in you custom validator and delegate annotation validation to it.
您必须生成一个LocalValidatorFactoryBean并将其与您的消息源(如果有)一起注入。然后在自定义验证器中注入该基本验证器并将注释验证委托给它。
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");
}
}
}
#3
7
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。
#1
54
I know this is a kind of old question but, for googlers...
我知道这是一个古老的问题,但对于谷歌......
you should use addValidators
instead of setValidator
. Like following:
你应该使用addValidators而不是setValidator。如下:
@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注释将无法按预期工作。
#2
9
If I correctly understand your problem, as soon as you use you custom validator, default validation for @NotEmpty
annotation no longer occurs. That is common when using spring : if you override a functionnality given by default, you have to call it explicitely.
如果我正确理解您的问题,只要您使用自定义验证器,就不再出现@NotEmpty注释的默认验证。这在使用spring时很常见:如果你覆盖默认情况下给出的函数,你必须明确地调用它。
You have to generate a LocalValidatorFactoryBean
and inject it with your message source (if any). Then you inject that basic validator in you custom validator and delegate annotation validation to it.
您必须生成一个LocalValidatorFactoryBean并将其与您的消息源(如果有)一起注入。然后在自定义验证器中注入该基本验证器并将注释验证委托给它。
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");
}
}
}
#3
7
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。