添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
慷慨的枕头  ·  Little Rock Anime ...·  4 月前    · 
坚强的拖把  ·  iOS 18/17/16 ...·  4 月前    · 
爱旅游的西红柿  ·  Troubleshooting — ...·  5 月前    · 

14. Using Deferred Events

发送事件时,如果状态机处于成功评估触发器的状态,则可能会触发EventTrigger,然后可能会导致发生转换。 通常这可能导致事件不被接受并被丢弃的情况。 然而,可能需要推迟该事件,直到状态机进入其他可能接受该事件的状态。 换句话说,一个事件只是在不方便的时间到达。

Spring Statemachine提供了一种机制来延迟事件以便后续处理。 每个州可以有一个延期事件列表。 如果发生当前状态的延迟事件列表中的某个事件,则该事件将被保存(延迟)以供将来处理,直到输入一个未在延迟事件列表中列出事件的状态。 当输入这样的状态时,状态机将自动调用不再延迟的任何保存的事件,然后消耗或放弃这些事件。 超级城市有可能在由子状态推迟的事件上定义一个转换。 遵循相同的分层状态机概念,子状态优先于超状态,事件将被延迟,并且超状态的转换不会被执行。 对于正交区域,其中一个正交区域延迟事件,而另一个接受事件,接受优先,事件消耗且不延迟。

推迟事件最明显的用例是事件导致转换到特定状态,然后状态机返回到原来的状态,第二个事件应该导致相同的转换。 我们来看一个简单的例子。

@Configuration
@EnableStateMachine
static class Config5 extends StateMachineConfigurerAdapter<String, String> {
    @Override
    public void configure(StateMachineStateConfigurer<String, String> states)
            throws Exception {
        states
            .withStates()
                .initial("READY")
                .state("DEPLOYPREPARE", "DEPLOY")
                .state("DEPLOYEXECUTE", "DEPLOY");
    @Override
    public void configure(StateMachineTransitionConfigurer<String, String> transitions)
            throws Exception {
        transitions
            .withExternal()
                .source("READY").target("DEPLOYPREPARE")
                .event("DEPLOY")
                .and()
            .withExternal()
                .source("DEPLOYPREPARE").target("DEPLOYEXECUTE")
                .and()
            .withExternal()
                .source("DEPLOYEXECUTE").target("READY");

在上面的状态机中有READY状态,表示机器已准备好处理事件,这会将其置于实际部署将发生的DEPLOY状态。 部署操作执行完毕后,机器将返回到READY状态。 如果机器正在使用同步执行程序,发送READY状态下的多个事件不会引起任何问题,因为事件发送会阻止事件调用。 但是,如果执行程序正在使用线程,则其他事件可能会丢失,因为机器不再处于可以处理事件的状态。 因此推迟其中一些事件可以让机器保存这些事件。

@Configuration
@EnableStateMachine
static class Config6 extends StateMachineConfigurerAdapter<String, String> {
    @Override
    public void configure(StateMachineStateConfigurer<String, String> states)
            throws Exception {
        states
            .withStates()
                .initial("READY")
                .state("DEPLOY", "DEPLOY")
                .state("DONE")
                .and()
                .withStates()
                    .parent("DEPLOY")
                    .initial("DEPLOYPREPARE")
                    .state("DEPLOYPREPARE", "DONE")
                    .state("DEPLOYEXECUTE");
    @Override
    public void configure(StateMachineTransitionConfigurer<String, String> transitions)
            throws Exception {
        transitions
            .withExternal()
                .source("READY").target("DEPLOY")
                .event("DEPLOY")
                .and()
            .withExternal()
                .source("DEPLOYPREPARE").target("DEPLOYEXECUTE")
                .and()
            .withExternal()
                .source("DEPLOYEXECUTE").target("READY")
                .and()
            .withExternal()
                .source("READY").target("DONE")
                .event("DONE")
                .and()
            .withExternal()
                .source("DEPLOY").target("DONE")
                .event("DONE");

在上面使用嵌套状态而不是平坦状态模型的状态机中,可以直接在子状态中延迟事件DEPLOY。 它还显示了将事件DONE推迟到某个子状态的概念,如果在分派DONE事件时状态机碰巧处于DEPLOYPREPARE状态,那么该状态将覆盖DEPLOY和DONE状态之间的匿名转换。 在DEPLOYEXECUTE状态中,DONE事件不被延迟,因此事件将以超级状态处理。