为什么要使用状态机?

如果你写过很复杂的流程系统,流程系统中涉及多步操作,流程达到不同的状态需要有不同的处理,同时状态间的转换也是有特定逻辑的。如果不使用状态机,那么你的代码我估计会有大量的if判断语句,你得判断某个操作指令过来了,当前这个状态是否能执行该指令。当程序需要异常终止,你需要在本不该对数据库进行操作的状态对数据库进行操作,进而导致到处都在操作数据库,一旦数据库出现数据异常,很难确定时哪里出现了问题。给修改bug带来了极大的困难。如果你有上面的困惑,那么我建议你修改代码模式,如果你的代码中存在大量的if elseif,你可以用反射,也可以用策略模式或者状态模式。如果你的系统中很明显就是一个状态流传的逻辑,那么我强烈建议你使用有限状态机重构自己的代码。有限状态机可以解决上面的问题。

什么是状态机?

从我的实际经验来讲,有限状态机可以看作是有向有环图。有向,因为状态一般是以一个状态到另一个状态;有环,因为流程很有可能出现失败然后重新定位到前面某个状态节点。如下所示:

为什么说有限状态机能解决去掉大量if判断的问题?

在有限自动机中,状态的转换被预先设定好。以上图为例,按照流程化的编写代码,原本T1状态是只能转移到T2状态的,如果此时来了一个Command要求当前状态转为S2状态,传统的写法只能是加判断条件,判断该指令是否合法,满足我业务流程,不满足就抛弃。这样就使得代码中会嵌入大量的状态-指令契合的条件判断语句。如果使用有限状态机,预先定义好状态之间的转化流程,当一个非法命令来到某个状态的执行部分,当前状态并没有为该命令定义处理方法,那么该命令自然就被舍弃掉了。在流程比较复杂的系统中,这样的优势更为明显。

有限状态机的实现原理是什么呢?

可以利用栈这种数据结构手写一个有限状态机。通过把状态的入栈和出栈操作定义为状态的转化过程,栈顶状态为当前自动机状态流程的状态,通过压栈和出栈的方式实现有限自动机的流程控制。不过,手写的有限状态机要上生产线还是比较麻烦,例如如何解决状态持久化问题等等。

我使用的是springboot,有现成的框架供我使用吗?
答案是肯定的。springboot为spring使用开发人员提供了StateMachine这个有限状态自动机,官方文档传送门

接下来让我详细为大家介绍一下如何简单上手StateMachine(详细使用参照官方文档)

