Java Spring MVC 验证器注解+自定义验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25075683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:34:26  来源:igfitidea点击:

Spring MVC validator annotation + custom validation

javaspringvalidationspring-mvc

提问by Vartlok

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?

那么,是否可以同时使用自定义验证器和注释?如果是,如何?

采纳答案by destan

I know this is a kind of old question but, for googlers...

我知道这是一个老问题,但是,对于谷歌员工......

you should use addValidatorsinstead of setValidator. Like following:

你应该使用addValidators而不是setValidator. 像下面这样:

@InitBinder
protected void initBinder(final WebDataBinder binder) {
    binder.addValidators(yourCustomValidator, anotherValidatorOfYours);
}

PS: addValidatorsaccepts multiple parameters (ellipsis)

PS:addValidators接受多个参数(省略号)

if you checkout the source of org.springframework.validation.DataBinderyou 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 setValidatorclears existing (default) validator so @Validannotation won't work as expected.

如您所见,setValidator清除现有(默认)验证器,因此@Valid注释将无法按预期工作。

回答by nicearma

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。

回答by Serge Ballesta

If I correctly understand your problem, as soon as you use you custom validator, default validation for @NotEmptyannotation 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 LocalValidatorFactoryBeanand inject it with your message source (if any). Then you inject that basic validator in you custom validator and delegate annotation validation to it.

您必须生成 aLocalValidatorFactoryBean并将其注入您的消息源(如果有)。然后,您在自定义验证器中注入该基本验证器,并将注释验证委托给它。

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 UserValidatorto 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");
        }
    }
}