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


发表于 2017-03-21 | Spring框架 | SpringBoot

文章目

  1. 1. 环境依赖
  2. 2. 状态和事件
    1. 2.1. 状态枚举
    2. 2.2. 事件枚举
  3. 3. 状态机配置
    1. 3.1. 初始化状态机状态
    2. 3.2. 初始化状态迁移事件
  4. 4. 状态监听器
  5. 5. 总结
  6. 6. 源代码

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

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

环境依赖

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

  
  
  1. <dependency>
  2. <groupId>org.springframework.statemachine</groupId>
  3. <artifactId>spring-statemachine-core</artifactId>
  4. <version>1.2.0.RELEASE</version>
  5. </dependency>

状态和事件

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

状态枚举

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

  
  
  1. public enum RegStatusEnum {
  2.  
  3. // 未连接
  4. UNCONNECTED,
  5. // 已连接
  6. CONNECTED,
  7. // 注册中
  8. REGISTERING,
  9. // 已注册
  10. REGISTERED;
  11.  
  12. }

事件枚举

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

  
  
  1. public enum RegEventEnum {
  2. // 连接
  3. CONNECT,
  4. // 注册
  5. REGISTER,
  6. // 注册成功
  7. REGISTER_SUCCESS,
  8. // 注册失败
  9. REGISTER_FAILED,
  10. // 注销
  11. UN_REGISTER;
  12. }

状态机配置

  
  
  1. @Configuration
  2. @EnableStateMachine
  3. public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<RegStatusEnum, RegEventEnum> {
  4.  
  5. }

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

初始化状态机状态

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

  
  
  1. @Override
  2. public void configure(StateMachineStateConfigurer<RegStatusEnum, RegEventEnum> states) throws Exception {
  3. states.withStates()
  4. // 定义初始状态
  5. .initial(RegStatusEnum.UNCONNECTED)
  6. // 定义状态机状态
  7. .states(EnumSet.allOf(RegStatusEnum.class));
  8. }

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

初始化状态迁移事件

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

  
  
  1. @Override
  2. public void configure(StateMachineTransitionConfigurer<RegStatusEnum, RegEventEnum> transitions)
  3. throws Exception {
  4. transitions
  5. // 1.连接事件
  6. // 未连接 -> 已连接
  7. .withExternal()
  8. .source(RegStatusEnum.UNCONNECTED)
  9. .target(RegStatusEnum.CONNECTED)
  10. .event(RegEventEnum.CONNECT)
  11. .and()
  12.  
  13. // 2.注册事件
  14. // 已连接 -> 注册中
  15. .withExternal()
  16. .source(RegStatusEnum.CONNECTED)
  17. .target(RegStatusEnum.REGISTERING)
  18. .event(RegEventEnum.REGISTER)
  19. .and()
  20.  
  21. // 3.注册成功事件
  22. // 注册中 -> 已注册
  23. .withExternal()
  24. .source(RegStatusEnum.REGISTERING)
  25. .target(RegStatusEnum.REGISTERED)
  26. .event(RegEventEnum.REGISTER_SUCCESS)
  27. .and()
  28.  
  29. // 5.注销事件
  30. // 已连接 -> 未连接
  31. .withExternal()
  32. .source(RegStatusEnum.CONNECTED)
  33. .target(RegStatusEnum.UNCONNECTED)
  34. .event(RegEventEnum.UN_REGISTER)
  35. .and()
  36. // 注册中 -> 未连接
  37. .withExternal()
  38. .source(RegStatusEnum.REGISTERING)
  39. .target(RegStatusEnum.UNCONNECTED)
  40. .event(RegEventEnum.UN_REGISTER)
  41. .and()
  42. // 已注册 -> 未连接
  43. .withExternal()
  44. .source(RegStatusEnum.REGISTERED)
  45. .target(RegStatusEnum.UNCONNECTED)
  46. .event(RegEventEnum.UN_REGISTER)
  47. ;
  48. }

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

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

  
  
  1. // 未连接 -> 已连接
  2. .withExternal()
  3. .source(RegStatusEnum.UNCONNECTED)
  4. .target(RegStatusEnum.CONNECTED)
  5. .event(RegEventEnum.CONNECT)

状态监听器

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

  
  
  1. @WithStateMachine
  2. public class StateMachineEventConfig {
  3.  
  4. @OnTransition(source = "UNCONNECTED", target = "CONNECTED")
  5. public void connect() {
  6. System.out.println("///");
  7. System.out.println("连接事件, 未连接 -> 已连接");
  8. System.out.println("///");
  9. }
  10.  
  11. @OnTransition(source = "CONNECTED", target = "REGISTERING")
  12. public void register() {
  13. System.out.println("///");
  14. System.out.println("注册事件, 已连接 -> 注册中");
  15. System.out.println("///");
  16. }
  17.  
  18. @OnTransition(source = "REGISTERING", target = "REGISTERED")
  19. public void registerSuccess() {
  20. System.out.println("///");
  21. System.out.println("注册成功事件, 注册中 -> 已注册");
  22. System.out.println("///");
  23. }
  24.  
  25. @OnTransition(source = "REGISTERED", target = "UNCONNECTED")
  26. public void unRegister() {
  27. System.out.println("///");
  28. System.out.println("注销事件, 已注册 -> 未连接");
  29. System.out.println("///");
  30. }
  31. }

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

总结

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

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

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

源代码

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值