使用JSR-303和Spring的Validator的组合为Spring引导端点实现自定义验证逻辑 [英] Implementing custom validation logic for a spring boot endpoint using a combination of JSR-303 and Spring's Validator
问题描述
我正在尝试使用 JSR-303 Bean Validation API
和的组合来为Spring引导端点实现一些自定义验证逻辑Spring的Validator
。
基于Validator类图,似乎可以扩展 CustomValidatorBean $ c $中的一个c>,
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屋!