10分钟带你体验 Solon 的状态机

一、介绍

Solon 状态机,称为 Solon State Machine。它是一种可以管理状态、事件之间的关系,以及他们之间的转换。这是一个专门为应用程序中的状态管理和状态转换提供支持的框架。

它简化了事物对象在不同状态下,不同事件转化的代码管理,让其代码变得更加清晰明了。

本文将介绍 Solon State Machine 状态机在 Solon 框架下的使用,10分钟带你理解并上手使用 Solon 状态机

二、状态机的核心概念

首先,我们必须要了解 Solon 状态机的几个核心概念,如下

  • 状态(State):代表着对象的当前状态
  • 事件(Event):对象状态转变是因何而改变的
  • 转换(Transition):定义了事物的状态是通过哪个事件变到了另一个状态

比如,最常见的就是订单系统,下面就简单模拟一下正常订单的状态流转:

  • 用户下单(状态为:待支付)
  • 用户支付成功(状态为:已支付待发货)
  • 仓库已发货(状态为:已发货待收货)
  • 用户成功收货(状态为:已收货)

三、代码

添加对应的 maven 依赖

xml 复制代码
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-statemachine</artifactId>
    <version>3.5.0</version>
</dependency>

对于状态,由于非常固定,我们最好是使用枚举,如下OrderStatus.java

java 复制代码
import org.noear.solon.statemachine.State;

public enum OrderStatusEnum implements State{
    WAIT_PAY, //待支付
    WAIT_DELIVER, //已支付待发货
    WAIT_RECEIVE, //已发货待收货
    RECEIVED; //已收货
}

还要定义一下事件的枚举

java 复制代码
import org.noear.solon.statemachine.Event;

public enum OrderStatusEventEnum implements Event{
    ORDER, //用户下单
    PAY, //用户支付成功
    DELIVER, //仓库已发货
    RECEIVE; //用户成功收货
}

接下来我们就能定义转换了,在 Solon 框架下,我们可以定义一个 OrderStateMachine 托管类

java 复制代码
@Managed
public class OrderStateMachine extends StateMachine<OrderStatusEnum,OrderStatusEventEnum, OrderEntity> {
    public OrderStateMachine() {
        // 待支付 -> 已支付待发货(支付成功)
        addTransition(t -> t.
                from(OrderStatusEnum.WAIT_PAY)
                .to(OrderStatusEnum.WAIT_DELIVER)
                .on(OrderStatusEventEnum.PAY)
                .then(c -> c.getPayload().setStatus(c.getTo())));

        // 已支付待发货 -> 已发货待收货(仓库已发货)
        addTransition(t -> t.
                from(OrderStatusEnum.WAIT_DELIVER)
                .to(OrderStatusEnum.WAIT_RECEIVE)
                .on(OrderStatusEventEnum.DELIVER)
                .then(c -> c.getPayload().setStatus(c.getTo())));

        // 已发货待收货 -> 已收货(用户收货)
        addTransition(t -> t.
                from(OrderStatusEnum.WAIT_RECEIVE)
                .to(OrderStatusEnum.RECEIVED)
                .on(OrderStatusEventEnum.RECEIVE)
                .then(c -> c.getPayload().setStatus(c.getTo())));
    }
}

是不是感觉还缺了什么呢,配置中还缺少一个下单事件,这没有关系,这是我们初始的一个事件,不参于配置

我们写对应的 OrderController 接口即可,这边模拟一下,创建订单进行落库

java 复制代码
@Controller
public class OrderController {
    @Mapping("/create")
    public Result<Void> create() {
        // TODO 模拟订单落库
        return Result.succeed();
    }
}

重点是在后面的,支付这一个阶段,我们应该如何接入状态机,如下

java 复制代码
@Controller
public class OrderController {
    @Inject
    private OrderStateMachine orderStatusMachine;

    @Mapping("/create")
    public Result create() {
        // TODO 模拟订单落库
        return Result.succeed();
    }

    @Post
    @Mapping("/pay")
    public Result pay() {
        // TODO 模拟订单支付
        return Result.succeed();
    }

    @Post
    @Mapping("/payNotify")
    public Result payNotify(Integer orderId) {
        // TODO 支付成功后,使用状态机

        // 模拟通过id查找一个订单对象
        OrderEntity entity = new OrderEntity(orderId, OrderStatusEnum.WAIT_PAY);

        // 使用状态机发送这个消息
        orderStatusMachine.sendEvent(OrderStatusEventEnum.PAY, EventContext.of(entity.getStatus(), entity));
        return Result.succeed();
    }
}
相关推荐
chilavert3181 分钟前
技术演进中的开发沉思-356:重排序(中)
java·开发语言
毕设源码-邱学长2 分钟前
【开题答辩全过程】以 基于SSM的儿童福利院管理系统为例,包含答辩的问题和答案
java·eclipse
TT哇8 分钟前
【实习】数字营销系统 银行经理端(interact_bank)前端 Vue 移动端页面的 UI 重构与优化
java·前端·vue.js·ui
Elieal18 分钟前
SpringBoot 数据层开发与企业信息管理系统实战
java·spring boot·后端
识君啊18 分钟前
MyBatis-Plus 逻辑删除导致唯一索引冲突的解决方案
java·spring boot·mybatis·mybatis-plus·唯一索引·逻辑删除
Coder_Boy_19 分钟前
Java开发者破局指南:跳出内卷,借AI赋能,搭建系统化知识体系
java·开发语言·人工智能·spring boot·后端·spring
QT.qtqtqtqtqt21 分钟前
SQL注入漏洞
java·服务器·sql·安全
独自破碎E24 分钟前
BISHI23 小红书推荐系统
java·后端·struts
xqqxqxxq26 分钟前
Java IO 核心:BufferedReader/BufferedWriter & PrintStream/PrintWriter 技术笔记
java·笔记·php
Aric_Jones27 分钟前
idea使用.env运行SpringBoot项目
java·spring boot·intellij-idea