likes
comments
collection
share

状态机选型之SpringStateMachine

作者站长头像
站长
· 阅读数 42

写在前头的一些话

最近项目状态重构,引入了状态机。在网上找了一些资料,常用的状态机有:spring-statemachine,squirrel-foundation,Akka FSM,stateless4j 等等,看的我是眼花缭乱的。

最终,考虑组件的维护团队、使用手册、与项目使用架构的兼容性(项目使用的是SSM)等方面原因,选用spring-statemachine。

在前期技术调研过程中,网上绝大部分资料都是相互copy或者翻译官方文档,甚至还有一些就是BUG跑不起来,一上来就是告诉你有这么个玩意,然后就是怎么安装,怎么运行,功能有哪些,特性列起来,写一个超级简单demo。但就不告诉你这个东西能干啥!由那些模块组成!在企业中如何应用!

我想要的是企业级的解决方案,网上一个简单demo在企业级的开发中毫无用处,从我的角度出发,有以下几个问题:

项目中不会只有一个状态机,多个状态机如何并存,如何区分,一个简单的demo能有用吗?难道和老板讲我的状态机demo告诉我,状态机的流程只能选一个? 项目是高并发的应用,一类状态机流程,比如订单流程,其实也是有很多订单的流程在同时跑,而以网上简单的demo,全部订单共用一个流程,一个订单到 WAIT_PAY 状态了,其他订单就不能是 REFUND 状态了? 项目是分布式的应用,不可能一个订单的所有状态扭转的请求都打到一台服务器上,所以订单状态不全部都是从 WAIT_PAY 开始,这种情况 如何指定状态机的初始状态? 做项目是有业务逻辑的,是有参数传递的,不是打印一句‘订单创建,等待支付’就能结束的,所以,状态机如何传递参数,在哪里处理业务等等,这些都要解决的。 如何使用事物?

一些参考文档

官方文档:spring.io/projects/sp…

用户手册:docs.spring.io/spring-stat… (2.1.3.RELEASE 版本)

官网提供的文档,讲解的是十分的精简,要想更深入的了解其内部架构,只有不断的测试,查看内部源码的实现。

网上较好的资料

blog.csdn.net/firebat CSDN上一个博主写的,应用于企业项目,博主写的不是很详细,但是博主在应用企业项目时踩过的坑都有记录,具有参考意义 www.jianshu.com/u/c323ec8e0… 简书上一个博主写的,状态机常用的使用方法都有些,具有参考意义。

官网Demo

@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {
 
    @Override
    public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
        config.withConfiguration()
                .autoStartup(true)
                .listener(listener());
    }
 
    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
        states.withStates().initial(States.SI).states(EnumSet.allOf(States.class));
    }
 
    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
        transitions.withExternal()
                .source(States.SI)
                .target(States.S1)
                .event(Events.E1)
                 
                .and().withExternal()
                .source(States.S1)
                .target(States.S2)
                .event(Events.E2);
    }
 
    @Bean
    public StateMachineListener<States, Events> listener() {
        return new StateMachineListenerAdapter<States, Events>() {
            @Override
            public void stateChanged(State<States, Events> from, State<States, Events> to) {
                System.out.println("State change to " + to.getId());
            }
        };
    }
}

在官方文档说明中,支持注解声明状态机配置,这点也可以从demo中看出。至于为什么写上一个@EnableStateMachine或者@EnableStateMachineFactory就创建了一个状态机,这是底层实现,需要看源码。这里没有进行深入研究,不发表任何言论。如果有兴趣可以研究研究 AnnotationConfigurer

相关概念

状态机模型 StateMachine<S, E>

StateMachine 是状态机模型的抽象接口,接口定义了两个泛型 S 和 E。

S 即为 state-状态:一般以枚举定义。 E 即为 event-事件:一般以枚举定义。

要素

状态机可归纳为4个要素,现态、条件、动作、次态。“现态”和“条件”是因,“动作”和“次态”是果。

现态:指当前所处的状态。 条件:又称“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必须的,当条件满足后,也可以不执行任何动作,直接迁移到新的状态。 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转换成“现态”。

常用注解

@EnableStateMachine:声明启用状态机配置,适合单机服务,在企业开发中很少用到。 @EnableStateMachineFactory:声明启动状态机工厂配置。适用于企业中,多个状态机并存。 @WithStateMachine:声明事件,通过ID或者name关联状态机。 @OnTransition:事件配置,source-target。

实现自己的状态机

实现状态机有两种方式,一种是集成StateMachineConfigurer实现具体方法,另一种是使用StateMachineBuilder构建。首先看看StateMachineConfigurer的继承结构。

StateMachineConfigurer |-- AbstractStateMachineConfigurerAdapter |-- StateMachineConfigurerAdapter |-- EnumStateMachineConfigurerAdapter |-- BuilderStateMachineConfigurerAdapter StateMachineConfigurer 是状态机配置的抽象接口。它的下面有两个子类适配器,一个抽象的AbstractStateMachineConfigurerAdapterBuilderStateMachineConfigurerAdapter

AbstractStateMachineConfigurerAdapter 下面有StateMachineConfigurerAdapterStateMachineConfigurerAdapter下面有EnumStateMachineConfigurerAdapterStateMachineConfigurerAdapterEnumStateMachineConfigurerAdapter区别主要在于泛型,StateMachineConfigurerAdapter支持泛型为Object,EnumStateMachineConfigurerAdapter支持泛型为Enum。

BuilderStateMachineConfigurerAdapterStateMachineBuilder的一个内部类。StateMachineBuilder通过构建器模式实现。

StateMachinePersist<S, E, T> |-- ZookeeperStateMachinePersist |-- RepositoryStateMachinePersist |-- Memory |-- Redis

基于StateMachineConfigurer实现状态机

一般情况下,是继承StateMachineConfigurerAdapter,该类中有5个配置方法,状态机将配置分为5大类:状态配置,事件配置,配置信息配置,构造器配置置,状态机模型配置。在日常开发中用到其中三个。

configure(StateMachineStateConfigurer<S, E> states):定义状态配置,主要是定义初始化状态,定义状态集合。 configure(StateMachineTransitionConfigurer<S, E> transitions):定义事件配置。 configure(StateMachineConfigurationConfigurer<S, E> config):定义配置信息配置,有基本信息配置,分布式配置,监控配置,持久化配置,安全配置,验证配置。 configure(StateMachineConfigBuilder<S, E> config):定义构造器配置,一般不用。 configure(StateMachineModelConfigurer<S, E> model):定义状态机模型配置,一般不用。 定义状态枚举

转载自:https://juejin.cn/post/6992929648426352671
评论
请登录