基于Flux实现状态模式递归流转时类型不匹配问题求解
问题分析
你遇到的编译报错核心原因是泛型类型不匹配,具体问题有3个:
go方法声明返回值为Flux<SelectionState>,但方法内部flatMap的两个分支返回值类型不统一:action为空时返回Flux<SelectionStateResult>,action非空时返回递归调用go()得到的Flux<SelectionState>,泛型参数无法推断,触发报错。move方法中ACTION_FETCH_OFFERS分支只调用了state.fetchOffers(request),没有把方法返回值赋值给result,会直接返回空Flux,属于逻辑bug。- 自行实现的递归
flatMap写法不符合响应式流规范,高并发场景下存在栈溢出风险。
修复方案
直接使用WebFlux内置的expand操作符实现状态流转,该操作符专门用于处理迭代/递归生成流的场景,天然符合你的状态机流转需求。
修复后代码
SelectionMachine核心逻辑
private Flux<SelectionState> run(OfferSelectionRequest request) { // 构造初始状态结果,包含初始状态、启动Action和上下文 Flux<SelectionStateResult> initialState = Flux.just(new SelectionStateResult(selectionRequested, ACTION_START, new SelectionContext(request))); return initialState.expand(stateResult -> { // action为空时返回空Flux,终止状态流转 if (stateResult.getAction().isEmpty()) { return Flux.empty(); } // action非空时调用move执行对应逻辑,获取下一个状态流 return move(stateResult.getState(), stateResult.getAction().get(), stateResult.getContext().getRequest()); }) // 提取结果中的状态返回 .map(SelectionStateResult::getState); // 如果你只需要最终的终止状态,在末尾追加.last()即可: // .map(SelectionStateResult::getState).last(); } private Flux<SelectionStateResult> move(SelectionState state, Action action, OfferSelectionRequest request) { Flux<SelectionStateResult> result = Flux.empty(); if (ACTION_START.equals(action)) { result = state.start(request); } else if (ACTION_FETCH_OFFERS.equals(action)) { // 修复漏赋值问题,将方法返回值赋值给result result = state.fetchOffers(request); } else { result = Flux.just(new SelectionStateResult(state)); } return result; }
原递归go方法可以直接删除。
需求匹配验证
修复后的代码完全满足你的四个业务需求:
- 从初始状态和初始Action启动执行:run方法中已经构造了包含初始状态和
ACTION_START的初始流作为流转入口 - 状态执行结束后返回新的状态和对应Action:
move方法调用对应状态的执行逻辑,返回的SelectionStateResult已包含新状态和下一个要执行的Action - 若返回的Action和State均不为空,则在新返回的State上执行对应Action:
expand操作符会自动遍历每一个状态结果,Action非空时就触发下一轮执行 - 若返回的Action为null,则直接返回当前State,终止执行:Action为空时
expand返回空流,终止流转,所有流转过程的状态都会被返回,仅需最终状态可追加.last()操作符。
内容的提问来源于stack exchange,提问作者Gurucharan Sharma
相关产品推荐
相关产品推荐

