聊聊Cola-StateMachine轻量级状态机的实现

这篇具有很好参考价值的文章主要介绍了聊聊Cola-StateMachine轻量级状态机的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

在分析Seata的saga模式实现时,实在是被其复杂的 json 状态语言定义文件劝退,我是有点没想明白为啥要用这么来实现状态机;盲猜可能是基于可视化的状态机设计器来定制化流程,更方便快捷且上手快吧,毕竟可以通过UI直接操作,设计状态流转图,但我暂时不太能get到。对于Saga模式的实现,之前的博文中已经阐述了基于状态机模式实现Saga,是比较常见且合适的做法,因此了解了下Java中的状态机实现方案,以后有相关的业务场景也可以直接上手使用状态机。

Cola-StateMachine

Cola-StateMachine组件是一种轻量级的、无状态的、基于注解的状态机实现,可以方便地管理订单等业务对象的状态转换。COLA框架的状态机使用了连贯接口(Fluent Interfaces)来定义状态和事件,以及对应的动作和检查。COLA框架的状态机是COLA 4.0应用架构的一部分,旨在控制复杂度,提高开发效率。开发背景可见实现一个状态机引擎,教你看清DSL的本质。

基础模型

在Cola-StateMachine组件中有如下的抽象概念模型:

1.State:状态
2.Event:事件,状态由事件触发,引起变化
3.Transition:流转,表示从一个状态到另一个状态
4.External Transition:外部流转,两个不同状态之间的流转
5.Internal Transition:内部流转,同一个状态之间的流转
6.Condition:条件,表示是否允许到达某个状态
7.Action:动作,到达某个状态之后,可以做什么
8.StateMachine:状态机

Cola-StateMachine链路图

聊聊Cola-StateMachine轻量级状态机的实现

业务应用示例

基于订单业务的场景,做一个简单的demo。

关闭订单的简单流程图

聊聊Cola-StateMachine轻量级状态机的实现

关闭订单简单的状态流转图

聊聊Cola-StateMachine轻量级状态机的实现

添加依赖

<dependency>
    <groupId>com.alibaba.cola</groupId>
    <artifactId>cola-component-statemachine</artifactId>
    <version>4.3.1</version>
</dependency>

定义一个订单的实体类、订单状态的枚举值、订单事件的枚举值

@Data
@Builder
public class Order {

    public OrderStatusEnum orderStatusEnum;
    public Integer orderId;
    public String orderName;

}

public enum OrderStatusEnum {
    INIT("0", "待付款"),
    WAITING_FOR_DELIVERY("1", "待发货"),
    HAVE_BEEN_DELIVERY("2", "已发货"),
    CLOSE("3", "已取消");


    private final String code;
    private final String info;

    OrderStatusEnum(String code, String info)
    {
        this.code = code;
        this.info = info;
    }

    public String getCode()
    {
        return code;
    }

    public String getInfo()
    {
        return info;
    }
}

public enum OrderEvent {
    /**
     * 用户关闭
     */
    USER_CLOSE("0", "用户取消"),
    /**
     * 管理员关闭
     */
    ADMIN_CLOSE("1", "后台取消"),
    /**
     * 超时关闭
     */
    OVERTIME_CLOSE("2", "超时取消"),
    /**
     * 检查错误关闭
     */
    CHECK_ERROR_CLOSE("3", "上级审核取消"),

    /**
     * 用户付费
     */
    USER_PAY("4", "用户支付");


    /**
     * 密码
     */
    private final String code;
    /**
     * 信息
     */
    private final String info;

    /**
     * 订单事件
     *
     * @param code 密码
     * @param info 信息
     */
    OrderEvent(String code, String info) {
        this.code = code;
        this.info = info;
    }

    /**
     * 获取代码
     *
     * @return {@link String}
     */
    public String getCode() {
        return code;
    }

    /**
     * 获取信息
     *
     * @return {@link String}
     */
    public String getInfo() {
        return info;
    }
}

