Spring state-machine:常见的过渡

时间:2018-02-13 08:42:09

标签: spring-boot spring-statemachine

有没有办法为多个事件配置公共外部转换? 即

  1. 对于所有状态X,Y,Z - >在CANCEL活动上取消。 其中 X,Y,Z - 来源取消 - 目标状态
  2. 对于取消状态,在所有事件上运行常见内部转换
  3. 我有超过20个州应用此过渡,并且手动配置所有这些过程都不方便。

    我正在使用EnumStateMachineConfigurerAdapter@EnableStateMachineFactory配置状态机,我的配置如下所示

    @Configuration
    @EnableStateMachineFactory
    public class ContentOnlyStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskState, WorkflowEvent> {
    
    private final Action<TaskState, WorkflowEvent> someAction;
    private final Action<TaskState, WorkflowEvent> anotherAction;
    
    @Autowired
    public ContentOnlyStateMachineConfig(
            final Action<TaskState, WorkflowEvent> someAction,
            final Action<TaskState, WorkflowEvent> anotherAction) {
        this.someAction = someAction;
        this.anotherAction = anotherAction;
    }
    
    
    
    
    @Override
    public void configure(final StateMachineStateConfigurer<TaskState, WorkflowEvent> states)
            throws Exception {
    
        states
                .withStates()
                .initial(TaskState.CONTENT)
                .end(TaskState.COMPLETE)
                .state(TaskState.CONTENT, someAction)
                .state(TaskState.COMPLETE, anotherAction);
    
    }
    
    @Override
    public void configure(
            final StateMachineTransitionConfigurer<TaskState, WorkflowEvent> transitions)
            throws Exception {
    
        transitions
                .withExternal()
                .source(TaskState.CONTENT).target(TaskState.SOME_STATE)
                .event(WorkflowEvent.EXCEPTION)
                .and()
                .withExternal()
                .source(TaskState.EXCEPTION).target(TaskState.CANCELED)
                .event(WorkflowEvent.CANCEL)
                .and()
                .withExternal()
                .source(TaskState.SOME_STATE_2).target(TaskState.SOME_STATE_1)
                .event(WorkflowEvent.SOME_EVENT_3)
                .and()
                .withExternal()
                .source(TaskState.SOME_STATE).target(TaskState.SOME_STATE_2)
                .event(WorkflowEvent.SOME_EVENT_2)
                .and()
                .withExternal()
                .source(TaskState.SOME_STATE).target(TaskState.COMPLETE)
                .event(WorkflowEvent.ADMIN_ACCEPT)
                .and()
                .withExternal()
                .source(TaskState.SOME_STATE).target(TaskState.CONTENT)
                .event(WorkflowEvent.SOME_EVENT);
    }
    }
    

2 个答案:

答案 0 :(得分:2)

不允许用户创建意大利面条的快捷方式;)。话虽如此,如果您在纸上绘制后的状态图看起来像意大利面,而不是那个清晰的状态图,我会说你做错了。

将所有东西放在一台平板电脑中很容易造成这种状态爆炸乳清配置本身开始变得难以理解。通常这是机器设计师需要开始考虑使用嵌套子状态的时刻。如果您有多个状态,其中同一事件应使机器处于相同状态,则您已在这些状态中具有共享功能。

将这些状态放入子状态将允许从其父状态的单个转换转移。这通常是在机器中完成工作的模型。

答案 1 :(得分:0)

不支持即用即用的方法来配置具有多个源和单个目标的过渡。

需要明确地执行此操作。
例如:

@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {

    transitions.withExternal()
    // normal transitions configuration ..

    // common error transitions
    for (var state : EnumSet.of(States.A, States,B, States.C)) { 
        transitions.withExternal().source(state).target(States.ERROR).event(ERROR_EVENT);
    }
}

(由于Stream.of()引发了已检查的异常,因此无法使用withExternal()。)