状态机笔记

Spring状态机应用详解


听到这个名词一愣,但是很快反应过来了,就是状态和逻辑控制名词化了。

当然,和普通逻辑相比,可不是改个名字而已,有很多不同。

什么是状态机

Java状态机是一种用于描述系统状态转换的模型,通过定义状态、事件、动作和转换规则来控制程序行为。

其核心要素如下:
**状态(States):**系统可能处于的固定状态,如订单状态中的"已支付"、“已发货"等 。 ‌
**事件(Events):**触发状态转换的外部或内部信号,如"支付”、“取消"等操作 。 ‌
**动作(Actions):**状态转换时执行的操作,例如更新状态字段或记录日志 。 ‌
**转换(Transitions):**定义事件触发下状态转移的规则,例如"支付成功"事件将"待支付"状态转为"支付成功”。

这么看是否还得维护个状态表,看起来才比较清楚。

普通逻辑和状态机的区别

名称普通逻辑状态机
逻辑清晰度需要if else来实现逻辑判断,可读性差状态机通过预定义状态和事件,将状态转换规则显式化,避免冗余的条件判断,可读性强。
扩展性需要在原代码上修改逻辑,易出错,扩展性差。新增状态或事件时,只需扩展状态机配置,无需修改现有代码。
线程安全支持需手动处理同步问题(如使用synchronized或Lock),实现复杂且易出错。状态机框架(如Spring StateMachine)内置线程同步机制,确保并发场景下状态一致性。
业务解耦状态处理常耦合在业务方法内,难以独立测试。 ‌状态机将状态逻辑与业务代码分离,便于测试和复用。
可视化配置普通逻辑需通过代码硬编码状态转换,可读性差。 ‌框架支持通过代码或配置文件定义状态机,直观展示状态迁移路径。

集成及使用

引入maven依赖

<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>	
定义状态枚举

代码:

public enum States {
    UNPAID,                 // 待支付
    WAITING_FOR_RECEIVE,    // 待收货
    DONE                   	// 结束
}
定义事件枚举

代码:

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

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

代码:

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;
            }
        };
}
状态转移的监听器
@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("--------------------用户已收货,订单完成----------------------");  
    }  
 
}

测试

测试类代码:

@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);  //收货操作   结束
	}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值