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
相关产品推荐
相关产品推荐

