通过实例学习SpringStateMachine之TURN STILE

2024-01-03 10:50

本文主要是介绍通过实例学习SpringStateMachine之TURN STILE,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景介绍

本系列通过学习SpringStateMachine中附带的10余个Sample来学习SpringStateMachine中的各个概念和用法。项目是使用的分支为2.2.0.RELEASE[1]。项目参考文档也是2.2.0.RELEASE[1]。

TURN STILE简介

turnstile是对体育场入口或地铁入口的旋转栅门构建的状态机。

状态机的两种状态:

  • LOCKED
  • UNLOCKED

状态机的两种事件

  • COIN
  • PUSH

触发相应事件后发生状态转换。
在这里插入图片描述

TURN STILE 依赖

项目在实现上述功能时,需要依赖springshell,官方给出的demo[4]使用了spring-shell1.2,本文将其改为spring-shell 2.0.0.RELEASE。

        <dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>2.2.0.RELEASE</version></dependency><dependency><groupId>org.springframework.shell</groupId><artifactId>spring-shell-starter</artifactId><version>2.0.0.RELEASE</version></dependency>

TURN STILE 实现

为了实现本例,我们需要描述状态及其转换。首先定义状态与事件枚举类型。

状态枚举类型:

public enum States {LOCKED, UNLOCKED
}

使状态发生变化的事件枚举类型:

public enum Events {COIN, PUSH
}

接着我们配置状态与转换。

package springboot.statemachine.example.turnstile.demo;import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;import java.util.EnumSet;@Configuration
@EnableStateMachine
public class StateMachineConfigextends EnumStateMachineConfigurerAdapter<States, Events> {@Overridepublic void configure(StateMachineStateConfigurer<States, Events> states)throws Exception {states.withStates().initial(States.LOCKED).states(EnumSet.allOf(States.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<States, Events> transitions)throws Exception {transitions.withExternal().source(States.LOCKED).target(States.UNLOCKED).event(Events.COIN).and().withExternal().source(States.UNLOCKED).target(States.LOCKED).event(Events.PUSH);}}

在配置状态与转换时用到如下的注解与类:

  • @Configuration
  • @EnableStateMachine
  • EnumStateMachineConfigurerAdapter

代码继承EnumStateMachineConfigurerAdapter类,并覆盖两个configure方法,在这两个方法中分别来配置转换与状态列表同时指定好初始状态。

随后在创建的类上增加@EnableStateMachine与@Configuration注解,通过这些创建状态机实例,系统随后会检测是否使用了adapter类,并在运行时根据这些配置修改状态机。

statemachine中有三种形式的转换(transition)external, internal, local。
这里我们使用了withExternal,返回一个ExternalTransitionConfigurer来完成转换的配置。target方法指定了目标状态,source指定了源状态,event指定了使状态发生变更的事件。

最后是命令实现。这里对StateMachineCommands官方demo[5]进行了小修改。最后通过stateMachine的sendEvent方法发送事件,使状态机状态发生变化。

import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import springboot.statemachine.example.AbstractStateMachineCommands;@ShellComponent
public class StateMachineCommands extends AbstractStateMachineCommands<States, Events> {@ShellMethod(key = "sm event", value = "Sends an event to a state machine")public String event(Events event) {getStateMachine().sendEvent(event);return "Event " + event + " send";}
}

此外将官方AbstractStateMachineCommands[6]中打印turn stile字符图形的部分去掉了。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.state.State;
import org.springframework.util.StringUtils;import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;public class AbstractStateMachineCommands<S, E>{@Autowiredprivate StateMachine<S, E> stateMachine;protected StateMachine<S, E> getStateMachine() {return stateMachine;}@ShellMethod(key = "sm state", value = "Prints current state")public String state() {State<S, E> state = stateMachine.getState();if (state != null) {return StringUtils.collectionToCommaDelimitedString(state.getIds());} else {return "No state";}}@ShellMethod(key = "sm start", value = "Start a state machine")public String start() {stateMachine.start();return "State machine started";}@ShellMethod(key = "sm stop", value = "Stop a state machine")public String stop() {stateMachine.stop();return "State machine stopped";}@ShellMethod(key = "sm variables", value = "Prints extended state variables")public String variables() {StringBuilder buf = new StringBuilder();Set<Entry<Object, Object>> entrySet = stateMachine.getExtendedState().getVariables().entrySet();Iterator<Entry<Object, Object>> iterator = entrySet.iterator();if (entrySet.size() > 0) {while (iterator.hasNext()) {Entry<Object, Object> e = iterator.next();buf.append(e.getKey() + "=" + e.getValue());if (iterator.hasNext()) {buf.append("\n");}}} else {buf.append("No variables");}return buf.toString();}}

验证

发送不同的命令触发事件,并查看状态机当前状态,发现状态正确发生变化。

State machine started
shell:>sm event COIN
Event COIN send
shell:>sm event PUSH
Event PUSH send
shell:>sm start
State machine started
shell:>sm state
LOCKED
shell:>sm event COIN
Event COIN send
shell:>sm state
UNLOCKED
shell:>sm event PUSH
Event PUSH send
shell:>sm state
LOCKED
shell:>sm event PUSH
Event PUSH send
shell:>sm state
LOCKED
shell:>sm state COIN
LOCKED
shell:>sm state
LOCKED
shell:>sm start
State machine started
shell:>sm state
LOCKED
shell:>sm stop

总结

通过turnstile这个例子学习了基础的概念及相关配置。通过

