注意事项
- 由于框架中每次都是加载一个状态机内存实例,所以在执行状态转移相关代码时一定要加分布式锁!!!建议状态维护提供统一调用service,开启事务、处理异常 。
- spring-statemachine异常包装比较另类,如guard、action以及listener中发生异常,状态机会捕获并把异常信息捕获为警告,状态也能够成功转移到次态,这显然不符合 我们的需求,所以调用后需要手动判断是否发生异常stateMachine.hasStateMachineError(),但statemachine并没有给提供获取异常信息的接口,所以在guard 和action中将异常信息用变量的方式解决此问题,stateMachine.getExtendedState().getVariables().put("message", "当前状态不满足执行条件");
- @EnableStateMachineFactory开启工厂模式,然后通过StateMachineService从持久化层加载一个状态机实例 。
- 当一个project中有多个业务状态机时,@EnableStateMachineFactory(name = "xxx")为工厂配置名称以区别不同的业务状态机 。
- 当使用withChoice()时,一定要在配置StateMachineStateConfigurer.choice()配置分支状态,否则将不生效 。
@Componentpublic class ActivityMachine extends SquirrelStateMachine<ActivityMachine, State, Event, TransmitCmd> {private final ActivityStateService activityStateService;public ActivityMachine(ApplicationContext applicationContext) {super(applicationContext);activityStateService = applicationContext.getBean(ActivityStateService.class);}@Overridepublic void buildStateMachine(StateMachineBuilder<ActivityMachine, State, Event, TransmitCmd> stateMachineBuilder) {stateMachineBuilder.externalTransition().from(State.INIT).to(State.DRAFT).on(Event.SAVE).when(applicationContext.getBean(SubmitCondition.class));//以下省略,大致与spring-statemachine相同}@Overridepublic ActivityMachine createStateMachine(State stateId) {ActivityMachine activityMachine = super.createStateMachine(stateId);activityMachine.addStartListener(new StartListener<ActivityMachine, State, Event, TransmitCmd>() {});return activityMachine;}@Overrideprotected void afterTransitionDeclined(S fromState, E event, C context) {//转移状态未执行}@Overrideprotected void afterTransitionCausedException(S fromState, S toState, E event, C context) {// 转移状态时发生异常}@Overrideprotected void afterTransitionCompleted(State fromState, State toState, Event event, TransmitCmd context) {log.info("from {} to {} on {}, {}", fromState.getDesc(), toState.getDesc(), event.getDesc(), context);}}
说明:- squirrel-foundation直接可继承AbstractStateMachine实例化状态机,配置上大体相同只是使用的是from、to、on、when词不同,框架builder的约束太强 。
- 不支持choice分支状态 。
- 状态机异常处理afterTransitionCausedException相比spring-statemachine更加方便、易用 。
- 状态的持久化通过重写afterTransitionCompleted方法即可 。
- 由于新项目中涉及到跨部门卡券业务,在开发初期审核活动通过时同步创建卡券批次,却忽略了异步生成券码的时间,随着开发的深入才意识到此问题 。此时只需要在状态审核通过时加一个过渡状态并启动一个任务去轮询券码是否创建完成即可,丝毫不影响已开发的代码 。
- 最初的需求设计时,活动下线后是不能再次上线的,在需求迭代期内又增加了再次上线的功能,状态机流转逻辑清晰,只需要再增加个状态配置流转事件就行,就为状态机赋予了再次上线的能力 。
最后建议在状态流程不是很复杂的情况,如果您也厌烦了if...else,那么不妨尝试一下squirrel-foundation,相信也是不错的选择 。
参考文献
- ??https://baike.baidu.com/item/%E7%8A%B6%E6%80%81%E6%9C%BA/6548513?fr=aladdin??
- ??https://zh.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA??
推荐阅读
- SpringBoot整合RocketMQ,老鸟们都是这么玩的!
- Spring注解@After,@Around,@Before的执行顺序?
- Spring Boot+Nacos+gRPC,一个区别于 OpenFeign 的微服务通信方案!
- 冬天酵母粉怎样发面快
- 不支持随机播放等,关于苹果古典乐应用 Apple Music Classical 的一些注意事项
- 在 SpringBoot 中使用 Spring AOP 实现接口鉴权
- 这两个强大的开源C#反编译逆向工具,探索C#桌面应用的秘密
- HTTP缓存如何提高Web应用程序的性能?
- 硝化细菌胶囊怎么用
- |滑漂钓鱼的4个应用场景,大鱼的克星,针对特殊鱼情的杀手锏