使用 Spring Reactive 时如何验证 Mono

Posted

技术标签:

【中文标题】使用 Spring Reactive 时如何验证 Mono【英文标题】:How to validate Mono when using Spring Reactive 【发布时间】:2018-04-24 23:32:10 【问题描述】:

我们正在为一个项目评估 Spring 5,但不确定如何最好地验证 Mono 参数。传统上,我们一直使用 MethodValidationPostProcessor 来验证我们的方法参数,如下所示:

@Validated
@Service
public class FooService

@Validated(SignUpValidation.class)
public void signup(@Valid UserCommand userCommand) 

    ...

然后我们将在ControllerAdviceErrorController 中处理异常,并将合适的 4xx 响应传递给客户端。

但是当我将参数更改为Mono时,如下所示,它似乎不再起作用了。

@Validated
@Service
public class FooService

@Validated(SignUpValidation.class)
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand) 

    ...

据我了解 Spring Reactive,可能它实际上不应该工作。那么,验证 Monos 和 Fluxes,然后发送合适的错误响应的 Spring 5 最佳实践是什么?

【问题讨论】:

【参考方案1】:

在回答这个问题之前不要急,您方法的 void 返回类型在反应式应用程序中是非常不寻常的。看这个,似乎这个方法应该异步执行实际工作,但该方法返回一个同步类型。我在回答中将其更改为Mono&lt;Void&gt;

As stated in the reference documentation,Spring WebFlux 确实支持验证。

但最佳实践在这里有所不同,因为方法参数可以是反应类型。如果方法参数尚未解析,则无法获得验证结果。

所以这样的事情不会真正起作用:

// can't have the BindingResult synchronously,
// as the userCommand hasn't been resolved yet
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand, BindingResult result)

// while technically feasible, you'd have to resolve 
// the userCommand first and then look at the validation result
public Mono<Void> signup(@Valid Mono<UserCommand> userCommand, Mono<BindingResult> result)

反应式操作符更惯用且更易于使用:

public Mono<Void> signup(@Valid Mono<UserCommand> userCommand) 
    /*
     * a WebExchangeBindException will flow through the pipeline
     * in case of validation error.
     * you can use onErrorResume or other onError* operators
     * to map the given exception to a custom one
     */
    return userCommand.onErrorResume(t -> Mono.error(...)).then();

【讨论】:

谢谢!将我的问题编辑为 Mono。我看到 @Valid 在控制器中工作,但是验证组,例如@Validated(SignUpValidation.class),不工作。此外,使用MethodValidationPostProcessor 验证服务方法(参见我上面的示例)也不起作用。顺便说一句,我找不到您提到的参考文档(您写了“如参考文档中所述,Spring WebFlux 确实支持验证”)。那是哪里? 我认为 WebFlux 不支持验证组;这可能值得在官方问题跟踪器(jira.spring.io)上提出。参考文档中的相关部分仅提及验证输入参数,请参阅docs.spring.io/spring-framework/docs/current/… 刚刚检查过 - 控制器支持验证组,但 MethodValidationPostProcessor 不支持(有一张票:jira.spring.io/browse/SPR-16234)。

以上是关于使用 Spring Reactive 时如何验证 Mono的主要内容,如果未能解决你的问题,请参考以下文章

如何将 GlobalMethodSecurityConfiguration 迁移到 Reactive Spring?

如何在 Spring WebFlux Security(Reactive Spring Security)配置中将多个用户角色添加到单个 pathMatcher/Route?

Reactive Spring实战 -- 响应式Kafka交互

Spring WebFlux Reactive 和 Kotlin Coroutines 启动错误

使用 Spring Security OAuth 时 Spring Boot Reactive WebClient “serverWebExchange must be null”

Reactive-Spring-Security-5.1.3.RELEASE,多重授权