  • @Configuration,
  • @EnableStateMachine,
  • EnumStateMachineConfigurerAdapter

完成配置及创建单实例。实现触发事件使状态机当前状态发生变化,从源状态到目标状态变化。

参考

[1]2.2.0.RELEASE source,https://github.com/spring-projects/spring-statemachine/blob/2.2.0.RELEASE/
[2]2.2.0.RELEASE/reference,https://docs.spring.io/spring-statemachine/docs/2.2.0.RELEASE/reference
[3]turnstile,https://docs.spring.io/spring-statemachine/docs/2.2.0.RELEASE/reference/#statemachine-examples-turnstile
[4]turnstile demo,https://github.com/spring-projects/spring-statemachine/tree/2.2.0.RELEASE/spring-statemachine-samples/turnstile/src/main/java/demo/turnstile
[5]StateMachineCommands,https://github.com/spring-projects/spring-statemachine/blob/2.2.0.RELEASE/spring-statemachine-samples/turnstile/src/main/java/demo/turnstile/StateMachineCommands.java
[6]AbstractStateMachineCommands,https://github.com/spring-projects/spring-statemachine/blob/2.2.0.RELEASE/spring-statemachine-samples/src/main/java/demo/AbstractStateMachineCommands.java

这篇关于通过实例学习SpringStateMachine之TURN STILE的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/565456

相关文章

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析

《Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析》InstantiationAwareBeanPostProcessor是Spring... 目录一、什么是InstantiationAwareBeanPostProcessor?二、核心方法解

java String.join()方法实例详解

《javaString.join()方法实例详解》String.join()是Java提供的一个实用方法,用于将多个字符串按照指定的分隔符连接成一个字符串,这一方法是Java8中引入的,极大地简化了... 目录bVARxMJava String.join() 方法详解1. 方法定义2. 基本用法2.1 拼接

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Linux lvm实例之如何创建一个专用于MySQL数据存储的LVM卷组

《Linuxlvm实例之如何创建一个专用于MySQL数据存储的LVM卷组》:本文主要介绍使用Linux创建一个专用于MySQL数据存储的LVM卷组的实例,具有很好的参考价值,希望对大家有所帮助,... 目录在Centos 7上创建卷China编程组并配置mysql数据目录1. 检查现有磁盘2. 创建物理卷3. 创

Java List排序实例代码详解

《JavaList排序实例代码详解》:本文主要介绍JavaList排序的相关资料,Java排序方法包括自然排序、自定义排序、Lambda简化及多条件排序,实现灵活且代码简洁,文中通过代码介绍的... 目录一、自然排序二、自定义排序规则三、使用 Lambda 表达式简化 Comparator四、多条件排序五、

Java实例化对象的​7种方式详解

《Java实例化对象的​7种方式详解》在Java中,实例化对象的方式有多种,具体取决于场景需求和设计模式,本文整理了7种常用的方法,文中的示例代码讲解详细,有需要的可以了解下... 目录1. ​new 关键字(直接构造)​2. ​反射(Reflection)​​3. ​克隆(Clone)​​4. ​反序列化

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

Python解决雅努斯问题实例方案详解

《Python解决雅努斯问题实例方案详解》:本文主要介绍Python解决雅努斯问题实例方案,雅努斯问题是指AI生成的3D对象在不同视角下出现不一致性的问题,即从不同角度看物体时,物体的形状会出现不... 目录一、雅努斯简介二、雅努斯问题三、示例代码四、解决方案五、完整解决方案一、雅努斯简介雅努斯(Janu