bean验证不适用于spring webflux
Posted
技术标签:
【中文标题】bean验证不适用于spring webflux【英文标题】:Bean validation is not working for 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。
【问题讨论】:
【参考方案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;
【讨论】:
不是更好吗? :) github.com/spring-projects/spring-boot/issues/…【参考方案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 响应以上是关于bean验证不适用于spring webflux的主要内容,如果未能解决你的问题,请参考以下文章
Bean 验证 @Positive 指令不适用于 Integer @PathVariable