BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Spring发布1.1版Statemachine框架

| 作者 Michael Redlich 关注 11 他的粉丝 ,译者 大愚若智 关注 9 他的粉丝 发布于 2016年6月12日. 估计阅读时间: 7 分钟 | Google、Facebook、Pinterest、阿里、腾讯 等顶尖技术团队的上百个可供参考的架构实例!

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

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT