WebFlux中如何用Mono基于不同结果编排支付操作链?
问题:Reactor Mono 是否支持编排带分支判断的操作链?
我需要编排以下操作链:
- A) 调用
boolean checkUserPayment(Long userId)检查用户是否已支付; - B) 若A返回true,则终止流程并返回
Mono.just(PaymentResponse.alreadyPaid(userId));若A返回false,则继续执行UserInformation fetchUserInformationFromAPI(Long userID)获取用户信息; - C) 若
fetchUserInformationFromAPI返回有效用户信息,则执行步骤D; - D) 通过
PaymentResponse sendPaymentRequest(PaymentRequest paymentRequest)发起支付请求; - E) 若
fetchUserInformationFromAPI未返回用户信息或执行出错,则不执行D,而是返回Mono.just(PaymentResponse.Error(throwable))。
最终要实现一个Mono<PaymentResponse> initiatePayment(Long userID)方法来完成上述编排,请问Mono是否支持此类场景?
补充说明:我希望用单一方法实现,对应的非响应式版本代码如下:
public PaymentResponse initiatePayment(Long userId) { if (checkUserPayment(userId)) { return PaymentResponse.AlreadyPaid(userId); } UserInformation ui = fetchUserInformationFromAPI(userId); if (ui == null) { return PaymentResponse.Error(userId); } PaymentRequest paymentRequest = new PaymentRequest(userId, ui); // 假设需用用户信息构建请求 PaymentResponse pr = sendPaymentRequest(paymentRequest); if (pr == null) { return PaymentResponse.Error(userId); } return pr; }
回答
Mono完全支持这类带条件分支、错误处理的操作链编排,Reactor提供的filterWhen、flatMap、onErrorResume等操作符可以完美实现你的需求。以下是单一方法的响应式实现:
public Mono<PaymentResponse> initiatePayment(Long userId) { // 步骤A:将同步检查方法包装为响应式流 return Mono.fromCallable(() -> checkUserPayment(userId)) // 步骤B:已支付则返回对应响应,未支付则继续流程 .filter(isPaid -> !isPaid) .switchIfEmpty(Mono.just(PaymentResponse.alreadyPaid(userId))) // 步骤B:未支付时获取用户信息 .flatMap(ignored -> Mono.fromCallable(() -> fetchUserInformationFromAPI(userId))) // 步骤C/E:用户信息为空时抛出异常,后续统一处理 .filter(Objects::nonNull) .switchIfEmpty(Mono.error(new IllegalStateException("用户信息为空"))) // 步骤D:构建支付请求并发起支付 .flatMap(userInfo -> Mono.fromCallable(() -> { PaymentRequest paymentRequest = new PaymentRequest(userId, userInfo); return sendPaymentRequest(paymentRequest); })) // 全局异常捕获:处理所有流程中的错误,返回统一错误响应 .onErrorResume(throwable -> Mono.just(PaymentResponse.Error(throwable))); }
代码说明:
- 步骤A&B:用
Mono.fromCallable把同步的checkUserPayment包装成响应式流,通过filter过滤已支付的情况,switchIfEmpty在已支付时直接返回对应响应。 - 步骤B&C&E:通过
flatMap调用fetchUserInformationFromAPI,用filter校验用户信息非空,空值时用switchIfEmpty抛出异常,后续由onErrorResume统一捕获并返回错误响应。 - 步骤D:拿到有效用户信息后构建支付请求,调用
sendPaymentRequest并包装为响应式流。 - 全局错误处理:
onErrorResume会捕获流程中所有异常(包括API调用失败、空值校验异常等),统一返回错误响应。
注:如果fetchUserInformationFromAPI或sendPaymentRequest本身是返回Mono的异步方法,直接替换Mono.fromCallable为对应方法即可,无需额外包装。
内容的提问来源于stack exchange,提问作者Thomas Lang
相关产品推荐
相关产品推荐

