通过实例学习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

相关文章

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

mysqld_multi在Linux服务器上运行多个MySQL实例

《mysqld_multi在Linux服务器上运行多个MySQL实例》在Linux系统上使用mysqld_multi来启动和管理多个MySQL实例是一种常见的做法,这种方式允许你在同一台机器上运行多个... 目录1. 安装mysql2. 配置文件示例配置文件3. 创建数据目录4. 启动和管理实例启动所有实例

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结

MySQL的索引失效的原因实例及解决方案

《MySQL的索引失效的原因实例及解决方案》这篇文章主要讨论了MySQL索引失效的常见原因及其解决方案,它涵盖了数据类型不匹配、隐式转换、函数或表达式、范围查询、LIKE查询、OR条件、全表扫描、索引... 目录1. 数据类型不匹配2. 隐式转换3. 函数或表达式4. 范围查询之后的列5. like 查询6

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类