本文主要是介绍Spring StateMachine 使用小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《SpringStateMachine使用小结》SpringStateMachine是一个用于管理复杂状态流转的框架,本文就来介绍一下SpringStateMachine使用,具有一定的参考价值,...
一、基本概念
状态机(State Machine) 是一种行为模型,定义了一组状态、状态之间的转换(事件驱动)、以及在状态转换时触发的动作。Spring StateMachine 提供了强大的框架支持,帮助开发者管理和驱动复杂的状态流。
核心要素:
- State(状态):对象所处的不同阶段。
- Event(事件):触发状态转换的动作。
- Transition(转换):状态之间的转换过程。
- Action(动作):状态转换时执行的业务逻辑。
二、核心组件
- StateMachine:状态机核心接口,负责状态管理和事件驱动。
- StateMachineConfigurerAdapter:状态机配置适配器,用户自定义状态、事件、转换逻辑。
- StateMachineFactory:状态机工厂,创建状态机实例。
- Actions:状态转换时执行的具体业务逻辑。
- Guards:转换前的条件判断。
三、引入依赖
<!-- Maven依赖 -->
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>4.0.0</version>
</dependency>四、定义状态和事件
以订单流程为例:
public enum OrderStates {
CREATED, PAID, SHIPPED, COMPLETED, CANCELLED
}
public enum OrderEvents {
PAY, SHIP, COMPLETE, CANCEL
}五、配置状态机
通过继承 StateMachineConfigurerAdapter 进行配置:
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStates, OrderEvents> {
@Override
public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
states
.withStates()
.initial(OrderStates.CREATED)
.states(EnumSet.allOf(OrderStates.class));
}
@Override
public voihttp://www.chinasem.cnd configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
transitions
.withExternal().source(OrderStates.CREATED).target(OrderStates.PAID).event(OrderEvents.PAY)
.and()
.withExternal().source(OrderStates.PAID).target(OrderStates.SHIPPED).event(OrderEvents.SHIP)
.and()
.withExternal().source(OrderStates.SHIPPED).target(OrderStates.COMPLETED).event(OrderEvents.COMPLETE)
.and()
.withExternal().source(OrderStates.CREATED).target(OrderStates.CANCELLED).event(OrderEvents.CANCEL)
.and()
.withExternal().source(OrderStates.PAID).target(OrderStates.CANCELLED).event(OrderEvents.CANCEL);
}
}六、使用状态机
注入并驱动状态机:
@Autowired
private StateMachine<OrderStates, OrderEvents> stateMachine;
public void processOrder() {
stateMachine.start();
stateMachine.sendEvent(OrderEvents.PAY);
stateMachine.sendEvent(OrderEvents.SHIP);
stateMachine.sendEvent(OrderEvents.COMPLETE);
}七、添加动作和条件
1. 动作(Action)
@Bean
public Action<OrderStates, OrderEvents> payAction() {
return context -> {
System.out.println("订单已支付,执行相关业务逻辑");
};
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
transitions
.withExternal()
.source(OrderStates.CREATED).target(OrderStates.PAID).event(OrderEvents.PAY)
.action(payAction())
// 其他转换...
}2. 条件(Guard)
@Bean
public Guard<OrderStates, OrderEvents> payGuard() {
return context -> {
// 只有金额大于0才能支付
Integer amount = (Integer) context.getMessageHeader("amount");
return amount != null && amount > 0;
};
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStates, OrjavascriptderEvents> transitions) throws Exception {
transitions
.withExternal()
.source(OrderStates.CREATED).target(OrderStates.PAID).event(OrderEvents.PAY)
.guard(payGuard())
// 其他转换...
}八、持久化状态机(可选)
Spring StateMachine 支持状态持久化,可用 Redis、JPA 等存储状态,适合分布式场景。
九、最佳实践
- 合理拆分状态与事件,避免过于复杂的状态流。
- 利用动作和条件,实现业务与状态解耦。
- 持久化状态机,保证高可用和一致性。
- 结合 @WithStateMachine 注解,方便事件监听与回调。
十一、进阶用法
1. 状态监听器(StateMachineListener)
可以通过监听器获取状态变化、事件处理、异常等回调:
@Component
public class OrderStateMachineListener extends StateMachineListenerAdapter<OrderStates, OrderEvents> {
@Override
public void stateChanged(State<OrderStates, OrderEvents> from, State<OrderStates, OrderEvents> to) {
System.out.println("状态从 " + (from == null ? "none" : from.getId()) + " 变为 " + to.getId());
}
@Override
public void eventNotAccepted(Message<OrderEvents> event) {
System.out.println("事件未被接受: " + event.getPayload());
}
}注册监听器:
@Autowired
private StateMachine<OrderStates, OrderEvents> stateMachine;
@Autowired
private OrderStateMachineListener listener;
@PostConstruct
www.chinasem.cnpublic void addListener() {
stateMachine.addStateListener(listener);
}2. 状态机嵌套(子状态机)
Spring StateMachine 支持嵌套状态(Hierarchical States),适合复杂流程。
@Override
public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
states
.withStates()
.initial(OrderStates.CREATED)
.state(OrderStates.PAID)
.and()
.withStates()
.parent(OrderStates.PAID)
.initial(OrderStates.PAID_SUB1)
.state(OrderStates.PAID_SUB2);
}3. 状态机持久化
以 Redis 为例,持久化状态机:
@Bean
public StateMachinePersister<OrderStates, OrderEvents, String> persister(
RedisStateMachinePersister<OrderStates, nyYAJBcOrderEvents> persister) {
return persister;
}
// 保存状态
persister.persist(stateMachine, "orderId-123");
// 恢复状态
persister.restore(stateMachine, "orderId-123");4. 多实例状态机
对于每个业务对象(如订单),建议为每个对象创建独立的状态机实例:
@Autowired
private StateMachineFactory<OrderStates, OrderEvents> factory;
public void handleOrder(String orderId) {
StateMachine<OrderStates, OrderEvents> sm = factory.getStateMachine(orderId);
sm.start();
sm.sendEvent(OrderEvents.PAY);
}5. 结合Spring事件机制
可以通过监听 StateMachineEvent,实现解耦的业务响应。
十二、常见问题
状态未切换?
- 检查事件是否正确发送,状态机是否
start(),Guard 是否返回 true。
- 检查事件是否正确发送,状态机是否
状态机线程安全?
- 默认是线程不安全的,业务并发场景下请为每个业务对象创建独立状态机实例。
如何调试?
- 打开日志:
logging.level.org.springframework.statemachine=DEBUG,方便追踪状态流转。
- 打开日志:
如何与数据库结合?
- 利用持久化接口,将状态机状态存入数据库,保证分布式一致性。
十三、实战建议
- 不要把所有业务逻辑都塞到 Action,只做与状态相关的处理,复杂逻辑建议外部调用。
- 事件驱动:外部只需发事件,状态机自动处理后续流转。
- 解耦:状态机只关注流程和状态,业务逻辑在合适的位置实现。
- 测试:多写单元测试,覆盖各个状态和异常流转。
十四、完整示例
1. 配置类
@Configuration
@EnableStateMachineFactory
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStates, OrderEvents> {
// 状态、事件、转移配置同上
}2. 业务调用
@Service
public class OrderService {
@Autowired
private StateMachineFactory<OrderStates, OrderEvents> factory;
public void payOrder(String orderId) {
StateMachine<OrderStates, OrderEvents> sm = factory.getStateMachine(orderId);
sm.start();
sm.sendEvent(OrderEvents.PAY);
// 可持久化 sm
}
}3. 持久化(可选)
@Autowired private StateMachinePersister<OrderStates, OrderEvents, String> persister; public void saveState(StateMachine&pythonlt;OrderStates, OrderEvents> sm, String orderId) throws Exception { persister.persist(sm, orderId); } public void restoreState(StateMachine<OrderStates, OrderEvents> sm, String orderId) throws Exception { persister.restore(sm, orderId); }
到此这篇关于Spring StateMachine 使用小结的文章就介绍到这了,更多相关Spring StateMachine 使用内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Spring StateMachine 使用小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!