如何将 Spring Statemachine 作为一个轻量级工作流引擎来使用?

一、State Machine 是什么?

State Machine(状态机)是一个用来描述事物在不同状态之间如何转换的数学模型。其包含三个核心要素:状态(State)、事件(Event)、转换(Transition)。

  • 状态(State)

状态是指事物可能处于的某种情形或阶段。比如:一个订单处于已创建(CREATED)或已支付状态(PAID)。

  • 事件(Event)

事件是指引发状态发生变化的外部动作或内部触发。比如:对一个订单进行支付(PAY)或运输(SHIP)。

  • 转换(Transition)

转换是指从一个状态到另一个状态的变化规则。比如:一个订单从已支付(PAID)的状态,经过运输(SHIP)事件,转移到已运输(SHIPPED)状态。

一个完整的订单状态流转过程:

[DRAFT] --CREATE--> [CREATED] --PAY--> [PAID] --SHIP--> [SHIPPED] --DELIVER--> [DELIVERED]

二、Spring Statemachine 是什么?

Spring Statemachine 是 Spring 生态中的一个专门用来构建和管理 State Machine 的框架。它把上面提到的 State Machine 概念,变成了 Java 开发者可以直接使用的工具。

我们可以把它理解成一个「状态机的工厂」—— 只需要告诉它业务规则(有哪些状态、什么事件触发什么变化),它就会帮我们自动管理整个状态的流转过程。

没有 Spring Statemachine 时,我们需要自己编写大量的 if-else 来判断状态:

如果订单状态是 CREATED,并且用户进行了 PAY 操作
  调用支付接口
  并把状态改成 PAID
  ...

否则如果订单状态是PAID,并且后台管理员进行了 SHIP 操作
  调用物流接口
  并把状态改成 SHIPPED
  ...

这种代码写多了就会变成难以维护的「面条代码」。

而有了 Spring Statemachine 后,我们只需要定义规则,框架会负责执行规则:

规则 1:CREATED → PAY 事件 → PAID
规则 2:PAID → SHIP 事件 → SHIPPED
规则 3:SHIPPED → DELIVER 事件 → DELIVERED

然后我们只需要告诉它:「触发支付事件」,框架就会自动触发我们预先绑定的业务逻辑。

Spring Statemachine 的主要组成部分:

  • 状态定义器

列出所有可能的状态。比如订单的状态:DRAFT、CREATED、PAID、SHIPPED、DELIVERED。

  • 事件定义器

定义所有可能触发的动作。比如订单的事件:CREATE、PAY、SHIP、DELIVER。

  • 转移配置器

连接状态和事件,形成规则。比如转移规则:CREATED 状态遇到 PAY 事件后变成 PAID 状态。

  • 动作执行器

在状态变化时执行具体的业务逻辑。比如支付成功后,要更新状态、发送短信通知、记录日志等。

  • 监听器

监控状态机的每一步变化。比如状态改变时、事件触发时,都能触发到指定的回调方法。

  • 持久化支持

把状态机的当前状态保存到数据库。这样当服务重启后,工作流也能从上次中断的地方继续。

三、将 Spring Statemachine 作为一个轻量级工作流引擎来使用

将 Spring Statemachine 作为轻量级工作流引擎来使用,核心思路是:将业务流程建模为一个状态机,通过定义清晰的状态和事件,由框架来驱动整个流程的自动化。

3.1 定义状态和事件(States & Events)

public enum OrderStates {
    DRAFT,
    CREATED,
    PAID,
    SHIPPED,
    DELIVERED
}
public enum OrderEvents {
    CREATE,
    PAY,
    SHIP,
    DELIVER
}

3.2 配置流程规则(Transitions)

这是构建工作流引擎最核心的一步。我们需要通过代码将这些状态(States)和事件(Events)连接起来,形成明确的流转规则。在配置类上使用 @EnableStateMachineFactory 注解,可以为每个流程实例(如每个订单)创建独立的状态机。

@Configuration
@EnableStateMachineFactory
public class OrderStateMachineConfig
        extends EnumStateMachineConfigurerAdapter<OrderStates, OrderEvents> {

    @Override
    public void configure(StateMachineConfigurationConfigurer<OrderStates, OrderEvents> config)
            throws Exception {
        config.withConfiguration()
                .autoStartup(true);
    }

    @Override
    public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states)
            throws Exception {
        states.withStates()
                .initial(OrderStates.DRAFT)
                .states(EnumSet.allOf(OrderStates.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions)
            throws Exception {
        transitions.withExternal()
                .source(OrderStates.DRAFT).target(OrderStates.CREATED).event(OrderEvents.CREATE)
                .and()
                .withExternal()
                .source(OrderStates.CREATED).target(OrderStates.PAID).event(OrderEvents.PAY)
                .and()
                .withExternal()
                .source(OrderStates.PAID).target(OrderStates.SHIPPED).event(OrderEvents.SHIP)
                .and()
                .withExternal()
                .source(OrderStates.SHIPPED).target(OrderStates.DELIVERED).event(OrderEvents.DELIVER);
    }
}

3.3 驱动流程运转(Sending Events)

流程模型和规则配置好后,在业务代码(如 Service 层)中,就可以通过向状态机发送事件来驱动流程前进了。

3.4 监听器(Listener)

使用 @OnTransition 注解来监听状态变化并执行对应的业务逻辑。这比将业务代码写在 Service 层更符合工作流引擎的设计理念。

3.4 实现持久化与恢复(Persistence、Restore)

对于一个可靠的工作流引擎来说,服务重启后流程必须能从断点处恢复,这是至关重要的一步。

参考资料

[1] Spring: Spring Statemachine Reference Documentation - https://docs.spring.io/spring-statemachine/docs/4.0.1/reference/index.html

评论

正在加载评论......