WebFlux请求体验证时机解析及指定场景下的验证实现方案
WebFlux 请求体验证时机及转发场景下的验证方案
一、WebFlux 何时验证请求体?
WebFlux里,用@Valid或@Validated标记请求体参数时,只有当请求体被订阅(subscribed)并实际解析为Java对象时,才会触发Bean Validation(JSR-380)的验证逻辑。
针对@RequestBody Mono<User>这类反应式参数:
- 要是只把
Mono直接传递(比如直接转给WebClient),因为没触发对象的实际解析,验证逻辑根本不会执行 - 只有调用
Mono的subscribe()、block(),或者通过flatMap、map等操作符消费其中的对象时,才会在对象实例化后触发验证
二、转发场景下触发请求体验证的解决方案
你提供的代码里,直接把Mono<User>传给WebClient的body()方法,没触发订阅解析,所以验证没生效。可以用下面两种方法解决:
方案1:手动触发验证并处理错误
在转发前,先通过Validator手动验证Mono中的对象,再执行转发:
import org.springframework.validation.annotation.Validated; import javax.validation.Validator; import javax.validation.ConstraintViolationException; @Controller @Validated public class IndexController { @Resource WebClient webClient; @Resource Validator validator; @PostMapping public Mono<User> index(@RequestBody Mono<User> userMono) { return userMono .doOnNext(user -> { // 手动执行验证 var violations = validator.validate(user); if (!violations.isEmpty()) { throw new ConstraintViolationException(violations); } }) .flatMap(this::getResponse); } private Mono<User> getResponse(User user) { return webClient.post() .bodyValue(user) .retrieve() .bodyToMono(User.class); } }
方案2:利用@Valid结合flatMap触发订阅
通过flatMap消费Mono,触发@Valid的自动验证逻辑,再转发:
@Controller public class IndexController { @Resource WebClient webClient; @PostMapping public Mono<User> index(@Valid @RequestBody Mono<User> userMono) { // flatMap会触发Mono订阅,从而触发@Valid的验证 return userMono .flatMap(user -> webClient.post() .bodyValue(user) .retrieve() .bodyToMono(User.class) ); } }
注意:要确保
User类已经添加了Bean Validation的约束注解(比如@NotNull、@Size),同时项目中引入了hibernate-validator这类Bean Validation依赖。验证失败时,WebFlux会自动抛出WebExchangeBindException,你可以通过@ExceptionHandler统一处理这类异常,返回定制化的错误响应。
内容的提问来源于stack exchange,提问作者Liam lin
相关产品推荐
相关产品推荐

