Реализация нескольких ConstraintValidator и их приоритет (включение / отключение по конечной точке запросов) - PullRequest
0 голосов
/ 03 августа 2020

Допустим, у меня есть объект с двумя полями, которые следует проверить:

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

}

Обе аннотации @MerchantAccountValidation и @RequestIdValidation реализуют ConstraintValidator и включают правила, которые должны быть действительными или не. (Просто покажите один класс)

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

Есть ли способ добиться определенного приоритета или наследования, чтобы заставить это работать? Я думал о том, чтобы иметь аннотацию проверки на уровне метода конечных точек. Но, к сожалению, это не работает.

1 Ответ

1 голос
/ 03 августа 2020

Patrick!

Для достижения желаемого результата вы можете использовать @GroupSequence. В основном это предназначалось для заказа проверок (нет необходимости проверять, существует ли объект в базе данных, если id равен нулю, fe), но будет работать для вашей задачи. Допустим, у вас есть 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;

}

И в контроллере используйте @Validated вместо @ Действительно для предоставления соответствующей группы:

@RestController

@ RequestMapping ("/ validate") publi c class ValidController {

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

...