简体   繁体   English

bean验证不适用于spring webflux

[英]Bean validation is not working for spring webflux

I have refactored my code to use spring webflux but now @Valid stopped working.我已经重构了我的代码以使用 spring webflux 但现在@Valid停止工作。 It is not validating the request body.它没有验证请求正文。

@PostMapping(value = "/getContactInfo",produces = "application/json",consumes = "application/json")
public Flux<UserContactsModel> getUserContacts(@Valid @RequestBody Mono<LoginModel> loginDetail) {

    loginDetail.log();
    return contactInfoService
        .getUserContacts(loginDetailApiMapper.loginModelMonoToLoginBoMono(loginDetail))
        .flatMapIterable(
            userContactsBO -> contactInfoMapper.userContactBoToModelList(userContactsBO));
}

I am getting 200 OK in place of Bad request which I am returning from the controller advice.我得到 200 OK 代替我从控制器建议返回的 Bad request。

Edit 1:编辑1:

   import javax.validation.constraints.NotNull;
   import javax.validation.constraints.Pattern;

    public class LoginModel implements Serializable {

      private String clientId;

      @Pattern(regexp = "^[a-zA-Z0-9]*$", message = "Login ID is invalid")
      @NotNull
      private String loginId;
    }

update 1: After changing the code like this and adding @Validated on class level更新1:更改这样的代码并在类级别添加@Validated

@RestController
@Validated
public class ContactInfoController implements ContactInfoApi {
public Flux<UserContactsModel> getUserContacts(@RequestBody  Mono<@Valid  LoginModel> loginDetail) {

I am getting javax.validation.ConstraintDeclarationException: HV000197: No value extractor found for type parameter 'T' of type reactor.core.publisher.Mono.我收到 javax.validation.ConstraintDeclarationException: HV000197: No value extractor found for type parameter 'T' of type reactor.core.publisher.Mono。

@Valid annotation validates an object. @Valid批注验证对象。 So you are trying to validate a Mono, you need to change to LoginModel object, for example: 因此,您尝试验证Mono时,需要更改为LoginModel对象,例如:

  ..getUserContacts(@RequestBody Mono<@Valid LoginModel> loginDetail) {
      ...
  }

Nothing worked for me. 什么都没有为我工作。 So I validated it manually by using javax.validator. 因此,我使用javax.validator对其进行了手动验证。

@Autowired private Validator validator;

 public Flux<UserContactsModel> getUserContacts(@RequestBody Mono<@Valid LoginModel> loginDetail) {

    return loginDetail
        .filter(this::validate)
        .map(....);
}

 private boolean validate(LoginModel loginModel) {

    Set<ConstraintViolation<LoginModel>> constraintViolations = validator.validate(loginModel);

    if (CollectionUtils.isNotEmpty(constraintViolations)) {
      StringJoiner stringJoiner = new StringJoiner(" ");
      constraintViolations.forEach(
          loginModelConstraintViolation ->
              stringJoiner
                  .add(loginModelConstraintViolation.getPropertyPath().toString())
                  .add(":")
                  .add(loginModelConstraintViolation.getMessage()));
      throw new RuntimeException(stringJoiner.toString());
    }

    return true;
  }

For me the @Valid worked out of the box, the missing piece was adding spring-boot-starter-validation in the classpath:对我来说,@ @Valid开箱即用,缺少的部分是在类路径中添加spring-boot-starter-validation

  <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
  </dependency>

I have the exact same controller code as in this question plus a ExceptionHandler to handle the bean validation errors:我有与这个问题完全相同的控制器代码加上一个ExceptionHandler来处理 bean 验证错误:

@ResponseBody
@ExceptionHandler(WebExchangeBindException.class)
Mono<ResponseEntity<List<ErrorDTO>>> invalidRequestErrorHandler(@NotNull final WebExchangeBindException e) {
    log.error("Invalid request exception occurred", e);
    var errors = e.getBindingResult()
            .getAllErrors()
            .stream()
            .filter(Objects::nonNull)
            .map(this::getValidationErrorMessage)
            .toList();
    return Mono.just(ResponseEntity.status(BAD_REQUEST)
            .contentType(APPLICATION_JSON)
            .body(errors));
}

@NotNull
private ErrorDTO getValidationErrorMessage(@NotNull final ObjectError error) {
    final var errorMessage = new StringBuilder();
    if (error instanceof FieldError fe) {
        errorMessage.append(fe.getField()).append(" - ");
    }
    errorMessage.append(error.getDefaultMessage());
    return new ErrorDTO()
            .errorCode(GENERIC_ERROR).message(errorMessage.toString());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM