一、状态机
有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何相应来自外界的各种时间。在电商场景(订单、物流、售后)、社交(IM消息投递)、分布式集群管理(分布式计算平台任务编排)等场景都有大规模的使用。
状态机的要素
- 状态机可归纳为 4个要素,现态、条件、动作、次态。 现态 和 条件 和因, 动作 和次态 是果。
- 现态: 指当前所处的状态
- 条件: 又称 事件 ,当一个条件被满足,将会触发一个动作或者执行一个状态的迁移
- 动作: 条件满足后执行的动作,动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原有状态,动作不是必须的,当条件满足时,也可以不执行任何动作,直接迁移到新的状态
- 次态:条件满足后要迁往的新状态
状态机的动作类型
- 进入动作:在进入状态时进行
- 退出动作:在退出状态时进行
- 输入动作:依赖于当前状态 和 输入条件进行
- 转移动作:在进行特定转移时进行
二、spring statemachine
spring 提供的一个状态机开发引用框架。
需要引入的依赖:
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
- 创建相关状态 和 事件枚举类
/**
* 订单状态
*/
public enum OrderStatus {
// 待支付,待发货,待收货,订单结束
WAIT_PAYMENT, WAIT_DELIVER, WAIT_RECEIVE, FINISH;
public enum OrderStatusChangeEvent {
//待支付
PAYED,
DELIVER,
RECEIVERD;
}
- 初始化状态机
**/
@Configuration
@EnableStateMachine(name = "orderStateMachine")
public class OrderStatusMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderStatusChangeEvent> {
/**
* @Description: 配置状态
* @Param: [states]
* @return: void
* @Author: Administrator
* @Date: 2021/10/16
*/
@Override
public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception {
states
.withStates()
.initial(OrderStatus.WAIT_PAYMENT)
.states(EnumSet.allOf(OrderStatus.class));
}
/**
* @Description: 配置状态转换事件关系
* @Param: [transitions]
* @return: void
* @Author: Administrator
* @Date: 2021/10/16
*/
@Override
public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {
transitions
.withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED)
.and()
.withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVER)
.and()
.withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderStatusChangeEvent.RECEIVERD);
}
@Bean
public StateMachinePersist<OrderStatus,OrderStatusChangeEvent, Order> persist(){
return (StateMachinePersist<OrderStatus, OrderStatusChangeEvent, Order>) new DefaultStateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order>(new StateMachinePersist<OrderStatus, OrderStatusChangeEvent, Order>() {
@Override
public void write(StateMachineContext<OrderStatus, OrderStatusChangeEvent> context, Order order) throws Exception {
//此处并没有进行持久化操作
}
@Override
public StateMachineContext<OrderStatus, OrderStatusChangeEvent> read(Order order) throws Exception {
//此处直接获取order中的状态,其实并没有进行持久化读取操作
return null;
}
});
}
- 添加状态监听器 使用 @WithStateMachine(name = “orderStateMachine”)
@Component("orderStateListener")
@WithStateMachine(name = "orderStateMachine")
public class OrderStateListenerImpl{
@OnTransition(source = "WAIT_PAYMENT", target = "WAIT_DELIVER")
public boolean payTransition(Message<OrderStatusChangeEvent> message) {
Order order = (Order) message.getHeaders().get("order");
order.setStatus(OrderStatus.WAIT_DELIVER);
System.out.println("支付 headers=" + message.getHeaders().toString());
return true;
}
@OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")
public boolean deliverTransition(Message<OrderStatusChangeEvent> message) {
Order order = (Order) message.getHeaders().get("order");
order.setStatus(OrderStatus.WAIT_RECEIVE);
System.out.println("发货 headers=" + message.getHeaders().toString());
return true;
}
- 在 service 中使用 重点看下 sendEvent 这个方法
@Service("orderService")
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;
@Autowired
private StateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister;
private int id = 1;
private Map<Integer, Order> orders = new HashMap<>();
@Override
public Order creat() {
Order order = new Order();
order.setStatus(OrderStatus.WAIT_PAYMENT);
order.setId(id++);
orders.put(order.getId(), order);
return order;
/**
* 发送订单状态转换事件
*
* @param message
* @param order
* @return
*/
private synchronized boolean sendEvent(Message<OrderStatusChangeEvent> message, Order order) {
boolean result = false;
try {
orderStateMachine.start();
//尝试恢复状态机状态
persister.restore(orderStateMachine, order);
//添加延迟用于线程安全测试
Thread.sleep(1000);
result = orderStateMachine.sendEvent(message);
//持久化状态机状态
persister.persist(orderStateMachine, order);
} catch (Exception e) {
e.printStackTrace();
} finally {
orderStateMachine.stop();
}
return result;
}
- 测试
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderServiceImplTest {
@Autowired
private OrderService orderService;
@Test
public void testMultThread(){
orderService.creat();
orderService.creat();
orderService.pay(1);
new Thread(()->{
orderService.deliver(1);
orderService.receive(1);
}).start();
orderService.pay(2);
orderService.deliver(2);
orderService.receive(2);
System.out.println(orderService.getOrders());