demo: www.cnblogs.com/xd502djj/p/…
- maven中引入依赖
<!--状态机-->
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-starter</artifactId>
<version>2.5.0</version>
</dependency>
<!-- Spring State Machine Redis持久化 -->
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-redis</artifactId>
<version>1.2.9.RELEASE</version>
</dependency>
- 定义状态和事件
public enum TestState {
UNPAID, // 待支付
WAITING_FOR_RECEIVE, // 待收货
DONE // 结束
}
public enum TestEvents {
PAY, // 支付
RECEIVE // 收货
}
配置 StatemachineConfigurer绑定状态与事件
**
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import java.util.EnumSet;
@Configuration
@EnableStateMachine(name = "StateMachineConfig")
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<TestState, TestEvents> {
private Logger logger = LoggerFactory.getLogger(getClass());
//定义初始状态
@Override
public void configure(StateMachineStateConfigurer<TestState, TestEvents> states)
throws Exception {
states.withStates()
.initial(TestState.UNPAID)
.states(EnumSet.allOf(TestState.class));
}
//状态转换过程 触发什么事件就转换为什么状态
@Override
public void configure(StateMachineTransitionConfigurer<TestState, TestEvents> transitions)
throws Exception {
transitions
.withExternal()
.source(TestState.UNPAID).target(TestState.WAITING_FOR_RECEIVE)
.event(TestEvents.PAY)
.and()
.withExternal()
.source(TestState.WAITING_FOR_RECEIVE).target(TestState.DONE)
.event(TestEvents.RECEIVE);
}
}
将事件监听触发与配置类进行配置:(EventListener) @OnTransition注解配置。它省去了原来事件监听器方法中各种if的判断,从而使代码显得更为简洁,具有更好的可读性。
@Component
@WithStateMachine(name = "StateMachineConfig")
public class EventListener {
private Logger logger = LoggerFactory.getLogger(getClass());
@OnTransition(target = "UNPAID")
public boolean create(Message<Order> order) { // 创建订单逻辑
logger.info("订单创建,待支付");
return true;
}
@OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE")
public boolean pay(Message<Order> order) {
// 支付逻辑 从redis根据order 来进行处理
logger.info("用户完成支付,待收货");
return true;
}
@OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE")
public boolean receive(Message<Order> order) { //从redis中根据传入的order 来查询当前订单 并业务处理
logger.info("用户已收货,订单完成");
return true;
}
}
持久化状态
//config配置类中
@Resource
private StateMachinePersist orderRedisStateMachineContextPersist;
/**
* 持久化到redis中,在分布式系统中使用
*
* @return
*/
@Bean(name = "stateMachineRedisPersister")
public RedisStateMachinePersister<E, S> getRedisPersister() {
return new RedisStateMachinePersister<>(orderRedisStateMachineContextPersist);
}
@Component
@RequiredArgsConstructor
public class OrderRedisStateMachineContextPersist implements StateMachinePersist<TestState, TestEvents, String> {
private final RedisStateMachineContextRepository<TestState, TestEvents> redisStateMachineContextRepository;
@Override
public void write(StateMachineContext<TestState, TestEvents> context, String contextObj) throws Exception {
redisStateMachineContextRepository.save(context, contextObj);
}
@Override
public StateMachineContext<TestState, TestEvents> read(String contextObj) throws Exception {
StateMachineContext<TestState, TestEvents> context = redisStateMachineContextRepository.getContext(contextObj);
return context;
}
}
测试
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
public DemoApplication(StateMachine<TestState, TestEvents> stateMachine) {
this.stateMachine = stateMachine;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
private final StateMachine<TestState, TestEvents> stateMachine;
private final StateMachinePersister<TestState, TestEvents, String> stateMachineRedisPersister;
@Override
public void run(String... args) throws Exception {
Order order=new Order("测试",0);
// 使用 MessageBuilder 创建消息并设置负载和头信息
Message message = MessageBuilder
.withPayload(TestEvents.PAY)
.setHeader("order", order)
.build();
//尝试恢复状态机状态
stateMachineRedisPersister.restore(orderStateMachine, getContextObj(order));
// 发送消息给状态机
stateMachine.start();
stateMachine.sendEvent(message);
//执行成功则持久化状态机状态
stateMachineRedisPersister.persist(orderStateMachine, getContextObj(order));
}
}