FSM——squirrel状态机使用

article/2025/9/11 1:05:18

FSM——squirrel状态机使用

1 FSM介绍

1.1 概念

FSM(finite state machine):有限状态机

  • 是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
  • 核心内容:有限个状态、通过外部操作引起状态的转移。
  • 用来对状态的流转进行解耦,使代码逻辑更加清楚和更加容易维护

1.2 组成和分类

  • 组成
  1. 现态:当前所处状态
  2. 条件(事件):当一个条件被满足,可能会触发一个动作,或执行一次状态的迁移。
  3. 动作:条件满足后执行的动作行为。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原有状态。动作不是必须的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
  4. 次态:条件满足后要迁往的新状态。"次态"是相对于"现态"而言的,"次态"一旦被激活,就转变为新的"现态"了。

总结:

所有的状态转换都可以概括为:
F(S, E) -> (A,S'):即如果当前状态为S,接收到一个事件E,则执行动作A,同时状态转换为下个状态S’

  • 分类
  • F(S) -> (A, S’) 型状态机:下一状态只由当前状态决定
  • F(S, E) -> (A, S’) 型状态机:下一状态不但与当前状态有关,还与当前输入值有关

2 使用

2.1 squirrel状态机框架

就像松鼠一样,小巧,灵活,智能,警觉和可爱的动物,squirrel基础旨在为企业使用提供轻量级,高度灵活和可扩展,可诊断,易于使用和类型安全的Java状态机实现。
squirrel文档:https://www.yangguo.info/2015/02/01/squirrel/

代码中使用:

<!--FSM 状态机-->
<dependency><groupId>org.squirrelframework</groupId><artifactId>squirrel-foundation</artifactId><version>0.3.8</version>
</dependency>

2.1.1 普通实现

①事件枚举类
public enum Event {/*** 审批通过*/APPROVE_PASS,/*** 审批拒绝*/APPROVE_REFUSED,/*** 复核通过*/RECHECK_PASS,/*** 复核不通过*/RECHECK_REFUSED;
}
②状态枚举类
public enum State {/*** 待审核*/APPROVE,/*** 拒绝*/REFUSED,/*** 同意*/PASS;
}
③上下文参数
@Getter
@Setter
@AllArgsConstructor
public class Context {private String param;
}
④自定义状态机(继承抽象类)
public class StateMachine extends AbstractStateMachine<StateMachine, State, Event, Context> {private void approvePassAction(State from, State to, Event event, Context context) {System.out.println(MessageFormat.format("审批人{0}审批了价格,审批结果为通过", context.getParam()));//TODO 将审批状态更新为已审核通过}private void approveRefusedAction(State from, State to, Event event, Context context) {System.out.println(MessageFormat.format("审批人{0}审批了价格,审批结果为拒绝", context.getParam()));//TODO 将审批状态更新为审核拒绝}private void recheckPassAction(State from, State to, Event event, Context context) {System.out.println(MessageFormat.format("审批人{0}对未审核通过的价格进行复核,审批结果为通过", context.getParam()));//TODO 将审批状态更新为审核通过}private void recheckRefusedAction(State from, State to, Event event, Context context) {System.out.println(MessageFormat.format("审批人{0}对未审核通过的价格进行复核,审批结果为不通过", context.getParam()));//TODO 将审批状态更新为审核不通过}
}

⑤测试状态机

一般是通过controller请求发起状态机调用,此处为了简单就直接在main方法中调用发起

public class Test {public static void main(String[] args) {StateMachineBuilder<StateMachine, State, Event, Context> builder =StateMachineBuilderFactory.create(StateMachine.class, State.class, Event.class, Context.class);/*** 状态转移表*///F(APPROVE,APPROVE_PASS)->(PASS,approvePassAction)builder.externalTransition().from(APPROVE).to(PASS).on(APPROVE_PASS).callMethod("approvePassAction");//F(APPROVE,APPROVE_REFUSED)->(REFUSED,ApproveRefusedAction)builder.externalTransition().from(APPROVE).to(REFUSED).on(APPROVE_REFUSED).callMethod("approveRefusedAction");//F(REFUSED,RECHECK_PASS)->(PASS,RecheckPassAction)复核 - 通过builder.externalTransition().from(REFUSED).to(PASS).on(RECHECK_PASS).callMethod("recheckPassAction");//F(REFUSED,RECHECK_REFUSED)->(REFUSED,RecheckRefusedAction)builder.externalTransition().from(REFUSED).to(REFUSED).on(RECHECK_REFUSED).callMethod("recheckRefusedAction");StateMachine machine = builder.newStateMachine(APPROVE);Context ziyi = new Context("ziyi");Context ka = new Context("ka");machine.start();//ziyi审批拒绝machine.fire(APPROVE_REFUSED,ziyi);ka复核成功//machine.fire(RECHECK_PASS,ka);}}

手动builder添加状态转移:
待审核 - 审核同意 - 复核通过

运行结果:
在这里插入图片描述

2.1.2 注解实现

可以直接通过@Transitions注解定义多个状态转变,指定从from状态到那to状态,然后on在哪个事件,最后callMethod(调用)哪个方法

@Transitions({@Transit(from = "APPROVE", to = "REFUSED", on = "APPROVE_REFUSED", callMethod = "approveRefusedAction"),
})
public class StateMachine extends AbstractStateMachine<StateMachine, State, Event, Context> {...
}

其他示例:

/*** 定义 触发事件、状态变化时,调用的方法* @States 定义状态列表,里面可以包含多个状态* @State定义每个状态,name状态名称,entryStateInit进入状态时调用的方法,exitCallMethod 离开状态是调用的方法,initialState 为true时,为默认状态。* */
@States({@State(name = "INIT", entryCallMethod = "entryStateInit", exitCallMethod = "exitStateInit", initialState = true),@State(name = "WAIT_PAY", entryCallMethod = "entryStateWaitPay", exitCallMethod = "exitStateWaitPay"),@State(name = "WAIT_SEND", entryCallMethod = "entryStateWaitSend", exitCallMethod = "exitStateWaitSend"),@State(name = "PART_SEND", entryCallMethod = "entryStatePartSend", exitCallMethod = "exitStatePartSend"),@State(name = "WAIT_RECEIVE", entryCallMethod = "entryStateWaitReceive", exitCallMethod = "exitStateWaitReceive"),@State(name = "COMPLETE", entryCallMethod = "entryStateComplete", exitCallMethod = "exitStateComplete")
})
@Transitions({@Transit(from = "INIT", to = "WAIT_PAY", on = "SUBMIT_ORDER", callMethod = "submitOrder"),@Transit(from = "WAIT_PAY", to = "WAIT_SEND", on = "PAY", callMethod = "pay"),@Transit(from = "WAIT_SEND", to = "PART_SEND", on = "PART_SEND", callMethod = "partSend"),@Transit(from = "PART_SEND", to = "WAIT_RECEIVE", on = "SEND", callMethod = "send"),@Transit(from = "WAIT_RECEIVE", to = "COMPLETE", on = "COMPLETE", callMethod = "complete")
})
// @StateMachineParameters用来声明状态机泛型参数类型,向AbstractStateMachine传递参数
@StateMachineParameters(stateType = OrderState.class, eventType = OrderEvent.class, contextType = OrderContext.class)
@Slf4j
public class SubmitOrderStateMachine extends AbstractStateMachine<UntypedStateMachine, Object, Object, Object> implements UntypedStateMachine {.......
}

2.1.5 状态机引擎

有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。在电商场景(订单、物流、售后)、社交(IM消息投递)、分布式集群管理(分布式计算平台任务编排)等场景都有大规模的使用。

有限状态机的使用场景很丰富,主要有以下三种常用框架:

  • squirrel-foundation(503stars)
  • spring-statemachine(305stars)
  • stateless4j(293stars)
    这三款finite state machine是github上stars top3的java状态机引擎框架

2.1.4 工作流与状态机区别

都是流程的管理,工作流引擎和状态机到底区别在哪里。

  1. 工作流引擎中,在完成之前的操作时,就会切换到下一个步骤,而状态需要一个外部事件才能让分支到下一个活动。【状态机是事件驱动的,工作流引擎不是】
  2. 当业务规则可能在时间上发生变化时,应当选择工作流引擎。因为如果选择状态机,在我们添加新状态时,需要保证不破坏其他流程。
- 工作

参考:
https://blog.csdn.net/footless_bird/article/details/115797710
https://blog.csdn.net/sunyufeng22/article/details/117986507


http://chatgpt.dhexx.cn/article/Gir3XHTH.shtml

相关文章

Squirrel SQL客户端使用图解

一、Squirrel简介 Squirrel是一个连接数据库的客户端工具&#xff0c;一般支持JDBC的数据库都可以用它来简介&#xff0c;如连接MySQL。 二、安装准备 下载jar包&#xff1a;squirrel-sql-3.7.1-standard.jar 三、安装 ①进入squirrel-sql-3.7.1-standard.jar文件所在的目录…

完成GitHub上squirrel 的运行(数据库的模糊测试)

文章目录 一、squirrel的介绍squirrel链接建议下载Ubuntu 18.04编译安装clang/llvm&#xff08;建议9.0以上&#xff09;将squirrel的文件下载到Ubuntu上下载docker&#xff08;建议按照dockerfile步骤直接在外部搭建环境&#xff09;Dockerfile创建镜像按照dockfile搭建时时有…

连接HiveServer2的图形化工具SQuirrel和Dbeaver

文章目录 SQuirrel SQL Client简介视频演示安装SQuirrel SQL Client启动hdfs和hiveserver2配置SQuirrel SQL Client使用SQuirrel SQL Client访问hive使用Cloudera提供的hive连接驱动进行连接Dbeaver的安装及使用 本文介绍的工具可以通过下面链接下载&#xff1a; 链接&#xff…

squirrel校园二手交易平台

##squirrel校园二手交易平台 &#xff08;适合寻找SSM项目练手的你。&#xff09; 问题汇总&#xff1a; &#xff08;朋友毕设用到了这个二手平台&#xff0c;他自己把后台优化了&#xff0c;我又帮忙实现了一部分功能&#xff0c;只能做到这里了。有兴趣的&#xff0c;自行优…

squirrel sql 使用

前置 安装jdk&#xff08;1.8版本即可&#xff09; 1、官网下载squirrel sql client jar https://sourceforge.net/projects/squirrel-sql/ 2 运行java -jar squirrel-sql-3.6-standard.jar安装 jar包 注意3.0的版本要JDK1.6以上 这里可以改安装目录 这里可以选择插件&#…

[squirrel使用]--Windows安装详解

squirrel在windows下的安装文档 一&#xff0e;下载安装 从网址http://www.squirrelsql.org/下载相应版本的squirrel的安装jar包&#xff0c;比如下载squirrel-sql-3.7-standard.jar双击安装&#xff0c;出现如下安装界面&#xff0c;下一步开始安装 二&#xff0e;配置连接p…

Squirrel状态机-从原理探究到最佳实践

作者&#xff1a;京东物流 郑朋辉 1 简介 Squirrel状态机是一种用来进行对象行为建模的工具&#xff0c;主要描述对象在它的生命周期内所经历的状态&#xff0c;以及如何响应来自外界的各种事件。比如订单的创建、已支付、发货、收获、取消等等状态、状态之间的控制、触发事件…

squirrel(松鼠)状态机的介绍及使用

squirrel&#xff08;松鼠&#xff09;状态机 依赖 <dependency><groupId>org.squirrelframework</groupId><artifactId>squirrel-foundation</artifactId><version>0.3.8</version> </dependency>状态机描述 参考&#xf…

将图片转换为base64编码

1、base64编码简介 Base64是一种可逆的编码方式&#xff0c;简单来讲就是一种将64个Ascii字符来表示成二进制数据的方法。主要用于将不可打印的字符转换成可打印字符&#xff0c;或者简单的说将二进制数据编码成Ascii字符。Base64是网络上最常用的传输8bit字节数据的编码方式之…

前端理解base64

一、背景&#xff1a;ascii码 字符>二进制 计算机中所有数据的存储都是以二进制模式&#xff0c;比如想要存储abcd需将其转化为二进制&#xff0c;具体用哪些二进制来表示哪个符号*&#xff0c;有一个统一的编码规则&#xff0c;这就是ascii。 ASCII 码使用指定的7 位或8…

Web 图片Base64编码

转载自: 【前端攻略】&#xff1a;玩转图片Base64编码 引言   图片处理在前端工作中可谓占据了很重要的一壁江山。而图片的 base64 编码可能相对一些人而言比较陌生&#xff0c;本文不是从纯技术的角度去讨论图片的 base64 编码。标题略大&#xff0c;不过只是希望通过一些…

base64编码解码器【C++】

在线编码解码工具https://base64.us/所有结果可以使用上述网站检验。 什么是base64编码&#xff1f; base64编码是一种编码方式 用64 1 个字符表示字符 本质是将三位8比特字符扩增为四位8比特字符&#xff0c;但是这么说开始可能很闷逼。 给个图&#xff0c;这个编码是以3字…

前端图片在线转换Base64 图片编码Base64

首先讲一下什么是图片Base64编码&#xff1a; 简单来说&#xff0c;图片的base64编码就是可以将一副图片数据编码成一串字符串&#xff0c;使用该字符串代替图像地址。 为什么要用Base64&#xff1f; 我们知道&#xff0c;我们所看到的网页上的每一个图片&#xff0c;都是需…

理解图片base64编码

什么是编码解码 编码&#xff1a;利用特定的算法&#xff0c;对原始内容进行处理&#xff0c;生成运算后的内容&#xff0c;形成另一种数据的表现形式&#xff0c;可以根据算法&#xff0c;再还原回来&#xff0c;这种操作称之为编码。 解码&#xff1a;利用编码使用的算法的…

【HTML5】------- 图片Base64编码详解

引言   图片处理在前端工作中可谓占据了很重要的一壁江山。而图片的 base64 编码可能相对一些人而言比较陌生&#xff0c;本文不是从纯技术的角度去讨论图片的 base64 编码。标题略大&#xff0c;不过只是希望通过一些浅显的论述&#xff0c;让你知道什么是图片的 base64 编码…

记录:Base64编码步骤详解

文章目录 具体转换步骤实例演示&#xff1a;AbC实例演示二&#xff1a;字节数不足三个例&#xff1a;A例&#xff1a;8H ASCII编码表Base64编码表 具体转换步骤 第一步&#xff0c;将待转换的字符串每三个字节分为一组&#xff0c;每个字节占8bit&#xff0c;那么共有24个二进…

对图片进行base64 编码

原文地址&#xff1a;https://www.cnblogs.com/coco1s/p/4375774.html 引言 图片处理在前端工作中可谓占据了很重要的一壁江山。而图片的 base64 编码可能相对一些人而言比较陌生&#xff0c;本文不是从纯技术的角度去讨论图片的 base64 编码。标题略大&#xff0c;不过只是希…

php将图片转成base64编码,利用PHP将图片转换成base64编码的实现方法

利用PHP将图片转换成base64编码的实现方法 先来说一下为什么我们要对图片base64编码 base64是当前网络上最为常见的传输8Bit字节代码的编码方式其中之一。base64主要不是加密,它主要的用途是把某些二进制数转成普通字符用于网络传输。由于这些二进制字符在传输协议中属于控制字…

Hex编码与Base64编码

Hex编码与Base64编码 什么是明文什么是编码Hex编码Hex编码实现细节自定义Hex编码 Base64编码Base64编码实现细节自定义Base64编码 什么是明文 介绍什么是编码之前&#xff0c;首先了解下什么是明文&#xff0c;表示其本身意思的&#xff0c;他就是明文 比如你看到"E6988…

Base64编码linux服务器与网页编码不一致问题

一、起因 在一次环境变量注入的时候&#xff0c;使用Base64将密码编码传入&#xff0c;但是传入后无法登录&#xff0c;但是登录到容器内&#xff0c;使用明文却能登录 二、排错过程 出现这种问题&#xff0c;首先判断密文是否有误&#xff0c;但是在linux服务器内反复base64&…