前言
本文主要介绍一下状态机以及相关的一些概念。结合一个简单的订单状态流程,示例怎样在Springboot中集成Spring-statemachine。
有限状态机(Finite-state machine)
有限状态机(英语:finite-state machine,缩写:FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。应用FSM模型可以帮助对象生命周期的状态的顺序以及导致状态变化的事件进行管理。将状态和事件控制从不同的业务Service方法的if else中抽离出来。FSM的应用范围很广,对于有复杂状态流,扩展性要求比较高的场景都可以使用该模型。下面是状态机模型中的4个要素,即现态、条件、动作、次态。
现态:是指当前所处的状态。
条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
如下图示例:有限的状态集是“opend”以及“closed”。如果“现态”是“opend”,当“条件”为“Close”时,执行的“动作”是“close door”,次态则为“closed”。状态机逻辑执行完毕后“closed”则变成了“现态”。
有限状态机
所以FSM的执行逻辑可以理解为下图,即FSM的下一个状态和输出是由输入和当前状态决定的:
FSM的执行逻辑
集成Spring-statemachine框架到Springboot应用
对于使用Java语言的应用来说,可以选择的集成框架也比较多。如squirrel-foundation,spring-statemachine,stateless4j 。squirrel-foundation,stateless4j相对spring-statemachine更加轻量级。感兴趣的可以去看下这两个项目的源码。
Spring官网项目的QuickStart中没有对于持久化模型的举例。所以本文以一个持久化的流程——一个简单的示例订单流程进行举例。示例代码中,持久化框架使用了hibernate-jpa,请求的示范例子用了spring-web,spring-webmvc的Rest api。基于JDK8。Spring statemachine版本:1.2.7,SpringBoot 版本:1.5.3。
配置
gradle 配置的版本
dependencies {
compile ‘org.springframework.statemachine:spring-statemachine-core:1.2.7.RELEASE’
}
1
2
3
4
示例-订单的状态流程
如下图,本文示例一个简单的订单流程。
订单状态图
订单状态模型
状态枚举类OrderStatus:
public enum OrderStatus {
// 待支付,待发货,待收货,订单结束
WAIT_PAYMENT, WAIT_DELIVER, WAIT_RECEIVE, FINISH;
}
1
2
3
4
5
6
事件枚举类OrderStatusChangeEvent:
public enum OrderStatusChangeEvent {
// 支付,发货,确认收货
PAYED, DELIVERY, RECEIVED
}
1
2
3
4
5
6
订单Entity Order:
@Entity
@Table(name = “order_test”)
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@NotNull
@Column(name = "order_id")
private Integer orderId;
@NotNull
@Enumerated(EnumType.ORDINAL)
@Column(name = "status")
private OrderStatus status;
public Order() {
}
public Order(Integer orderId, OrderStatus status) {
this.orderId = orderId;
this.status = status;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public OrderStatus getStatus() {
return status;
}
public void setStatus(OrderStatus status) {
this.status = status;
}
@Override
public String toString() {
return "Order{" +
"orderId=" + orderId +
", status=" + status +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Repository类 OrderRepo :
public interface OrderRepo extends JpaRepository