基于Spring StateMachine的有限状态机应用研究
2018-11-20吴德许凡
吴德,许凡
(三江学院计算机科学与工程学院,南京210012)
0 引言
近年来,基于“互联网+”模式的软件系统变得越来越精致复杂[1],软件需求和软件架构的多元化,导致软件开发过程中建模难度增加[2],其重要因素之一就是系统状态随着复杂的交互过程而变得更加多样化。
在面向对象的编程中,如果出现大量的与类内部状态转换有关的逻辑时,传统的解决方式为在代码中增加大量的if…else或者switch等判断语句。然而,这样做一方面随着状态的增加代码可能会不受控制(比如使用浏览器的历史记录、手工输入链接以及模拟一次表单提交,等等),从而出现无法预期的状态转换错误,导致程序运行异常,给用户造成损失;另一方面,这种做法将对象状态的转换与业务逻辑进行了紧密耦合,随着规模的增大不利于系统的后期维护。
状态机模式是处理这些情况的有效方法,它能处理任何顺序的事件,并能提供有意义的响应——即使这些事件发生的顺序和预计的不同。
Spring StateMachine是Spring提供的一个有限状态机的框架。其主要功能是帮助开发者简化状态机的开发过程,让状态机结构更加层次化[3]。Spring StateMachine框架可将状态机模式较为轻松地加入程序之中,提高编程的一致性和规范性。
1 有限状态机
有限状态机(Finite State Machine,FSM),简称状态机,是一种表示有限状态以及在这些状态之间的转移和动作等行为的数学模型[4],广泛应用于计算机领域。状态机是一种图形化的同步建模语言,具有并发性、层次性、良好的优先级抢占机制和通信机制[5]。
状态机能采取某种操作来响应一个外部事件。具体采取的操作不仅取决于接收到的事件,还取决于各个事件的相对发生顺序。之所以能做到这一点,是因为机器能跟踪一个内部状态,它会在收到事件后进行状态更新。也就是说,为一个事件而采取的响应行动不仅取决于事件本身,还取决于其内部状态。因此,任何逻辑都可建模成一系列事件/状态组合。
驱动状态机的是触发器,这些触发器基于事件或定时器。可以通过发送事件,或者请求当前状态来与状态机进行交互。
状态机中的几个重要概念:
(1)状态:用于模拟事物在条件不变时情况相对稳定的抽象概念,是状态机的主要实体,状态的变化主要由事件驱动。
(2)事件:向状态机发送的实体,用来驱动状态机各种各样的变化。
(3)行为:象征着从“源状态”向“目标状态”的转换,伴随着事件的发送,行为会进行特定的响应,实现对应的功能。
(4)初始状态:状态机被创建时的特殊状态,总是伴随着状态机的初始化。
(5)结束状态:也被称为最终状态,标志着状态转换已经完成。
2 Spring StateMachine
Spring StateMachine是Spring提供给应用程序开发人员使用状态机模型的一款轻量级框架。该框架提供了一整套与状态机概念一一对应的工具类,用于模仿或者实现状态机中每个实体对应的功能或者组件。
Spring StateMachine旨在提供以下功能:
(1)提供易于使用的、扁平的状态机实例[6]。简化状态机构建的操作,使得开发人员更加容易地获取状态机对象。
(2)利用注解可以简化复杂的状态配置。降低代码的复杂度,增加代码的可读性,提高开发效率。
(3)提供事件、行为的操作和使用。事件的触发同时伴随行为的发生,可以方便设置行为的具体内容。
(4)程序运行安全的适配器。保证程序安全运行,不会出现预料外的状态改变。
Spring StateMachine配置流程如图1所示。
图1 Spring StateMachine配置流程图
使用者首先需要按照状态机模式的概念抽象出自己所需要的状态以及事件。并为其定义好对应的枚举类。例如:
根据状态和事件进行配置,然后创建状态机,获取状态机主要有通过状态机生成器和使用注解自动注入两种方式。每当事件发送时,状态机都会监听到,并且改变其对应的状态,同时伴随行为的发生。也可以自定义监听器以满足特定的需求。
3 应用案例
本案例在电商订单管理系统中加入Spring State Machine框架,严格控制订单状态走向。订单最主要的状态可以抽象为CREATED(已下单)、PICKED(已拣货)、DELIVERED(已出库)、SENT(已发货)、RE⁃CEIVED(已收货),根据具体场景还可能扩展为“已支付”、“已退货”等。状态迁移图如图2所示。
图2 状态转移图
系统采用Spring Boot框架进行搭建,使用Maven框架进行依赖管理,利用Spring MVC,实现传统的MVC(Model View Controller)模式,数据库持久层框架使用MyBatis,数据库使用MySQL。
利用Spring StateMachine框架创建状态机,将订单所有的状态抽象出来得到的状态枚举类为:
将所有管理事件抽象出来得到的枚举类为:
将状态和事件交由状态机对象进行管理,在MVC的Controller层以及Service层发送事件,状态机将触发事件所对应的行为,将订单状态持久化存入数据库中。总体框架如图3所示。
图3 系统技术架构图
状态机配置的具体步骤如下:
步骤1:定义状态机的状态和事件集合,将抽象好的状态和事件分别创建对应的枚举类。根据图2的状态转移图,对应的枚举类如下:
步骤2:设置为状态机的初始状态,并配置状态变化的流程。将“CREATED”设置为状态机的初始状态,并设置所有状态的枚举类。
步骤3:配置状态变化的流程,例如:将“CREAT⁃ED”设置为源状态,将“PICKED”设置为目标状态,并关联事件“PICK”,这样当状态机接收到状态为源状态“CREATED”的订单以及事件“PICK”时就会自动获取订单的目标状态“PICKED”,根据状态转移图以此类推进行配置。
步骤4:设置自定义的持久化状态机Handler以监听系统内部订单的状态转移,并设置伴随状态转移触发的行为。当事件被发送时,行为也会同时发生,在行为中对订单状态的改变进行持久化处理,例如:当“PICK”事件被监听到时,订单目标状态“PICKED”就会被持久化至数据库中。
4 结语
在应用中合理使用状态机设计模式可以增加程序的安全性,简化代码的编写,增加代码的可读性。Spring StateMachine将状态机模式以框架的形式引入到Web应用中,减轻了开发者的压力,扩展了状态机的功能,方便状态机的监控以及持久化扩展,为开发者提供了更多的选择。就Spring StateMachine而言,目前迭代的版本不多,并没有得到充分的验证,可能还存在一些未知的Bug,相信随着信息技术的持续快速发展,Spring StateMachine会迎来更大的发展空间。