在容器启动的时候注册一个订单状态变更的工厂

@Component
public class StateMachineBuilderConfig {
    @Autowired
    UserCloseAction userCloseAction;

    @Bean("orderOperaMachine")
    public StateMachine orderOperaMachine() {
        String ORDER_OPERA = "order_opera";
        StateMachineBuilder<OrderStatusEnum, OrderEvent, Order> builder = StateMachineBuilderFactory.create();
        //订单从初始化状态-待发货-状态-转到-关闭订单状态--用户关闭
        builder.externalTransitions()
                .fromAmong(OrderStatusEnum.INIT, OrderStatusEnum.WAITING_FOR_DELIVERY)
                .to(OrderStatusEnum.CLOSE)
                .on(OrderEvent.USER_CLOSE)
                .when(checkCondition())
                .perform(userCloseAction);
        //订单从-初始化状态-已发货-待发货--转到-关闭订单状态--后台操作人员关闭
        builder.externalTransitions()
                .fromAmong(OrderStatusEnum.INIT, OrderStatusEnum.HAVE_BEEN_DELIVERY, OrderStatusEnum.WAITING_FOR_DELIVERY)
                .to(OrderStatusEnum.CLOSE)
                .on(OrderEvent.ADMIN_CLOSE)
                .when(checkCondition())
                .perform(doAction());
        //订单从等待发货状态-转为-订单关闭状态-超时关闭
        builder.externalTransition()
                .from(OrderStatusEnum.WAITING_FOR_DELIVERY)
                .to(OrderStatusEnum.CLOSE)
                .on(OrderEvent.OVERTIME_CLOSE)
                .when(checkCondition())
                .perform(doAction());
        //订单从待发货状态--转为-订单关闭状态-上级审批不通过关闭
        builder.externalTransition()
                .from(OrderStatusEnum.WAITING_FOR_DELIVERY)
                .to(OrderStatusEnum.CLOSE)
                .on(OrderEvent.CHECK_ERROR_CLOSE)
                .when(checkCondition())
                .perform(doAction());
        //订单从初始化状态--转为待发货状态--用户支付完毕动
        builder.externalTransition()
                .from(OrderStatusEnum.INIT)
                .to(OrderStatusEnum.WAITING_FOR_DELIVERY)
                .on(OrderEvent.USER_PAY)
                .when(checkCondition())
                .perform(doAction());

        StateMachine orderOperaMachine = builder.build(ORDER_OPERA);

        //打印uml图
        String plantUML = orderOperaMachine.generatePlantUML();
        System.out.println(plantUML);
        return orderOperaMachine;
    }

    private Condition<Order> checkCondition() {
        return (ctx) -> {
            return true;
        };
    }

    private Action<OrderStatusEnum, OrderEvent, Order> doAction() {
        return (from, to, event, ctx) -> {
            System.out.println(ctx.getOrderName() + " 正在操作 " + ctx.getOrderId() + " from:" + from + " to:" + to + " on:" + event);
        };
    }

}

在定义一个特殊的,只是举个例子,可以通过集成的方式集成实现一个用户关单的具体操作

@Component
public class UserCloseAction implements Action<OrderStatusEnum, OrderEvent, Order> {

    @Override
    public void execute(OrderStatusEnum from, OrderStatusEnum to, OrderEvent event, Order context) {
        System.out.println("用户关闭流程开始走了");
        System.out.println("从这个状态-【" + from.getInfo() + "】-转为+【" + to.getInfo() + "】 的状态");
        System.out.println("上下文信息:" + context.toString());
        System.out.println("中间执行的一些操作.......");
        System.out.println("用户关闭流程完毕了");
    }
}

定义一个 controller 的操作接口

@RestController
public class OrderOperaController {

    @Autowired
    @Qualifier("orderOperaMachine")
    StateMachine<OrderStatusEnum, OrderEvent, Order> orderOperaMachine;

