java statemachine_StateMachine 状态机机制深入解析

前言

Spring StateMachine 让状态机结构更加层次化,可以帮助开发者简化状态机的开发过程。

之前,我们使用二维数组实现状态机机制,现在,我们来用 Spring StateMachine 进行改造。

环境依赖

修改 POM 文件,添加 spring-statemachine-core 依赖。

org.springframework.statemachine

spring-statemachine-core

1.2.0.RELEASE

状态和事件

现在,我以用户注册为案例,来讲解状态和事件之间的状态机机制。

状态枚举

注册有哪些状态呢,我们来想想,应该有4个状态:未连接、已连接、注册中、已注册。

public enum RegStatusEnum {

// 未连接

UNCONNECTED,

// 已连接

CONNECTED,

// 注册中

REGISTERING,

// 已注册

REGISTERED;

}

事件枚举

相对应的,存在几个核心事件:连接、注册、注册成功、注册失败、注销。

public enum RegEventEnum {

// 连接

CONNECT,

// 注册

REGISTER,

// 注册成功

REGISTER_SUCCESS,

// 注册失败

REGISTER_FAILED,

// 注销

UN_REGISTER;

}

状态机配置

@Configuration

@EnableStateMachine

public class StateMachineConfig extends EnumStateMachineConfigurerAdapter {

}

@EnableStateMachine注解,标识启用 Spring StateMachine 状态机功能。

初始化状态机状态

我们需要初始化状态机的状态。

@Override

public void configure(StateMachineStateConfigurer states) throws Exception {

states.withStates()

// 定义初始状态

.initial(RegStatusEnum.UNCONNECTED)

// 定义状态机状态

.states(EnumSet.allOf(RegStatusEnum.class));

}

其中,initial(RegStatusEnum.UNCONNECTED) 定义了初始状态是未连接状态。states(EnumSet.allOf(RegStatusEnum.class)) 定义了定义状态机中存在的所有状态。

初始化状态迁移事件

我们需要初始化当前状态机有哪些状态事件。

@Override

public void configure(StateMachineTransitionConfigurer transitions)

throws Exception {

transitions

// 1.连接事件

// 未连接 -> 已连接

.withExternal()

.source(RegStatusEnum.UNCONNECTED)

.target(RegStatusEnum.CONNECTED)

.event(RegEventEnum.CONNECT)

.and()

// 2.注册事件

// 已连接 -> 注册中

.withExternal()

.source(RegStatusEnum.CONNECTED)

.target(RegStatusEnum.REGISTERING)

.event(RegEventEnum.REGISTER)

.and()

// 3.注册成功事件

// 注册中 -> 已注册

.withExternal()

.source(RegStatusEnum.REGISTERING)

.target(RegStatusEnum.REGISTERED)

.event(RegEventEnum.REGISTER_SUCCESS)

.and()

// 5.注销事件

// 已连接 -> 未连接

.withExternal()

.source(RegStatusEnum.CONNECTED)

.target(RegStatusEnum.UNCONNECTED)

.event(RegEventEnum.UN_REGISTER)

.and()

// 注册中 -> 未连接

.withExternal()

.source(RegStatusEnum.REGISTERING)

.target(RegStatusEnum.UNCONNECTED)

.event(RegEventEnum.UN_REGISTER)

.and()

// 已注册 -> 未连接

.withExternal()

.source(RegStatusEnum.REGISTERED)

.target(RegStatusEnum.UNCONNECTED)

.event(RegEventEnum.UN_REGISTER)

;

}

这里,我以连接事件为案例,其中 source 指定原始状态,target 指定目标状态,event 指定触发事件。

因此,下面的状态就很好理解了,即当发生连接事件时,从未连接状态变更为已连接状态。

// 未连接 -> 已连接

.withExternal()

.source(RegStatusEnum.UNCONNECTED)

.target(RegStatusEnum.CONNECTED)

.event(RegEventEnum.CONNECT)

状态监听器

Spring StateMachine 提供了注解配置实现方式,所有 StateMachineListener 接口中定义的事件都能通过注解的方式来进行配置实现。

@WithStateMachine

public class StateMachineEventConfig {

@OnTransition(source = "UNCONNECTED", target = "CONNECTED")

public void connect() {

System.out.println("///");

System.out.println("连接事件, 未连接 -> 已连接");

System.out.println("///");

}

@OnTransition(source = "CONNECTED", target = "REGISTERING")

public void register() {

System.out.println("///");

System.out.println("注册事件, 已连接 -> 注册中");

System.out.println("///");

}

@OnTransition(source = "REGISTERING", target = "REGISTERED")

public void registerSuccess() {

System.out.println("///");

System.out.println("注册成功事件, 注册中 -> 已注册");

System.out.println("///");

}

@OnTransition(source = "REGISTERED", target = "UNCONNECTED")

public void unRegister() {

System.out.println("///");

System.out.println("注销事件, 已注册 -> 未连接");

System.out.println("///");

}

}

这里,我仍然以连接事件为案例,@OnTransition 中 source 指定原始状态,target 指定目标状态,当事件触发时将会被监听到从而调用 connect() 方法。

总结

Spring StateMachine 让状态机结构更加层次化,可以帮助开发者简化状态机的开发过程。

我们来回顾下几个核心步骤

定义状态枚举。

定义事件枚举。

定义状态机配置,设置初始状态,以及状态与事件之间的关系。

定义状态监听器,当状态变更时,触发方法。

源代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持谷谷点程序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值