当前位置: 首页 > news >正文

Spring状态机简单实现

一、什么是状态机

状态机,又称有限状态自动机,是表示有限个状态以及在这些状态之间的转移和动作等行为的计算模型。状态机的概念其实可以应用的各种领域,包括电子工程、语言学、哲学、生物学、数学和逻辑学等,例如日常生活中的电梯、风扇、门闸机等,都会涉及到多种状态,随着动作的执行会进行状态的转移,而在软件编程领域,采用状态机的思路同样可以简化我们的设计流程,会使代码的可读性和可维护性得到增加。

目前用的比较多的开源状态机如:Spring StateMachine、Squirrel StateMachine以及阿里开源一款轻量的Cola-StateMachine,本文主要介绍Spring的状态机的使用。

二、Spring状态机的核心概念

  • transition:转换是原状态和目标状态之间的关系,用于将状态机从一种状态转移到另一种状态
  • source:节点的当前状态
  • target:节点的目标状态
  • event:触发节点从当前状态到目标状态的动作,如从State A 到 State B
  • guard:也叫“门卫”,当事件请求触发时,可以定义校验规则,用于校验是否可以执行后续action
  • action:用于实现当前节点对应的业务逻辑(事件发生之后系统做出的反应)
  • withChoice:当执行一个动作,可能导致多种结果时,可以选择使用choice+guard来跳转
  • withInternal:我们支持三种不同类型的转换,external,internal和local。转换时通过信号触发的,该信号是发送到状态机的事件或计时器

三、Spring状态机使用示例

Spring StateMachine 是 Spring 官方提供的状态机实现。其核心组件如下:

  • StateMachine:状态机实例,可以触发事件、执行状态转换,并获取当前状态等信息;
  • StateMachineStateConfigurer:用于配置状态,定义状态机中的各种状态,并指定每个状态的行为和属性;
  • StateMachineTransitionConfigurer:用于配置状态之间的转换关系,定义转换的触发事件、源状态、目标状态,以及转换的条件和动作;
  • StateMachineConfigurationConfigurer:状态机系统配置,用于配置状态机的全局属性和行为,包括状态机的执行模式、并发策略、监听器等;
  • StateMachineListenerAdapter:事件监听器,用于简化状态机事件监听器(StateMachineEventListener)的实现

这里还是以抽奖奖励状态转换为例,奖励的状态转换图如下:

在这里插入图片描述

  1. 环境准备:
<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-starter</artifactId><version>2.5.0</version></dependency>
  1. 定义奖励状态以及事件的枚举类

public enum AwardState {INACTIVE, ACTIVE, PAUSE, FINISH
}public enum AwardEvent {AUTO_ACTIVATE, AUTO_FINISH, FINISH, PAUSE, RESUME
}
  1. 状态机配置类:
