gpt4 book ai didi

java - validator 调用 "Return value constraints"两次

转载 作者:太空宇宙 更新时间:2023-11-04 09:33:23 24 4
gpt4 key购买 nike

在 Spring Boot 项目中,我需要验证业务规则,并且我尝试使用 Bean Validation 来实现此目的。

我编写了一个单独的类来放置我的业务规则,并通过使用“返回值约束”技术来实现。但是,Validator.validate() 方法调用我的约束方法两次。

为什么?以及如何解决这个问题?

下面的简单代码更容易理解问题:

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Autowired
private Validator validator;

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
DemoObject obj = new DemoObject();
validator.validate(obj);
}
}

class DemoObject {
@AssertTrue(message="My business rule was failed")
public boolean isMyBusinessRule() {
System.out.println("isMyBusinessRule called");
// ... my business rule validation code ...
return true;
}
}

方法 isMyBusinessRule() 被调用两次。输出控制台显示:

isMyBusinessRule called
isMyBusinessRule called

如何解决这个问题?

最佳答案

我刚刚使用 Spring Boot 2.2 对其进行了测试,我注意到了同样的事情。
现在,您甚至不应该考虑 Hibernate Validator 实现调用该方法一次、两次甚至多次的事实。

仅供记录,在处理验证之前第一次调用它以检查是否需要验证。
如果需要验证,则处理约束并再次读取:因此第二次调用带有注释的方法。
下面是我用 3 条注释来解释流程的方法:

private boolean validateMetaConstraint(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Object parent, MetaConstraint<?> metaConstraint) {
// .... FIRST INVOCATION
if ( isValidationRequired( validationContext, valueContext, metaConstraint ) ) {

if ( parent != null ) {
// .... SECOND INVOCATION with valueContext.getValue()
valueContext.setCurrentValidatedValue( valueContext.getValue( parent, metaConstraint.getLocation() ) );
}

success = metaConstraint.validateConstraint( validationContext, valueContext );

validationContext.markConstraintProcessed( valueContext.getCurrentBean(), valueContext.getPropertyPath(), metaConstraint );
}
// ....
}

该行为来自 ValueContext class它存储验证信息,并且可以出于优化或处理原因多次调用:

An instance of this class is used to collect all the relevant information for validating a single class, property or method invocation.

仍然忘记,这是实现的细节,明天在下一个版本中,带注释的方法可以被调用一次,并且它永远不会破坏您的逻辑。所以不要依赖它。

重要的是 API 尊重其契约并且确实做到了:即使该方法被实现调用两次,也会返回一个验证错误。

public class DemoObj {

private final boolean value;

DemoObj(boolean value){
this.value = value;
}
@AssertTrue(message = "My business rule was failed")
public boolean isMyBusinessRule() {
System.out.println("isMyBusinessRule called");
return value;
}
}

使用它:

Set<ConstraintViolation<DemoObj>> constraintViolations = validator.validate(new DemoObj (true));
System.out.println("validations errors : " + constraintViolations.size());

constraintViolations = validator.validate(new DemoObj (false));
System.out.println("validation errors : " + constraintViolations.size());

输出:

isMyBusinessRule called
isMyBusinessRule called
validations errors : 0
isMyBusinessRule called
isMyBusinessRule called
validation errors : 1

关于java - validator 调用 "Return value constraints"两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56811785/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com