多个 ConstraintValidator 的实现及其优先级(enable/disable by requests endpoint)

Implementatio of mutliple ConstraintValidator and their priority (enable/disable by requests endpoint)

假设我有一个包含两个应验证字段的对象:

public class AnyRQ {
    
    @MerchantAccountValidation
    @JsonProperty(value = "merchant-account")
    private MerchantAccount merchantAccount;
    
    @RequestIdValidation
    @JsonProperty(value = "request-id")
    private String requestId;

}

注释 @MerchantAccountValidation@RequestIdValidation 都实现了 ConstraintValidator 并包含了有效或无效的规则。 (只显示一个class)

 public class RequestIdValidator
    implements ConstraintValidator<RequestIdValidation, String> {

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.length() > 10;
    }    
}

现在我有一个带有两个端点的控制器。端点 1 应验证两个字段,但请求 2 应仅验证 requestId.

@RestController
@RequestMapping("/validate")
public class ValidController {
    
    @PostMapping("/endpoint1")
    public ResponseEntity<?> register(@Valid @RequestBody AnyRQ req, Errors errors) {
         if (errors.hasErrors()) {
         }
        return null;
    }

    @PostMapping("/endpoint2")
    public ResponseEntity<?> authorization(@Valid @RequestBody AnyRQ req, Errors errors) {
         if (errors.hasErrors()) {
         }
        return null;
    }
}

有什么方法可以实现某种优先级或继承来使它正常工作吗?我正在考虑在端点的方法级别上使用验证注释。但不幸的是,这不起作用。

帕特里克!

要达到预期的结果,您可以使用@GroupSequence。它主要用于排序验证(如果 id 为 null f.e,则无需检查数据库中是否存在实体),但可以完成您的任务。 假设您有 2 个验证组(需要更好的名称 :)):

public interface InitialValidation {
}

@GroupSequence(InitialValidation.class)
public interface InitialValidationGroup {
}

public interface FullValidation {
}

@GroupSequence(FullValidation.class)
public interface FullValidationGroup {
}

在 DTO 中指定它们:

public class AnyRQ {

@MerchantAccountValidation(groups = FullValidation.class)
@JsonProperty(value = "merchant-account")
private MerchantAccount merchantAccount;

@RequestIdValidation(groups = {InitialValidation.class, FullValidation.class})
@JsonProperty(value = "request-id")
private String requestId;

}

并且在controller中使用@Validated代替@Valid来提供对应的组:

@RestController

@RequestMapping("/验证") public class 有效控制器 {

@PostMapping("/endpoint1")
public ResponseEntity<?> register(@Validated(FullValidationGroup.class) @RequestBody AnyRQ req, Errors errors) {
     if (errors.hasErrors()) {
     }
    return null;
}

@PostMapping("/endpoint2")
public ResponseEntity<?> authorization(@Validated(InitialValidationGroup.class) @RequestBody AnyRQ req, Errors errors) {
     if (errors.hasErrors()) {
     }
    return null;
}
}

另一种选择是在 DTO 中保留一组,但在控制器中为 @Validated 指定两组。