首页 > 其他分享 >spring StateMachine简易使用

spring StateMachine简易使用

时间:2023-06-01 17:00:33浏览次数:43  
标签:状态机 StateMachine UNPAID RECEIVE spring void States 简易 public

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);
    }

}

 

标签:状态机,StateMachine,UNPAID,RECEIVE,spring,void,States,简易,public
From: https://www.cnblogs.com/eer123/p/17449575.html

相关文章

  • SpringBoot项目中实现读写分离
    背景介绍面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极......
  • 前后端分离的架构,前端使用Vue2.6.10,后端使用SpringBoot2.0.0的ERP实现
    技术架构技术框架:SpringBoot2.0.0+Mybatis1.3.2+SLF4J1.7+Vue2.6.10+Ant-Design-Vue1.5.2+Mysql5.7+Redis运行环境:jdk8+IntelliJIDEA+maven+宝塔面板本地部署:1.小皮面板创建一个数据库,导入jsh_erp.sql文件至数据库中,该文件在后端程序的docs文件夹下。2.使用......
  • Spring AOP 使用介绍,从前世到今生
    SpringAOP使用介绍,从前世到今生 https://www.javadoop.com/post/spring-aop-intro @Before("execution(*com.javadoop.dao.*.*(..))")Tips:上面匹配中,通常"."代表一个包名,".."代表包及其子包,方法参数任意匹配使用两个点".."。......
  • springcloud的configserver配置中心默认中文乱码的解决方法
    springcloud的configserver配置中心默认中文乱码的解决方法先表明我的springcloud版本(2021.0.6)和对应springboot版本(2.6.14)ReleaseTrainVersion: 2021.0.6SupportedBootVersion: 2.6.14https://docs.spring.io/spring-cloud/docs/2021.0.6/reference/html/ 问题描述:当从......
  • Springboot实现ENC加密jasypt-spring-boot-starter
    依赖:<!--配置文件加密--><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.4</version>&l......
  • Spring Boot 3.1中如何整合Spring Security和Keycloak
    在今年2月14日的时候,Keycloak团队宣布他们正在弃用大多数Keycloak适配器。其中包括SpringSecurity和SpringBoot的适配器,这意味着今后Keycloak团队将不再提供针对SpringSecurity和SpringBoot的集成方案。但是,如此强大的Keycloak,还要用怎么办呢?本文就来聊聊,在最新的SpringBo......
  • 【博学谷学习记录】超强总结,用心分享 | Django简易开发指南
    【博学谷IT技术支持】一、介绍Django是python语言写的开源web开发框架,遵循MVC设计。Django的主要目的是简便、快捷的开发数据库驱动的网站。但是Django有一个专有名词:MVTM:Model,负责数据处理,内嵌了ORM框架V:View,接收HttpRequest,业务处理,返回HttpResponseT:Template,负责......
  • 记一次spring 事务失效的解决
    我们项目既有使用springJPA也有使用springJdbcTemplate,此次事务失效的原因是,项目之前配置的是springjpa的专门的事务管理器。第一次尝试解决:添加springJdbcTemplate的事务管理器,并添加相应的注解驱动。不生效!!!第二次尝试解决:问了下chartgpt,如果在Spring配置文件中启用了多......
  • 使用SpringMVC搭建第一个项目
    概述使用SpringMVC搭建第一个项目,入门教程,分享给大家。详细一、概述1、什么是SpringMVC?SpringMVC属于SpringFrameWork的后续产品,已经融合在SpringWebFlow里面。Spring框架提供了构建Web应用程序的全功能MVC模块。使用Spring可插入的MVC架构,从而在使用Sp......
  • 一天吃透Spring面试八股文
    内容摘自我的学习网站:topjavaer.cnSpring是一个轻量级的开源开发框架,主要用于管理Java应用程序中的组件和对象,并提供各种服务,如事务管理、安全控制、面向切面编程和远程访问等。它是一个综合性框架,可应用于所有类型的Java应用程序。SpringMVC是Spring框架中的一个模块,用......