003 电商平台核心链路_StateMachine(一)

有限状态机(Finite-state machine)

        有限状态机(英语:finite-state machine,缩写:FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。应用FSM模型可以帮助对象生命周期的状态的顺序以及导致状态变化的事件进行管理。将状态和事件控制从不同的业务Service方法的if else中抽离出来。FSM的应用范围很广,对于有复杂状态流,扩展性要求比较高的场景都可以使用该模型。下面是状态机模型中的4个要素,即现态、条件、动作、次态。

  • 现态:是指当前所处的状态。
  • 条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
  • 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
  • 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

如下图示例:有限的状态集是“opend”以及“closed”。如果“现态”是“opend”,当“条件”为“Close”时,执行的“动作”是“close door”,次态则为“closed”。状态机逻辑执行完毕后“closed”则变成了“现态”。

有限状态机

所以FSM的执行逻辑可以理解为下图,即FSM的下一个状态和输出是由输入和当前状态决定的:

FSM的执行逻辑

集成Spring-statemachine框架到Springboot应用(订单示例)

基于JDK8。Spring statemachine版本:2.0.0,SpringBoot 版本:2.0.3。

step1 配置依赖pom.xml

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
			
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>javax.servlet-api</artifactId>
		    <!-- <version>${servlet-api.version}</version> -->
		    <scope>provided</scope>	
		</dependency> 
		
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>${fastjson.version}</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.statemachine</groupId>
			<artifactId>spring-statemachine-core</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>
		<!-- uml to code -->
		<dependency>
			<groupId>org.springframework.statemachine</groupId>
			<artifactId>spring-statemachine-uml</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>	

 step2 状态枚举与事件枚举

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

step3 初始化订单的状态集合以及状态转移事件

在启动springboot时,需要注入状态机的状态,事件的配置。主要涉及到以下两个类:

StateMachineStateConfigurer < S, E> 配置状态集合以及初始状态,泛型参数S代表状态,E代表事件。
StateMachineTransitionConfigurer 配置状态流的转移,可以定义状态转换接受的事件。

public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {

    private Logger LOGGER = LoggerFactory.getLogger(getClass());

    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states.withStates().initial(States.UNPAID).states(EnumSet.allOf(States.class));
    }
    
    @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);
    }
        //守护
    @Bean	
    public Guard<States, Events> guard() {
        return new Guard<States, Events>() {
            public boolean evaluate(StateContext<States, Events> context) {
                return true;
            }
        };
    
    
}

step4 状态转移的监听器

        状态转移过程中,可以通过监听器(Listener)来处理一些持久化或者业务监控等任务。在需要持久化的场景中,可以在状态机模式中的监听器中添加持久化的处理。

@WithStateMachine
public class EventListener {
	
	private Logger LOGGER = LoggerFactory.getLogger(getClass());
	
    @OnTransition(target = "UNPAID")  
    public void create() {  
    	//此处可以执行具体业务逻辑处理
    	LOGGER.info("--------------------订单创建,待支付-----------------------");  
    }  
    
    @OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE")  
    public void pay() {  
    	//此处可以执行具体业务逻辑处理
    	LOGGER.info("--------------------用户完成支付,待收货--------------------");  
    }  
    
    @OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE")  
    public void receive() {  
    	//此处可以执行具体业务逻辑处理
    	LOGGER.info("--------------------用户已收货,订单完成----------------------");  
    }  

}


step5 测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

	@Test
	public void contextLoads() {
	}

	@Autowired
	private StateMachine<States, Events> stateMachine;
		
	@Test
	public void test() throws Exception {
		stateMachine.start();
        stateMachine.sendEvent(Events.PAY);  
        stateMachine.sendEvent(Events.RECEIVE);  
	}

}

1.只运行启动

@Test
	public void test() throws Exception {
		stateMachine.start();    //springboot启动时开启  待支付
        //stateMachine.sendEvent(Events.PAY);   //支付操作   待收货
        //stateMachine.sendEvent(Events.RECEIVE);  //收货操作   结束
	}

2.运行启动与支付操作

@Test
	public void test() throws Exception {
		stateMachine.start();    //springboot启动时开启  待支付
        stateMachine.sendEvent(Events.PAY);   //支付操作   待收货
        //stateMachine.sendEvent(Events.RECEIVE);  //收货操作   结束
	}

3.全部执行

@Test
	public void test() throws Exception {
		stateMachine.start();    //springboot启动时开启  待支付
        stateMachine.sendEvent(Events.PAY);   //支付操作   待收货
        stateMachine.sendEvent(Events.RECEIVE);  //收货操作   结束
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值