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

Spring State Machine 基于条件变更状态的正确实现方式咨询

核心问题分析

  1. 逻辑执行时机错误
    你当前写的packageAction()方法是在创建Action实例的时候判断packed变量的值,而非Action实际被状态机调用执行时动态判断。方法返回的lambda表达式里才是过渡触发时真正会执行的逻辑,你把业务判断写到了lambda外面,逻辑自然不会按预期触发。
  2. 未绑定Action到过渡规则
    你只定义了Action方法,没有在过渡配置中将它和NEW到PACKAGED的过渡关联,状态机触发对应过渡时根本不会执行这段逻辑。

修复方案

1. 修正Action逻辑

把打包业务判断和事件发送都放到lambda内部,保证每次过渡触发时都会动态执行:

public Action<States, Events> packageAction() {
  return context -> {
    // 此处为过渡触发时实际执行的打包业务逻辑
    boolean packed = executePackagingBusiness(); 
    // 发送事件后可以判断返回值确认是否发送成功,避免状态机未就绪导致事件丢失
    if(packed){
      context.getStateMachine().sendEvent(Events.process);  
    }else{
      context.getStateMachine().sendEvent(Events.error);
    }
  };
}

2. 绑定Action到过渡配置

修改你的过渡配置代码,给NEW到PACKAGED的过渡添加action绑定:

@Override
public void configure(final StateMachineTransitionConfigurer<States, Events> transitions)
  throws Exception {
     transitions
    .withExternal()
    .source(States.NEW).target(States.PACKAGED).event(Events.pack)
    .action(packageAction()) // 新增这行绑定打包逻辑
    .and()
    // 剩余原有过渡规则保持不变即可
    .withExternal()
    .source(States.PACKAGED).target(States.PROCESS).event(Events.process)
    .and()
    .withExternal()
    .source(States.PACKAGED).target(States.ERROR).event(Events.error)
    .and()
    .withExternal()
    .source(States.PROCESS).target(States.DELIVER).event(Events.deliver)
    .and()
    .withExternal()
    .source(States.PROCESS).target(States.ERROR).event(Events.error);
}

更符合状态机规范的优化方案

你也可以不用在Action里主动发事件,改用状态机原生的Guard(守卫)实现条件分支,逻辑更清晰也更符合状态机的设计理念:

  1. 定义守卫判断逻辑
// 打包成功守卫
public Guard<States, Events> packSuccessGuard() {
  return context -> {
    boolean packed = executePackagingBusiness();
    // 可以将打包结果存入扩展状态供后续逻辑使用
    context.getExtendedState().getVariables().put("packSuccess", packed);
    return packed;
  };
}

// 打包失败守卫
public Guard<States, Events> packFailGuard() {
  return context -> !Boolean.TRUE.equals(context.getExtendedState().getVariables().get("packSuccess"));
}
  1. 调整过渡配置添加守卫
.transitions
.withExternal()
.source(States.NEW).target(States.PACKAGED).event(Events.pack)
.and()
.withExternal()
.source(States.PACKAGED).target(States.PROCESS).event(Events.process)
.guard(packSuccessGuard())
.and()
.withExternal()
.source(States.PACKAGED).target(States.ERROR).event(Events.error)
.guard(packFailGuard())
// 剩余其他过渡规则保持不变

内容的提问来源于stack exchange,提问作者pranay jain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 22:36:04