当前位置: 首页 > 知识库问答 >
问题:

Spring MVC验证程序注释自定义验证

严阳夏
2023-03-14

我正在开发spring mvc应用程序,我应该在spring mvc validator的基础上应用验证。第一步,我为类和设置控制器添加了注释,效果很好。现在我需要实现自定义验证器来执行复杂的逻辑,但我想使用现有的注释并添加额外的检查。

我的用户类:

public class User
{
    @NotEmpty
    private String name;

    @NotEmpty
    private String login; // should be unique
}

我的验证器:

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

我的控制器:

@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
        }
    }
}

那么,有可能同时使用自定义验证器和注释吗?如果是,怎么做?

共有3个答案

左丘元徽
2023-03-14

对我来说,你必须删除

 @InitBinder
protected void initBinder(final WebDataBinder binder)
{
    binder.setValidator(validator);
}

离开

@Valid @ModelAttribute("user") final User user,
        BindingResult result

函数make中

validator.validate(user,result)

通过这种方式,您将把validation basic与@Valid一起使用,然后再将其放入更复杂的验证中。

因为使用initBinder,您可以使用复杂的逻辑设置验证,并为基本逻辑设置一条路径。

也许是错误的,我总是使用@Valid没有任何验证器。

法子昂
2023-03-14

如果我正确理解了您的问题,只要您使用自定义验证器,@NotEmpty注释的默认验证就不再发生。这在使用spring时很常见:如果覆盖默认给定的Functionality,则必须明确地调用它。

您必须生成一个LocalValidatoryFactoryBean,并将其与消息源(如果有)一起注入。然后将基本验证器注入定制验证器,并将注释验证委托给它。

使用java配置,它可能看起来像:

@Configuration
public class ValidatorConfig {
    @Autowired
    private MessageSource messageSource;

    @Bean
    public Validator basicValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);
        return validator;
    }
}

然后你修改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");
        }
    }
}
花博厚
2023-03-14

我知道这是一个老问题,但是,对于谷歌人来说...

您应该使用addValidators而不是setValidator。例如:

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

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

如果您签出org的源代码。springframework。验证。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));
    }

    ....

}

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

 类似资料:
  • 我有一个自定义注释,如下所示 我定义了一个方面来包装实际的方法调用 注释的用法如下所示 到目前为止,这工作得很好,我可以在TestableAspect#InvkeAndLog中实现我的登录。 现在我需要验证eg的索引值不大于10。 我可以在运行时通过更改方面实现来实现,如下所示 但这需要至少调用一次API,而且效率不高。是否有一种方法可以在spring启动应用程序启动时执行此操作?

  • 我正在开发一个java spring mvc应用程序。我已经实现了一个自定义的验证注释来验证某些字符串(例如)。这是我的注释体: 这是我的类:

  • 我使用Spring MVC和Hibernate来开发一个Web应用程序。起初,我只使用标准的JSR303注释。然后,我决定使用一些自定义注释来验证一个新用户的用户名和电子邮件的唯一性,该用户希望创建一个帐户。 因此,我创建了两个注释,如下所示(一个用于电子邮件,另一个用于用户名):

  • 我有以下验证器,用于验证更新请求。 object.getIdCreditor()有一个值,但是findById方法的执行["CreditorRepository.findById(object.getIdCreditor())" ] 进入NullPointer异常 我不明白怎么了。

  • 表单验证发生在数据验证之后。如果你需要定制化这个过程,有几个不同的地方可以修改,每个地方的目的不一样。表单处理过程中要运行三种类别的验证方法。它们通常在你调用表单的is_valid() 方法时执行。还有其它方法可以触发验证过程(访问errors 属性或直接调用full_clean() ),但是通用情况下不需要。 一般情况下,如果处理的数据有问题,每个类别的验证方法都会引发ValidationErr

  • 这里有一个小问题,希望这个问题也能帮助其他想知道更多关于注释验证的人 我目前正在研究Spring,目前,我计划尝试定制注释验证。 我搜索了很多,现在我知道主要有两种验证,一种用于控制器,另一种是使用@Valid的注释方法 在此之后,我需要创建验证器本身: 另一个想法是使用同一个类作为一个例子,它说我想要生日,confirmBirthday和birthdayMessdage只能同时为null或反对。