    /**
     * 场景1-用户关闭订单
     *
     * @return {@link Boolean}
     */
    @RequestMapping("userclose")
    public Boolean userCloseOrder() {
        //把订单状态改为关闭
        String machineId = orderOperaMachine.getMachineId();
        System.out.println(machineId);
        Order order = Order.builder().orderId(1).orderName("用户").orderStatusEnum(OrderStatusEnum.INIT).build();
        OrderStatusEnum orderStatusEnum = orderOperaMachine.fireEvent(OrderStatusEnum.INIT,OrderEvent.USER_CLOSE, order);
        System.out.println(orderStatusEnum.toString());
        return true;
    }

    /**
     * 场景2-管理员关闭订单
     *
     * @return {@link Boolean}
     */
    @RequestMapping("adminClose")
    public Boolean adminCloseOrder() {
        //把订单状态改为关闭
        Order order = Order.builder().orderId(1).orderName("后台操作人员").orderStatusEnum(OrderStatusEnum.HAVE_BEEN_DELIVERY).build();
        OrderStatusEnum orderStatusEnum = orderOperaMachine.fireEvent(OrderStatusEnum.HAVE_BEEN_DELIVERY, OrderEvent.ADMIN_CLOSE, order);
        System.out.println(orderStatusEnum.toString());

        return true;
    }

    /**
     * 场景3-超时关闭订单
     *
     * @return {@link Boolean}
     */
    @RequestMapping("overTimeclose")
    public Boolean overTimeCloseOrder() {
        //把订单状态改为关闭
        Order order = Order.builder().orderId(1).orderName("超时了关闭订单")
                .orderStatusEnum(OrderStatusEnum.WAITING_FOR_DELIVERY).build();
        //OrderStatusEnum orderStatusEnum = orderOperaMachine.fireEvent(OrderStatusEnum.CLOSE, OrderEvent.OVERTIME_CLOSE, order);
        OrderStatusEnum orderStatusEnum = orderOperaMachine.fireEvent(OrderStatusEnum.WAITING_FOR_DELIVERY, OrderEvent.OVERTIME_CLOSE, order);
        System.out.println(orderStatusEnum.toString());
        return true;
    }

    /**
     * 场景4-检查错误关闭订单
     *
     * @return {@link Boolean}
     */
    @RequestMapping("checkErrorClose")
    public Boolean checkErrorCloseOrder() {
        //把订单状态改为关闭
        Order order = Order.builder().orderId(1).orderName("上级检查错误").orderStatusEnum(OrderStatusEnum.WAITING_FOR_DELIVERY).build();
        OrderStatusEnum orderStatusEnum = orderOperaMachine.fireEvent(OrderStatusEnum.WAITING_FOR_DELIVERY, OrderEvent.CHECK_ERROR_CLOSE, order);
        System.out.println(orderStatusEnum.toString());
        return true;
    }
}

启动程序

聊聊Cola-StateMachine轻量级状态机的实现

安装UML

聊聊Cola-StateMachine轻量级状态机的实现

随便新建一个uml文件,然后将启动程序的控制台输出内容复制到uml中

聊聊Cola-StateMachine轻量级状态机的实现

最后运行下

聊聊Cola-StateMachine轻量级状态机的实现文章来源地址https://www.toymoban.com/news/detail-474276.html

