Spring Boot 揭秘与实战(七) 实用技术篇 - StateMachine 状态机机制

原文地址:Spring Boot 揭秘与实战(七) 实用技术篇 - StateMachine 状态机机制
博客地址:blog.720ui.com/javascript

Spring StateMachine 让状态机结构更加层次化,能够帮助开发者简化状态机的开发过程。以前,咱们使用二维数组实现状态机机制,如今,咱们来用 Spring StateMachine 进行改造。java

环境依赖

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

<dependency>
    <groupId>org.springframework.statemachine</groupId>
    <artifactId>spring-statemachine-core</artifactId>
    <version>1.2.0.RELEASE</version>
</dependency>复制代码

状态和事件

如今,我以用户注册为案例,来说解状态和事件之间的状态机机制。github

状态枚举

注册有哪些状态呢,咱们来想一想,应该有4个状态:未链接、已链接、注册中、已注册。spring

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<RegStatusEnum, RegEventEnum> {

}复制代码

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

初始化状态机状态

咱们须要初始化状态机的状态。微信

@Override
public void configure(StateMachineStateConfigurer<RegStatusEnum, RegEventEnum> states) throws Exception {
    states.withStates()
    // 定义初始状态
    .initial(RegStatusEnum.UNCONNECTED)
    // 定义状态机状态
    .states(EnumSet.allOf(RegStatusEnum.class));
}复制代码

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

初始化状态迁移事件

咱们须要初始化当前状态机有哪些状态事件。ui

@Override
public void configure(StateMachineTransitionConfigurer<RegStatusEnum, RegEventEnum> 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 让状态机结构更加层次化,能够帮助开发者简化状态机的开发过程。

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

  • 定义状态枚举。
  • 定义事件枚举。
  • 定义状态机配置,设置初始状态,以及状态与事件之间的关系。
  • 定义状态监听器,当状态变动时,触发方法。

源代码

相关示例完整代码: springboot-action

(完)

更多精彩文章,尽在「服务端思惟」微信公众号!

相关文章
相关标签/搜索