spring Spring StateMachine狀態機

http://blog.didispace.com/spring-statemachine/


使用spring StateMachine 狀態機步驟:

  • 定義狀態和事件枚舉
  • 爲狀態機定義使用的所有狀態以及初始狀態
  • 爲狀態機定義狀態的遷移動作
  • 爲狀態機指定監聽處理器

定義狀態枚舉:

package com.example.statemachine;

public enum States {
	
	UNPAY,                //待付款
	WAITING_FOR_RECEIVE,  //待收貨
	DONE                  //結束
}


定義事件枚舉

package com.example.statemachine;

public enum Events{
	PAY,      //付款
	RECEIVE   //收貨
}

狀態機配置

package com.example.statemachine;


import java.util.EnumSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.transition.Transition;

@Configuration
@EnableStateMachine//啓用Spring StateMachine狀態機功能
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events>{

	private Logger log=LoggerFactory.getLogger(getClass());
	
	@Override//初始化當前狀態機擁有哪些狀態
	public void configure(StateMachineStateConfigurer<States, Events> states)
			throws Exception {
		// TODO Auto-generated method stub
		states.withStates()
		      .initial(States.UNPAY)//定義了初始狀態
		      .states(EnumSet.allOf(States.class));//指定了使用上一步中定義的所有狀態作爲該狀態機的狀態定義。
	}
	
	@Override//初始化當前狀態機有哪些狀態遷移動作
	public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
			throws Exception {
		// TODO Auto-generated method stub
		transitions
		     .withExternal()//每一個遷移動作,都有來源狀態source,目標狀態target以及觸發事件event
		           .source(States.UNPAY).target(States.WAITING_FOR_RECEIVE)
		           .event(Events.PAY)
		           .and()
		     .withExternal()
		           .source(States.WAITING_FOR_RECEIVE).target(States.DONE)
		           .event(Events.RECEIVE);
		           
		           
	}
	
    @Override
    public void configure(StateMachineConfigurationConfigurer<States, Events> config)
    		throws Exception {
    	// TODO Auto-generated method stub
    	//爲當前的狀態機指定了狀態監聽器,也可以以註解的方式配置監聽器
//    	config.withConfiguration().listener(listener());
    }
	
	@Bean//狀態機監聽器,可以單獨寫一個類,然後注入
	public StateMachineListener<States, Events> listener(){
		StateMachineListenerAdapter<States, Events> listener=
				new StateMachineListenerAdapter<States, Events>(){
			
			@Override
			public void transition(Transition<States, Events> transition) {
				// TODO Auto-generated method stub
				States state=transition.getTarget().getId();
				if(state==States.UNPAY){
					log.info("訂單創建,待付款");
					return;
				}
				
				States resourceState=transition.getSource().getId();
				if(resourceState==States.UNPAY&&state==States.WAITING_FOR_RECEIVE){
					log.info("用戶完成支付,待收貨");
					return;
				}
				
				if(resourceState==States.WAITING_FOR_RECEIVE&&state==States.DONE){
					log.info("用戶已收貨,訂單完成");
					return;
				}
			}     		
		};
		return listener;
	}
}

測試狀態機

package com.example.other;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.statemachine.StateMachine;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.example.DemoApplication;
import com.example.statemachine.Events;
import com.example.statemachine.States;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=DemoApplication.class)
@WebAppConfiguration
public class StateMachineTest {
	
	@Autowired
	private StateMachine<States, Events> stateMachine;
	
	@org.junit.Test
	public void Test(){
		stateMachine.start();
		stateMachine.sendEvent(Events.PAY);
		stateMachine.sendEvent(Events.RECEIVE);
	}

}

也可以以註解的方式配置listener

package com.example.statemachine;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;

@WithStateMachine//以註解的方式配置監聽器
public class EventConfig {
	
	private Logger log=LoggerFactory.getLogger(getClass());
	
	@OnTransition(source="UNPAY")
	public void create(){
		log.info("訂單創建,待付款");
	}

	@OnTransition(source="UNPAY",target="WAITING_FOR_RECEIVE")
	public void pay(){
		 log.info("用戶完成支付,待收貨");
	}
	
	@OnTransition(source="WAITING_FOR_RECEIVE",target="DONE")
	public void receive(){
		 log.info("用戶已收貨,訂單完成");
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章