引入maven依赖
<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-starter</artifactId><version>2.2.0.RELEASE</version>
</dependency>
定义状态和事件的枚举类型
public enum Events {EVENT1, EVENT2
}public enum States {SI, STATE1, STATE2
}
自定义配置文件
@Configuration
@EnableStateMachine
@Slf4j
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {@Beanpublic StateMachineListener<States,Events> listener() {return new StateMachineListenerAdapter<States,Events>(){@Overridepublic void stateChanged(State<States,Events> from,State<States,Events> to){log.info("State change to {}",to.getId());}};}@Overridepublic void configure(StateMachineConfigurationConfigurer<States,Events> config) throws Exception {config.withConfiguration().autoStartup(true).listener(listener());}@Overridepublic void configure(StateMachineStateConfigurer<States,Events> states) throws Exception {states.withStates().initial(States.SI).states(EnumSet.allOf(States.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<States,Events> transitions) throws Exception {transitions.withExternal().source(States.SI).target(States.STATE1).event(Events.EVENT1).action(action()).and().withExternal().source(States.STATE1).target(States.STATE2).event(Events.EVENT2).action(action());}@Beanpublic Action<States,Events> action(){return new Action<States, Events>() {@Overridepublic void execute(StateContext<States, Events> stateContext) {log.info("from {} to {}",stateContext.getSource().getId(),stateContext.getTarget().getId());}};}
}
修改Application主类,实现CommandLineRunner接口
@EnableAutoConfiguration
@Configuration
@ComponentScan({"com.chaojilaji.workorderservice"})
public class WorkorderserviceApplication implements CommandLineRunner {@Autowiredprivate StateMachine<States, Events> stateMachine;public static void main(String[] args) {SpringApplication.run(WorkorderserviceApplication.class, args);}@Overridepublic void run(String... args) throws Exception {stateMachine.sendEvent(Events.EVENT1);stateMachine.sendEvent(Events.EVENT2);}
}
运行代码,可以看见如下输出:

官方文档关于这些配置的因果有详细的描述,再次给出官方文档地址:
https://docs.spring.io/spring-statemachine/docs/2.2.x-SNAPSHOT/reference/

springboot 有限状态机入门指南相关推荐

  1. SpringBoot快速入门——helloworld(来自官网)

    SpringBoot官网快速入门指南 首先使用SpringBoot官网快速创建可以创建一个小项目 创建完以后点击下面的Generate可以下载一个zip文件,将文件解压到指定位置. 打开idea,新版 ...

  2. 入门指南_Spring Boot2: 快速入门指南

    Spring Boot2: 快速入门指南 简述 对于之前的Spring框架的使用,各种配置文件XML.properties一旦出错之后错误难寻 这也是为什么Spring Boot被推上主流的原因,现在 ...

  3. macOS 入门指南

    本文首发于我的个人博客:『不羁阁』 文章链接:传送门 前言 这篇文章写给刚开始使用 Mac 的小白. 如果你刚刚买了一台 Mac 电脑,却发现用起来不是很顺手:或者你工作.生活使用的是 Windows ...

  4. html5怎么兼容js 插件,Modernizr.js入门指南(HTML5CSS3浏览器兼容插件)

    HTML5 和 CSS3 的快速发展,给我们带来了极大的便利,比如从此再也不用花费大量的时间只是为了设计一个圆角的效果. 但是!我们不能像控制机器一样来控制所有的人都一夜之间升级到现代浏览器,因为那些 ...

  5. 基于Groovy的Spock单元测试框架入门指南

    文章目录 1. Spock Primer 基本概念 1.1 对比Junit 1.2 Imports 1.3 Specification测试类 1.4 Fields 属性 1.5 Fixture Met ...

  6. 入门指南目录页 -PaddlePaddle 飞桨 入门指南 FAQ合集-深度学习问题

    入门指南目录页 -PaddlePaddle 飞桨 入门指南 FAQ合集 GT_Zhang关注 0.1012019.08.01 18:43:34字数 1,874阅读 795 Hi,欢迎各位来自Paddl ...

  7. Maven入门指南⑦:Maven的生命周期和插件

    Maven入门指南⑦:Maven的生命周期和插件 一个完整的项目构建过程通常包括清理.编译.测试.打包.集成测试.验证.部署等步骤,Maven从中抽取了一套完善的.易扩展的生命周期.Maven的生命周 ...

  8. UE4风格化场景设计入门指南 Stylized Station – The Environment Artist’s Survival Kit

    持续时间13h 1920X1080 .ts 包含项目文件 大小解压后:4.9G 语言:英语+中文字幕(人工校对) 标题:风格化的车站--环境艺术家的生存工具包 信息: 环境艺术很难. 尤其是作为初学者 ...

  9. 游戏风格化角色创建入门指南视频教程

    游戏风格化角色创建入门指南视频教程 时间 33小时 包括项目文件 1920X1080 MP4 语言:英语+中文字幕(根据原英文字幕机译更准确)+原英文字幕 游戏中的风格化角色创建入门指南  百度一下 ...

最新文章

  1. wxWidgets:在对话框之间共享信息
  2. 构建高性能ASP.NET站点 网站优化需要考虑的方面
  3. android开发技术探索,《android开发艺术探索》读书笔记(十三)--综合技术(示例代码)...
  4. python scrapy框架 简书_python scrapy 实战简书网站
  5. 2021首届“科创中国”开源创新榜评选来了,你优秀的开源内容应该上榜,立即参加
  6. memcpy的用法与strcpy的区别及纯c语言实现
  7. 明解c语言答案第八章,明解C语言 入门篇 第八章答案
  8. SegNet算法详解
  9. 星际争霸2 AI开发(持续更新)
  10. a标签 vue 动态点击_a链接的href怎么用vue动态生成
  11. NVIDIA CUDA初级教程(P2-P3)CPU体系架构概述、并行程序设计概述
  12. Excel 中如何去掉数值中出现的 E +,网上的方法都试过了不管用,改变单元格格式等都无效
  13. photoshop导出png发生未知错误的解决方案,ps导出发生未知错误怎么解决
  14. c++中的 单引号和双引号
  15. VS2022配置FreeImage - Windows
  16. Arduino 单总线驱动音频播放模块DY-SV 5W示例(MP3)
  17. openlayers3.20.1发布说明
  18. XSS攻击的简单实现
  19. 只有不断的学习才能收获成长
  20. 解决canvas生成base64图片不清晰的问题

热门文章

  1. 遥感数据获取方式总结
  2. AtCoder Regular Contest 085 F NRE 线段树优化dp
  3. 微信小程序|Springboot+Vue+Node开发实现医疗预约挂号系统
  4. linux替换命令 vim,Vim 替换命令(substitute)
  5. 25个基于浏览器的HTML在线编辑器集合
  6. mac 关于/usr 和/opt
  7. java transient作用_Java中transient关键字的作用
  8. AttributeError: ‘PipelinedRDD‘ object has no attribute ‘toDF‘
  9. React结合虚拟列表VirtualList的动态获取列表项高度问题
  10. DataBank收购了Stream的达拉斯数据中心