@Configuration
@EnableStateMachine
public class AwardStateMachineConfig extends EnumStateMachineConfigurerAdapter<AwardState, AwardEvent> {@Autowiredprivate AwardStateMachineListener awardStateMachineListener;@Overridepublic void configure(StateMachineStateConfigurer<AwardState, AwardEvent> states) throws Exception {states.withStates().initial(AwardState.INACTIVE).states(EnumSet.allOf(AwardState.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<AwardState, AwardEvent> transitions) throws Exception {transitions.withExternal().source(AwardState.INACTIVE).target(AwardState.ACTIVE).event(AwardEvent.AUTO_ACTIVATE).and().withExternal().source(AwardState.INACTIVE).target(AwardState.FINISH).event(AwardEvent.AUTO_FINISH).and().withExternal().source(AwardState.ACTIVE).target(AwardState.FINISH).event(AwardEvent.FINISH).and().withExternal().source(AwardState.ACTIVE).target(AwardState.PAUSE).event(AwardEvent.PAUSE).and().withExternal().source(AwardState.PAUSE).target(AwardState.ACTIVE).event(AwardEvent.RESUME).and().withExternal().source(AwardState.PAUSE).target(AwardState.FINISH).event(AwardEvent.FINISH);}@Overridepublic void configure(StateMachineConfigurationConfigurer<AwardState, AwardEvent> config) throws Exception {config.withConfiguration().autoStartup(true).listener(awardStateMachineListener);}
}
  1. 状态机监听器:
@Component
public class AwardStateMachineListener extends StateMachineListenerAdapter<AwardState, AwardEvent> {@Overridepublic void transition(Transition<AwardState, AwardEvent> transition) {System.out.println("状态转移 from " + transition.getSource().getId() + " to " + transition.getTarget().getId());}/*@Overridepublic void stateChanged(State<AwardState, AwardEvent> from, State<AwardState, AwardEvent> to) {System.out.println("状态改变 from " + from.getId() + " to " + to.getId());}*/
}
  1. 奖励服务类
@Service
public class AwardStateMachineService {@Resourceprivate StateMachine<AwardState, AwardEvent> stateMachine;public void autoActivate() {stateMachine.sendEvent(AwardEvent.AUTO_ACTIVATE);}public void autoFinish() {stateMachine.sendEvent(AwardEvent.AUTO_FINISH);}public void finish() {stateMachine.sendEvent(AwardEvent.FINISH);}public void pause() {stateMachine.sendEvent(AwardEvent.PAUSE);}public void resume() {stateMachine.sendEvent(AwardEvent.RESUME);}}
  1. 测试:
@SpringBootTest
class AwardStatemachineApplicationTests {@Autowiredprivate AwardStateMachineService awardStateMachineService;@Autowiredprivate StateMachine<AwardState, AwardEvent> stateMachine;@Testvoid awardStageTest() {// 发送事件自动激活抽奖awardStateMachineService.autoActivate();// 检查状态是否变为ACTIVEassert (stateMachine.getState().getId() == AwardState.ACTIVE);// 发送事件暂停抽奖awardStateMachineService.pause();// 检查状态是否变为PAUSEassert (stateMachine.getState().getId() == AwardState.PAUSE);// 发送事件恢复抽奖awardStateMachineService.resume();// 检查状态是否变为ACTIVEassert (stateMachine.getState().getId() == AwardState.ACTIVE);// 发送事件结束抽奖awardStateMachineService.finish();// 检查状态是否变为FINISHassert (stateMachine.getState().getId() == AwardState.FINISH);}}

测试执行结果:
在这里插入图片描述
可以看到 Spring 状态机很好的控制了奖励状态之间的流转。

总结:本文主要介绍了Spring状态机的一些基本概念,以及状态流转的使用方式,Spring状态机一些高级的用法,如状态的持久化、状态的并行(parallel,fork,join)、子状态机等,会在后面文章更新。

参考:
https://docs.spring.io/spring-statemachine/docs/2.0.2.RELEASE/reference/htmlsingle/#glossary

相关文章:

Spring状态机简单实现

一、什么是状态机 状态机&#xff0c;又称有限状态自动机&#xff0c;是表示有限个状态以及在这些状态之间的转移和动作等行为的计算模型。状态机的概念其实可以应用的各种领域&#xff0c;包括电子工程、语言学、哲学、生物学、数学和逻辑学等&#xff0c;例如日常生活中的电…...

WebServer -- 面试题(下)

&#x1f442; 夏风 - Gifty - 单曲 - 网易云音乐 目录 &#x1f33c;前言 &#x1f382;面试题(下) 4&#xff09;HTTP报文解析 为什么要用状态机 状态转移图画一下 https 协议为什么安全 https 的 ssl 连接过程 GET 和 POST 的区别 5&#xff09;数据库注册登录 登…...

企业微信如何接入第三方应用?

1.登录企业微信管理后台&#xff1a;https://work.weixin.qq.com/wework_admin​​​​​ 2.点击创建应用&#xff1b; ​​​​​​​ 3. 此时可以看到已经创建好的应用&#xff0c;并且生成应用的唯一id&#xff08;agentId&#xff09; 4. 第三方应用申请域名 (举例&…...

JAVA后端编码的主键字段存储为什么倾向于使用雪花算法

1.背景 最近有人问&#xff0c;什么是雪花算法&#xff0c;为什么使用雪花算法不使用数据库UUID&#xff0c;基于此&#xff0c;写一个说明。 2.简介 &#xff08;1&#xff09;雪花算法&#xff0c;英文名为snowflake&#xff0c;翻译过来就是是雪花&#xff0c;所以叫雪花…...

Rust 深度学习库 Burn

一、概述 Burn 它是一个新的综合动态深度学习框架&#xff0c;使用 Rust 构建的&#xff0c;以极高的灵活性、计算效率和可移植性作为其主要目标。 Rust Burn 是一个以灵活性、高性能和易用性为核心设计原则工具&#xff0c;主打就是灵活性 、高性能 及易用性。 二、Rust B…...

C语言-存储期2.0

静态存储期 在数据段中分配的变量&#xff0c;统统拥有静态存储期&#xff0c;因此也都被称为静态变量。这里静态的含义&#xff0c;指的是这些变量的不会因为程序的运行而发生临时性的分配和释放&#xff0c;它们的生命周期是恒定的&#xff0c;跟整个程序一致。 静态变量包含…...

计算机网络面经八股-HTTP请求报文和响应报文的格式?

请求报文格式&#xff1a; 请求行&#xff08;请求方法URI协议版本&#xff09;请求头部空行请求主体 请求行&#xff1a;GET /sample.jsp HTTP/1.1 表示使用 GET 方法请求 /sample.jsp 资源&#xff0c;并使用 HTTP/1.1 协议。请求头部&#xff1a;包含多个字段&#xff0c;…...

Ubuntu 18.04安装最新版Visual Studio Code(VS Code)报依赖库版本过低错误

Ubuntu 18.04安装最新版Visual Studio Code&#xff08;VS Code&#xff09;报依赖库版本过低错误 1. 问题描述2. 解决方案2.1 修复之前安装的错误2.2 安装VS Code 1.85.2 3. 原因分析 1. 问题描述 在Ubuntu 18.04系统上安装VS Code ≥ v1.86.2&#xff08;测试到v1.87.1&…...

Android NDK入门:在应用中加入C和C++的力量

目录 ​编辑 引 NDK的设计目的 与Java/Kotlin的结合 使用场景 开发流程 设置项目以支持NDK 编写本地代码 使用JNI连接本地代码和Java/Kotlin代码 编译和运行你的应用 附 引 自诩方向是android方向的移动端开发工程师&#xff0c;却从来没有真正仔细了解过NDK&#…...

2024年华为OD机试真题-田忌赛马-Java-OD统一考试(C卷)

题目描述: 给定两个只包含数字的数组a,b,调整数组 a 里面数字的顺序,使得尽可能多的 a[i] >b[i]。数组 a和 b 中的数字各不相同。 输出所有可以达到最优结果的 a 数组的数量 输入描述: 输入的第一行是数组 a 中的数字,其中只包含数字,每两个数字之间相隔一个空格,a…...

C++ 网络编程学习五

C网络编程学习五 网络结构的更新单例模式懒汉单例模式饿汉单例模式懒汉式指针智能指针设计单例类 服务器优雅退出asio的多线程模型IOServiceasio多线程IOThreadPoolepoll 和 iocp的一些知识点 网络结构的更新 asio网络层&#xff0c;会使用io_context进行数据封装&#xff0c;…...

案例分析篇05:数据库设计相关28个考点(9~16)(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…...

pip 和conda 更换镜像源介绍

1、前言 很多深度学习的项目免不了安装库文件、配置环境等等&#xff0c;如果利用官方提供的连接&#xff0c;网速很慢&#xff0c;而且很容易download掉。 所以配置好了虚拟环境&#xff0c;将pip换源属实重要 常见的国内镜像源有清华、中科大、阿里等等... 这里建议用中科…...

Git概述及安装步骤

一、Git简介 Git是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目。Git 易于学习&#xff0c;占地面积小&#xff0c;性能极快。它具有廉价的本地库&#xff0c;方便的暂存区域和多个工作流分支等特性。其性能优于Subversion、CV…...

北京保险服务中心携手镜舟科技,助推新能源车险市场规范化

2022 年&#xff0c;一辆新能源汽车在泥泞的小路上不慎拖底&#xff0c;动力电池底壳受损&#xff0c;电池电量低。车主向保险公司报案&#xff0c;希望能够得到赔偿。然而&#xff0c;在定损过程中&#xff0c;保司发现这辆车的电池故障并非由拖底事件引起&#xff0c;而是由于…...

给女朋友的浪漫微信消息推送超详细版

1. 下载代码 地址&#xff1a; 链接: https://pan.baidu.com/s/1lESgRoWn8bXyE0jsSVCHqQ?pwdimr6 提取码: imr6 根据 resources/db 下sql文件创建表 修改yml文件中数据库连接 2. 进入微信测试平台 地址&#xff1a;微信公众平台 扫码登录获取测试号信息 修改代…...

Android开发 Activity启动模式、ViewModel与LiveData,及Kotlin Coroutines

目录 Activity启动模式 onNewIntent解释 Activity启动模式的考虑时机 Service启动模式 ContentProvider的作用 Broadcast的注册方式 AsyncTask的作用 ViewModel LiveData Kotlin Coroutines 结合使用 Activity启动模式 Android中Activity的启动模式有四种&#xff0…...

MQL语言实现抽象工厂模式

文章目录 一、定义抽象产品接口二、定义抽象工厂接口三、定义具体产品四、定义具体工厂五、定义工厂客户端六、客户端调用工厂客户端七、抽象工厂模式的结构 一、定义抽象产品接口 //------------------------------------------------------------------ //| participants …...

UE4开个头-简易小汽车

跟着谌嘉诚学的小Demo&#xff0c;记录一下 主要涉及到小白人上下车和镜头切换操作 1、动态演示效果 2、静态展示图片 3、蓝图-上下车...

Java基础入门day04

day04 包 包可以用来区分相同的类名 将相同的类放在不同包下&#xff0c;可以进行存储 一个目录下没有办法存在两个同名的文件 包最终在文件系统中与文件目录结构是一一对应的 在不同包下可以存放相同类名的文件 包后期还可以实现项目中模块的精确划分&#xff0c;controller,…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...