Spring State Machine
Spring State Machine
创建 Spring Boot 项目并添加必要依赖
在 pom.xml
中引入 spring-statemachine-core
<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>3.2.1</version>
</dependency>
定义状态机状态与事件
使用枚举明确业务状态和触发事件:
public enum States {UNPAID, // 待支付WAITING_FOR_RECEIVE, // 待收货DONE // 结束
}
public enum Events {PAY, // 支付RECEIVE // 收货
}
配置状态机逻辑
通过 @EnableStateMachine
注解激活状态机,配置初始状态和转移规则:
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;import java.util.EnumSet;@Configuration
@EnableStateMachine
@Slf4j
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {@Overridepublic void configure(StateMachineStateConfigurer<States, Events> states)throws Exception {states.withStates().initial(States.UNPAID).states(EnumSet.allOf(States.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<States, Events> transitions)throws Exception {transitions.withExternal().source(States.UNPAID).target(States.WAITING_FOR_RECEIVE).event(Events.PAY).and().withExternal().source(States.WAITING_FOR_RECEIVE).target(States.DONE).event(Events.RECEIVE);}
}
这段代码定义了一个 Spring State Machine 的配置类,用于设置状态机的状态和转移逻辑。它继承了 EnumStateMachineConfigurerAdapter<States, Events>,这是一个便利类,让我们使用枚举轻松定义状态机。下面是对这段代码的详细解释:
用到的类和接口
EnumStateMachineConfigurerAdapter:
这个类是 Spring State Machine 提供的一个适配器类,简化了使用枚举来配置状态机的过程。通过继承这个类,可以利用其提供的默认方法来方便地设置状态和转移。
代码解析
1.configure 方法 (定义状态)
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {states.withStates().initial(States.UNPAID).states(EnumSet.allOf(States.class));
}
withStates():
开始配置状态。
initial(States.UNPAID):
定义状态机的初始状态为 UNPAID。状态机在启动后默认处于这个状态。
states(EnumSet.allOf(States.class)):
定义状态机所管理的所有可能状态。此处使用 EnumSet.allOf() 来获取 States 枚举中定义的所有状态,这意味着状态机将支持 UNPAID, WAITING_FOR_RECEIVE, 和 DONE 三种状态。
2.configure 方法 (定义状态转移)
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {transitions.withExternal().source(States.UNPAID).target(States.WAITING_FOR_RECEIVE).event(Events.PAY).and().withExternal().source(States.WAITING_FOR_RECEIVE).target(States.DONE).event(Events.RECEIVE);
}
- withExternal():
-
- 定义一个外部状态转换。这是状态机中从一个状态显式转换到另一个状态的基本方式。
source(States.UNPAID).target(States.WAITING_FOR_RECEIVE).event(Events.PAY):
- 定义一个外部状态转换。这是状态机中从一个状态显式转换到另一个状态的基本方式。
定义当 PAY 事件发生时,状态从 UNPAID 转换到 WAITING_FOR_RECEIVE。这代表支付操作成功后的状态变化。
and():
连接多个状态转换配置。这里用于配置一个新的状态转换。
source(States.WAITING_FOR_RECEIVE).target(States.DONE).event(Events.RECEIVE):
定义当 RECEIVE 事件发生时,状态从 WAITING_FOR_RECEIVE 转换到 DONE。这表示收货操作成功后的状态变化,订单流程完成。
通过 CommandLineRunner
自动触发状态变更:
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {@Autowiredprivate StateMachine<States, Events> stateMachine;public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@Overridepublic void run(String... args) {stateMachine.start();stateMachine.sendEvent(Events.PAY);stateMachine.sendEvent(Events.RECEIVE);}
}
监听状态变更事件
通过 @OnTransition
注解实现状态变更时的业务逻辑:
import lombok.extern.slf4j.Slf4j;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;
@WithStateMachine
@Slf4j
public class EventConfig {@OnTransition(target = "UNPAID")public void create() {log.info("订单创建,待支付");}@OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE")public void pay() {log.info("用户完成支付,待收货");}@OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE")public void receive() {log.info("用户已收货,订单完成");}
}