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

Spring Reactor中实现增量式多条件校验逻辑的问题

实现Reactor链式短路校验(任一失败即终止并抛异常)

需求背景

现有三个返回Mono<Boolean>的异步校验方法:

Mono<Boolean> isRegistered(Student std);
Mono<Boolean> isEligible(Student std);
Mono<Boolean> isAvailable(Student std); 

需要实现短路式校验逻辑:只有前一个校验返回true时才执行下一个,任一校验返回false则立即终止流程并抛出异常,等价于同步逻辑中的isRegistered(std) && isEligible(std) && isAvailable(std)。

此前尝试的Mono.zip()不支持短路执行,then()链式调用会忽略前一步结果直接执行后续方法,均不符合需求。


正确实现方案:filter + flatMap链式调用

利用Reactor的filter操作符校验结果,失败时直接抛出异常;通过flatMap实现前一步校验成功后才执行后续方法的短路逻辑。

完整代码示例

Mono<Void> checkAll(Student std) {
    return isRegistered(std)
            // 校验注册状态,失败则抛异常
            .filter(registered -> {
                if (!registered) {
                    throw new IllegalStateException("学生未注册");
                }
                return true;
            })
            // 注册校验通过,执行资格校验
            .flatMap(registered -> isEligible(std))
            // 校验资格状态,失败则抛异常
            .filter(eligible -> {
                if (!eligible) {
                    throw new IllegalStateException("学生不符合资格");
                }
                return true;
            })
            // 资格校验通过,执行可用性校验
            .flatMap(eligible -> isAvailable(std))
            // 校验可用性状态,失败则抛异常
            .filter(available -> {
                if (!available) {
                    throw new IllegalStateException("学生不可用");
                }
                return true;
            })
            // 所有校验通过,返回空Mono表示成功
            .then();
}

代码说明

  • filter:若传入的断言返回false,会触发异常终止流程;这里手动抛出业务相关异常,便于后续精准处理。
  • flatMap:仅当前一个Mono成功返回true时,才会订阅并执行下一个校验方法,天然实现短路逻辑。
  • then():最终将Mono<Boolean>转换为Mono<Void>,若需要返回成功标记,可替换为map(available -> true)。

简化写法(通用校验逻辑)

如果所有校验失败的异常类型一致,可提取通用校验方法简化代码:

private Mono<Boolean> validate(Mono<Boolean> check, String errorMsg) {
    return check.filter(result -> {
        if (!result) {
            throw new IllegalArgumentException(errorMsg);
        }
        return true;
    });
}

Mono<Void> checkAll(Student std) {
    return validate(isRegistered(std), "学生未注册")
            .flatMap(ignored -> validate(isEligible(std), "学生不符合资格"))
            .flatMap(ignored -> validate(isAvailable(std), "学生不可用"))
            .then();
}

内容的提问来源于stack exchange,提问作者Mohammed Idris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:30:58