Spring 发布 1.1 版 Statemachine 框架

  • Michael Redlich
  • 大愚若智

2016 年 6 月 11 日

话题:Java语言 & 开发架构AI

Spring最近发布了名为Statemachine的 1.1 版状态机(State machine)框架,该版本新增了如下功能:

  • 支持 Spring Security
  • 可与 @WithStateMachine 实现更进一步的集成
  • 内建对 Redis 的支持
  • 支持 UI 建模

根据 Spring Statemachine 官网介绍,Spring Statemachine“是一种供应用程序开发者在 Spring 应用程序中使用状态机概念的框架。”Statemachine 包含所有常用的核心 Spring 框架,例如通过 Spring 的 Inversion of Control 将 Bean 关联至有限状态机(Finite State Machine,FSM)的能力。

如果应用程序的状态数量是固定的,并且事件会按照顺序依次在不同状态之间转换,此时为应用程序部署 FSM 将能带来巨大的价值。Statemachine 会使用基于事件或计时器的触发器进行此类转换。

状态和事件可通过 String 和 Enumeration 这两种数据类型实现。

例如,我们要开发一个下列状态示意图所示的验票闸机:

在这个闸机的 FSM 中,有 LOCKED 和 UNLOCKED 两种状态,InsertToken 和 PassThru 两种事件,以及 Unlock、Lock、Alarm 和 Refund 四种操作。初始状态 LOCKED 是由示意图中该状态内部的同心圆代表的。发起 InsertToken 事件将触发一个 Unlock 操作,并将状态由 LOCKED 变为 UNLOCKED。一旦处于 UNLOCKED 状态,将发起 PassThru 事件并触发 Lock 操作,随后闸机状态将重新变为 LOCKED。Alarm 和 Refund 这两个操作不会导致状态的变化。

为确保这个演示应用尽量简单,其中并未定义具体操作。状态和事件可通过 Enumeration 实现:

static enum States {
  LOCKED,
  UNLOCKED
}
static enum Events {
  INSERTTOKEN,
  PASSTHRU
}

随后需要在 StateMachineConfigurer 接口中通过定义 Spring @Configuration 注解上下文(Annotation context)的方式配置状态和转换:

@Configuration
@EnableStateMachine
static class Config extends EnumStateMachineConfigurerAdapter {
  @Override
  public void configure(StateMachineStateConfigurer states)
          throws Exception {
             states
              .withStates()
               .initial(States.LOCKED)
               .states(EnumSet.allOf(States.class));
      }

  @Override
  public void configure(StateMachineTransitionConfigurer transitions)
          throws Exception {
             transitions
              .withExternal()
               .source(States.LOCKED)
               .target(States.UNLOCKED)
               .event(Events.InsertToken)
               .and()
              .withExternal()
               .source(States.UNLOCKED)
               .target(States.LOCKED)
               .event(Events.PassThru);
      }
  }

@EnableStateMachine 注解信号可以通知该上下文闸机可立刻构建完成并启动。

在上述配置中,初始状态 LOCKED 是通过 states.withStates().initial(States.LOCKED) 语句定义的。转换则是使用上述代码中所示的 source()、target(),以及 event() 方法定义的。这一系列方法可以用于在 FSM 中定义所有状态转换。更改状态的标准方法是 withExternal()。如果某个操作无需更改状态,例如上述示意图中的 Alarm 和 Refund 操作,则可使用 withInternal() 方法定义。

此外可通过定义 StateMachineListener 监控闸机 FSM 的过程:

static class StateMachineListener extends StateMachineListenerAdapter {
  @Override
  public void stateChanged(State from,State to) {
      System.out.println("State changed to: " + to.getId());
  }
}

最后可以创建一个 StateMachine 实例并定义一个 run() 方法实现监听器,启动闸机 FSM,并发送事件。

@Autowired
StateMachine stateMachine;
@Override
public void run(String... args) throws Exception {
  StateMachineListener listener = new StateMachineListener();
  stateMachine.addStateListener(listener);
  stateMachine.start();
  stateMachine.sendEvent(Events.InsertToken);
  stateMachine.sendEvent(Events.PassThru);
}

public static void main(String[] args) {
  SpringApplication.run(org.redlich.statemachine.DemoApplication.class,args);
}

整个项目已发布至Github。详细的参考指南可访问Spring Statemachine 网站

查看英文原文:Spring Releases Version 1.1 Statemachine Framework

Java语言 & 开发架构AI