使用JSR-303和Spring的Validator的组合为Spring引导端点实现自定义验证逻辑 [英] Implementing custom validation logic for a spring boot endpoint using a combination of JSR-303 and Spring's Validator

查看:398
本文介绍了使用JSR-303和Spring的Validator的组合为Spring引导端点实现自定义验证逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 JSR-303 Bean Validation API 的组合来为Spring引导端点实现一些自定义验证逻辑Spring的Validator

基于Validator类图,似乎可以扩展 CustomValidatorBean SpringValidatorAdapter LocalValidatorFactoryBean 将一些自定义验证逻辑添加到重写方法 validate(对象目标,错误错误)

Based on the Validator class diagram it appears to be possible to extend one of CustomValidatorBean, SpringValidatorAdapter or LocalValidatorFactoryBean to add some custom validation logic into an overridden method validate(Object target, Errors errors).

但是,如果我创建一个验证器来扩展这三个类中的任何一个并使用 @InitBinder 注册它的 validate(对象目标,错误)错误)永远不会调用方法,也不会执行验证。如果我删除 @InitBinder ,那么默认的spring验证器会执行 JSR-303 Bean验证

However, if I create a validator extending any of these three classes and register it using @InitBinder its validate(Object target, Errors errors) method is never invoked and no validation is performed. If I remove @InitBinder then a default spring validator performs the JSR-303 Bean Validation.

休息控制器:

@RestController
public class PersonEndpoint {

    @InitBinder("person")
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new PersonValidator());
    }

    @RequestMapping(path = "/person", method = RequestMethod.PUT)
    public ResponseEntity<Person> add(@Valid @RequestBody Person person) {

        person = personService.save(person);
        return ResponseEntity.ok().body(person);
    }
}

自定义验证器:

public class PersonValidator extends CustomValidatorBean {

    @Override
    public boolean supports(Class<?> clazz) {
        return Person.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        super.validate(target, errors);
        System.out.println("PersonValidator.validate() target="+ target +" errors="+ errors);
    }

}

如果我的验证器实现 org.springframework.validation.Validator 然后调用它的 validate(对象目标,错误错误)方法,但之前未执行JSR-303 Bean验证。我可以实现我的自定义JSR-303验证,类似于 SpringValidatorAdapter 实现其 JSR-303 Bean验证的方式但是有改为扩展它的方法:

If my validator implements org.springframework.validation.Validator then its validate(Object target, Errors errors) method is called but JSR-303 Bean Validation is not performed prior to it. I can implement my custom JSR-303 validation similar to the way SpringValidatorAdapter implements its JSR-303 Bean Validation but there has to be a way to extend it instead:

    @Override
    public void validate(Object target, Errors errors) {
        if (this.targetValidator != null) {
            processConstraintViolations(this.targetValidator.validate(target), errors);
        }
    }

我看过使用自定义JSR-303约束来避免一起使用 org.springframework.validation.Validator ,但必须有办法让自定义验证器工作。

I have looked at using custom JSR-303 constraints to avoid using org.springframework.validation.Validator all together but there must be a way to make a custom validator work.

Spring 验证文档不是结合两者非常明确:

Spring validation documentation is not super clear on combining the two:


应用程序还可以为每个DataBinder实例注册其他Spring Validator实例,如第9.8.3节所述, 配置DataBinder。这可能对于在不使用注释的情况下插入验证逻辑非常有用。

An application can also register additional Spring Validator instances per DataBinder instance, as described in Section 9.8.3, "Configuring a DataBinder". This may be useful for plugging in validation logic without the use of annotations.

然后它接触到配置多个Validator实例

And then later on it touches on configuring multiple Validator instances


还可以通过dataBinder.addValidators和dataBinder.replaceValidators为多个Validator实例配置DataBinder。将全局配置的Bean验证与在DataBinder实例上本地配置的Spring验证器组合时,这非常有用。请参阅???。

A DataBinder can also be configured with multiple Validator instances via dataBinder.addValidators and dataBinder.replaceValidators. This is useful when combining globally configured Bean Validation with a Spring Validator configured locally on a DataBinder instance. See ???.

我正在使用spring boot 1.4.0。

I'm using spring boot 1.4.0.

推荐答案

Per @ M.Deinum - 使用addValidators()而不是setValidator()就可以了。我也同意使用JSR-303,@ AssertTrue基于方法的注释专门用于交叉字段验证,可能是一个更清洁的解决方案。 https://github.com上提供了一个代码示例。 / pavelfomin /弹簧引导休息,例如/树/特征/自定义验证。在该示例中,中间名称验证通过自定义弹簧验证器执行,而姓氏验证由默认的jsr 303验证器处理。

Per @M.Deinum - using addValidators() instead of setValidator() did the trick. I also agree that using JSR-303, @AssertTrue method-based annotation specifically for cross fields validation, is probably a cleaner solution. A code example is available at https://github.com/pavelfomin/spring-boot-rest-example/tree/feature/custom-validator. In the example, the middle name validation is performed via custom spring validator while last name validation is handled by the default jsr 303 validator.

这篇关于使用JSR-303和Spring的Validator的组合为Spring引导端点实现自定义验证逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