【问题标题】:Bean validation is not working for spring webfluxbean验证不适用于spring webflux
【发布时间】:2019-05-22 02:40:51
【问题描述】:

我已重构代码以使用 spring webflux,但现在 @Valid 停止工作。 它没有验证请求正文。

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

我得到 200 OK 代替我从控制器建议返回的 Bad request。

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

更新 1: 像这样更改代码并在类级别添加@Validated

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

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

【问题讨论】:

    标签: java validation spring-boot spring-webflux reactive


    【解决方案1】:

    没有什么对我有用。所以我使用 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;
      }
    

    【讨论】:

    【解决方案2】:

    对我来说,@Valid 开箱即用,缺少的部分是在类路径中添加 spring-boot-starter-validation

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

    我有与这个问题完全相同的控制器代码加上一个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());
    }
    

    【讨论】:

      【解决方案3】:

      @Valid 注解验证一个对象。所以你要验证一个 Mono,你需要更改为 LoginModel 对象,例如:

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

      【讨论】:

      • 我也试过了,但没有用。我还需要别的吗?
      • 你能发布 LoginModel 类吗?你在使用一些自定义验证器吗?
      • 已编辑。添加登录模型。
      • javax.validation.ConstraintDeclarationException:HV000197:没有为类型 reactor.core.publisher.Mono 的类型参数“T”找到值提取器。 .现在得到这个
      • 在类级别添加@Validated 后我得到了这个,否则不会发生验证,我像以前一样得到 200 OK 响应
      猜你喜欢
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      • 2018-08-16
      • 2013-11-07
      • 2011-11-01
      • 2019-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多