You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

代码说明:

  1. 步骤A&B:用Mono.fromCallable把同步的checkUserPayment包装成响应式流,通过filter过滤已支付的情况,switchIfEmpty在已支付时直接返回对应响应。
  2. 步骤B&C&E:通过flatMap调用fetchUserInformationFromAPI,用filter校验用户信息非空,空值时用switchIfEmpty抛出异常,后续由onErrorResume统一捕获并返回错误响应。
  3. 步骤D:拿到有效用户信息后构建支付请求,调用sendPaymentRequest并包装为响应式流。
  4. 全局错误处理:onErrorResume会捕获流程中所有异常(包括API调用失败、空值校验异常等),统一返回错误响应。

注:如果fetchUserInformationFromAPI或sendPaymentRequest本身是返回Mono的异步方法,直接替换Mono.fromCallable为对应方法即可,无需额外包装。

内容的提问来源于stack exchange,提问作者Thomas Lang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:50:11