20. Triggering Transitions

驱动状态机是通过由触发器触发的转换完成的。 目前支持的触发器是EventTrigger和TimerTrigger。

20.1 EventTrigger

EventTrigger是最有用的触发器,因为它允许用户通过向它发送事件直接与状态机进行交互。 这些事件也被称为信号。 只需通过在配置期间将状态与其关联即可将触发器添加到转换中。

@Autowired
StateMachine<States, Events> stateMachine;

void signalMachine() {
    stateMachine.sendEvent(Events.E1);

    Message<Events> message = MessageBuilder
            .withPayload(Events.E2)
            .setHeader("foo", "bar")
            .build();
    stateMachine.sendEvent(message);
}

在上面的例子中,我们使用两种不同的方式发送事件。 首先,我们使用状态机API方法sendEvent(E事件)发送一个类型安全的事件。 其次,我们使用api方法sendEvent(Message <E> message)发送包含在Spring消息消息中的事件和自定义事件头。 这允许用户通过事件添加任意额外的信息,当用户正在执行操作时,该事件对StateContext可见。

通常会传递消息标题,直到机器运行完成以执行特定事件。 例如,如果一个事件正在转换到一个状态为A的匿名状态转换为状态B,那么原始事件可用于状态B中的操作或警卫。

20.2 TimerTrigger

当需要在没有任何用户交互的情况下自动触发某些事件时,TimerTrigger非常有用。 通过在配置期间将定时器与定时器相关联,触发器被添加到转换中。

目前支持两种类型的定时器,一种是连续触发的,另一种是一旦输入源状态就触发。

@Configuration
@EnableStateMachine
public class Config2 extends StateMachineConfigurerAdapter<String, String> {

    @Override
    public void configure(StateMachineStateConfigurer<String, String> states)
            throws Exception {
        states
            .withStates()
                .initial("S1")
                .state("S2")
                .state("S3");
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<String, String> transitions)
            throws Exception {
        transitions
            .withExternal()
                .source("S1").target("S2").event("E1")
                .and()
            .withExternal()
                .source("S1").target("S3").event("E2")
                .and()
            .withInternal()
                .source("S2")
                .action(timerAction())
                .timer(1000)
                .and()
            .withInternal()
                .source("S3")
                .action(timerAction())
                .timerOnce(1000);
    }

    @Bean
    public TimerAction timerAction() {
        return new TimerAction();
    }
}

public class TimerAction implements Action<String, String> {

    @Override
    public void execute(StateContext<String, String> context) {
        // do something in every 1 sec
    }
}

在上面我们有三个状态,S1,S2和S3。 我们有一个正常的外部转换,从S1到S2,从S1到S3分别有事件E1和E2。 有趣的部分是当我们为源状态S2和S3定义内部转换时。

对于这两个转换,我们将Action bean timerAction关联到源状态S2将使用计时器并且S3将使用timerOnce。 给出的值是毫秒,在这些情况下意味着1000毫秒。

一旦状态机接收到事件E1,就执行从S1到S2的转换并启动定时器。只要状态保持在S2中,TimerTrigger执行并导致与该状态相关的转换,在这种情况下,该转换是具有timerAction的内部转换定义。

一旦状态机接收到事件E2,就从S1转换到S3,并且定时器启动。在定时器定义的延迟之后进入状态后,该定时器只执行一次。

幕后计时器是一个简单的触发器,可能会导致转换发生。 使用定时器()定义转换将保持触发触发器,并且只有在源状态处于活动状态时才会导致转换。 使用timerOnce()进行转换有点不同,因为它只会在实际输入源状态后的延迟之后触发。

使用timerOnce()如果你想要在延迟之后发生某些事情,那么只要进入状态一次。

results matching ""

    No results matching ""