spring StateMachine简易使用

发布时间 2023-06-01 17:00:41作者: 俄而123

Spring StateMachine是一个状态机框架,在Spring框架项目中,开发者可以通过简单的配置就能获得一个业务状态机,而不需要自己去管理状态机的定义、初始化等过程。今天这篇文章,我们通过一个案例学习下Spring StateMachine框架的用法。

 

pom依赖中添加

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
</parent>

<dependency>
            <groupId>org.springframework.statemachine</groupId>
            <artifactId>spring-statemachine-starter</artifactId>
            <version>2.3.1</version>
</dependency>

定义好状态与事件两种枚举

public enum States {
    UNPAID, //待支付
    WAITING_FOR_RECEIVE, //待收货
    DONE; //结束
}

public enum Events {
    PAY,//支付
    RECEIVE;//收货
}

创建状态机配置类

@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * configure(StateMachineStateConfigurer<States, Events> states)方法用来初始化当前状态机拥有哪些状态,
     * 其中initial(States.UNPAID)定义了初始状态为待支付UNPAID,
     * states(EnumSet.allOf(States.class))则指定了使用上一步中定义的所有状态作为该状态机的状态定义。
     * @param states
     * @throws Exception
     */
    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
        //初始状态为待支付
        states.withStates().initial(States.UNPAID).states(EnumSet.allOf(States.class));
    }

    /**
     * configure(StateMachineTransitionConfigurer<States, Events> transitions)方法用来初始化当前状态机有哪些状态迁移动作,
     * 其中命名中我们很容易理解每一个迁移动作,都有来源状态source,目标状态target以及触发事件event。
     * @param transitions  StateMachineTransitionConfigurer<States, Events>
     * @throws Exception
     */
    @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);
    }

//    //     * configure(StateMachineConfigurationConfigurer<States, Events> config)方法为当前的状态机指定了状态监听器,
////     * 其中listener()则是调用了下一个内容创建的监听器实例,
////     * 用来处理各个各个发生的状态迁移事件。
////     * @param config
////     * @throws Exception
//    @Override
//    public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
//        config
//                .withConfiguration()
//                .listener(listener());  // 指定状态机的处理监听器
//    }
//
//    //
////     * StateMachineListener<States, Events> listener()方法用来创建StateMachineListener状态监听器的实例,
////     * 在该实例中会定义具体的状态迁移处理逻辑,上面的实现中只是做了一些输出,
////     * 实际业务场景会有更复杂的逻辑,所以通常情况下,
////     * 我们可以将该实例的定义放到独立的类定义中,并用注入的方式加载进来。
////     * @return
//    @Bean
//    public StateMachineListener<States, Events> listener() {
//        return new StateMachineListenerAdapter<States, Events>() {
//
//            @Override
//            public void transition(Transition<States, Events> transition) {
//                if(transition.getTarget().getId() == States.UNPAID) {
//                    logger.info("订单创建,待支付");
//                    System.out.println("订单创建,待支付");
//                    return;
//                }
//                if(transition.getSource().getId() == States.UNPAID
//                        && transition.getTarget().getId() == States.WAITING_FOR_RECEIVE) {
//                    logger.info("用户完成支付,待收货");
//                    System.out.println("用户完成支付,待收货");
//                    return;
//                }
//
//                if(transition.getSource().getId() == States.WAITING_FOR_RECEIVE
//                        && transition.getTarget().getId() == States.DONE) {
//                    logger.info("用户已收货,订单完成");
//                    System.out.println("用户已收货,订单完成");
//                    return;
//                }
//            }
//
//        };
//    }
}

创建业务监听类型

@WithStateMachine
@Slf4j
public class BizListener {

    @OnTransition(target = "UNPAID")
    public void unpaid(){
        System.out.println("订单创建,待支付");
    }

    @OnTransition(target = "WAITING_FOR_RECEIVE")
    public void payEvent(){
        System.out.println("用户完成支付,待收货");
    }

    @OnTransition(target = "DONE")
    public void receiveEvent(){
        System.out.println("用户已收货,订单完成");
    }
}

创建应用启动类,模拟状态转换

@SpringBootApplication
public class Application implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Autowired
    private StateMachine<States, Events> stateMachine;

    @Override
    public void run(String... args) throws Exception {
        stateMachine.start();
        stateMachine.sendEvent(Events.PAY);
        stateMachine.sendEvent(Events.RECEIVE);
    }

}