到了这里,关于聊聊Cola-StateMachine轻量级状态机的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 轻量级 HTTP 请求组件

    Apache HttpClient 是著名的 HTTP 客户端请求工具——现在我们模拟它打造一套简单小巧的请求工具库, 封装 Java 类库里面的 HttpURLConnection 对象来完成日常的 HTTP 请求,诸如 GET、HEAD、POST 等等,并尝试应用 Java 8 函数式风格来制定 API。 组件源码在:https://gitee.com/sp42_admin/ajaxjs/tr

    2024年02月01日
    浏览(65)
  • Tomcat轻量级服务器

    目录 1.常见系统架构  C-S架构 B-S架构 2.B-S架构系统的通信步骤 3.常见WEB服服务器软件 4.Tomcat服务器的配置 下载安装 环境变量配置 测试环境变量是否配置成功 测试Tomcat服务器是否配置成功  Tomcat窗口一闪而过的解决步骤 Tomcat解决乱码 介绍: C-S架构即Client/Server(客户端/服务

    2023年04月14日
    浏览(135)
  • 一种轻量级定时任务实现

    现在市面上有各式各样的分布式定时任务,每个都有其独特的特点,我们这边的项目因为一开始使用的是分布式开源调度框架TBSchedule,但是这个框架依赖ZK, 由于ZK的不稳定性和项目老旧无人维护 ,导致我们的定时任务会偶发出现异常,比如:任务停止、任务项丢失、任务不

    2024年02月14日
    浏览(43)
  • C++轻量级单元测试框架

    单元测试是构建稳定、高质量的程序、服务或系统的必不可少的一环。通过单元测试,我们可以在开发过程中及时发现和修复代码中的问题,提高代码的质量和可维护性。同时,单元测试也可以帮助我们更好地理解代码的功能和实现细节,从而更好地进行代码重构和优化。

    2023年04月25日
    浏览(71)
  • 108中超轻量级的加载动画!

    大家好,我是【程序视点】小二哥! 今天要上的菜不是 Animate.js,也不是 Move.js,而是能提供108种加载动画的库: Whirl . 话不多说,直接来看例子。 以上只是冰山一角。whirl的CSS加载动画集合中有108种选项供你挑选。选中喜欢的动画后,点击“Grab the CSS on Github!”。 将跳转到

    2024年02月03日
    浏览(51)
  • Kotlin 轻量级Android开发

    Kotlin 是一门运行在 JVM 之上的语言。 它由 Jetbrains 创建,而 Jetbrains 则是诸多强大的工具(如知名的 Java IDE IntelliJ IDEA )背后的公司。 Kotlin 是一门非常简单的语言,其主要目标之一就是提供强大语言的同时又保持简单且精简的语法。 其主要特性如下所示: 轻量级:这一点对

    2024年02月07日
    浏览(131)
  • 轻量级Web框架Flask(二)

    MySQL是免费开源软件,大家可以自行搜索其官网(https://www.MySQL.com/downloads/) 测试MySQL是否安装成功 在所有程序中,找到MySQL→MySQL Server 5.6下面的命令行工具,然后单击输入密码后回车,就可以知道MySQL数据库是否链接成功。 右击桌面上的“计算机”,在弹出的快捷键菜单中

    2023年04月15日
    浏览(66)
  • 一种轻量级websocket实现方案

    定义ws服务器工具类WsktUtil 开机启动ws服务器 测试结果 自定义一个WebSocketClient子类 测试连接ws服务器 测试效果

    2024年02月15日
    浏览(39)
  • volatile关键字(轻量级锁)

    目录 一、volatile出现背景 二、JMM概述 2.1、JMM的规定  三、volatile的特性 3.1、可见性  3.1.1、举例说明  3.1.2、总结 3.2、无法保证原子性 3.2.1、举例说明 3.2.2、分析 3.2.3、使用volatile对原子性测试  3.2.4、使用锁机制  3.2.5、总结 3.3、禁止指令重排序  四、volatile的内存语义 4

    2024年02月15日
    浏览(40)
  • Containerd【轻量级容器管理工具】

    Kubernetes v1.24 之前的版本直接集成了 Docker Engine 的一个组件,名为 dockershim [用于调用Docker]。 这种特殊的直接整合不再是 Kubernetes 的一部分 (这次删除被作为 v1.20 发行版本的一部分宣布)。 这意味Kubernetes从版本1.24开始就弃用Docker作为容器运行时,取而代之的是更加轻量级的

    2024年02月13日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包