阿里状态机引擎实现

状态机的技术选型看这篇就够了,最后一个直叫好! - 掘金

实现一个状态机引擎,教你看清DSL的本质_cola状态机-CSDN博客

一、引入jar包

<!--阿里状态机jar-->
<dependency><groupId>com.alibaba.cola</groupId><artifactId>cola-component-statemachine</artifactId><version>4.3.2</version>
</dependency>        

二、引入流转类型枚举

package com.lx.designPattern.statepattern.statemachine.enums;/*** 流转类型枚举* @author lwp* @date 2023-07-06 14:56:27* @version 1.0*/
public enum TransitionTypeEnum {/*** 内部流转*/INTERNAL,/*** 外部流转*/EXTERNAL,/*** 多状态外部流转*/EXTERNALS;
}

三、引入事件枚举

package com.lx.designPattern.statepattern.statemachine.enums;/*** 履约状态事件枚举** @author lwp* @version 1.0* @date 2023-07-06 13:40:11*/
public enum FulfillmentStatusEventEnum {/*** 开始租赁非标商品履约*/BEGIN_RENT_NON_STANDARD_GOODS_FULFILLMENT,/*** 完成资源匹配*/MATCH_RESOURCE,/*** 完成租赁交付*/COMPLETE_RENT_DELIVER,/*** 重置履约计划*/RESET_FULFILLMENT,/*** 取消履约单*/CANCEL_FULFILLMENT,/*** 创建售车交付履约单*/CREATE_SALE_DELIVER_FULFILLMENT,/*** 完成服务执行中*/COMPLETE_SERVICE_FULFILLMENT,/*** 非灰度履约单交付*/NON_GRAY_DELIVER,/*** 欢乐租备车*/HAPPY_RENT_PLAN_CAR,/*** 开始替换车履约*/START_REPLACE_DELIVER_FULFILLMENT,/*** 开始常规租赁退车履约*/START_RENT_BACK_CAR_FULFILLMENT,/*** 完成替换车车退车*/COMPLETE_REPLACE_BACK_CAR_FULFILLMENT,/*** 完成租赁退车*/COMPLETE_RENT_BACK_CAR_FULFILLMENT,/*** 取消履约 (新的)*/CANCEL_FULFILLMENT_2ND,/*** 完成服务履约*/COMPLETE_VEHICLE_SERVICE,/*** 渠道商履约*/CHANNEL_FULFILLMENT,;
}

四、引入流转状态枚举

package com.lx.designPattern.statepattern.statemachine.enums;import com.lx.exception.BusinessException;import java.util.Objects;/*** 履约单状态枚举* @author lwp* @date 2023/1/5 9:16* @version 1.0*/
public enum FulfillmentStatusEnum {/*** 初始状态*/INITIAL(0, "初始状态"),/*** 待匹配*/WAIT_MATCH(2, "待匹配"),/*** 进行中*/IN_PROGRESS(3, "进行中"),/*** 已完成*/COMPLETED(4, "已完成"),/*** 已取消*/CANCELED(5, "已取消"),;private Integer status;private String desc;FulfillmentStatusEnum(Integer status, String desc) {this.status = status;this.desc = desc;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}public static FulfillmentStatusEnum getByStatus(Integer status) {for (FulfillmentStatusEnum fulfillmentStatusEnum : FulfillmentStatusEnum.values()) {if (Objects.equals(status, fulfillmentStatusEnum.getStatus())) {return fulfillmentStatusEnum;}}throw new BusinessException("未找到履约状态枚举");}
}
 1.需要处理的业务参数类
package com.lx.designPattern.statepattern.statemachine.dto;import lombok.Data;/*** 履约单dto* @author lwp* @date 2023-07-25 16:22:04* @version 1.0*/
@Data
public class FulfillmentBillDTO {/*** 交易订单*/private A a;/*** 履约主单*/private B b;/*** 车辆履约子单*/private C c;
}

五、准备状态机

package com.lx.designPattern.statepattern.statemachine;import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.builder.StateMachineBuilder;
import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory;
import com.lx.designPattern.statepattern.statemachine.statustransition.FulfillmentStatusTransition;
import com.lx.designPattern.statepattern.statemachine.dto.FulfillmentBillDTO;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEnum;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEventEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.List;/*** 履约状态机** @author lwp* @version 1.0* @date 2023-07-27 10:31:27*/
@Slf4j
@Lazy
@Component
public class FulfillmentStatusStateMachine {/*** 状态机ID*/private static final String MACHINE_ID = "FulfillmentStatusStateMachine";/*** 状态机*/private StateMachine<FulfillmentStatusEnum, FulfillmentStatusEventEnum, FulfillmentBillDTO> stateMachine;@Autowiredprivate List<FulfillmentStatusTransition> fulfillmentStatusTransitions;/* ******************************* 履约单状态流转 *****************************//*** 初始化*/@PostConstructpublic void init() {// 创建状态机StateMachineBuilder<FulfillmentStatusEnum, FulfillmentStatusEventEnum, FulfillmentBillDTO> stateMachineBuilder= StateMachineBuilderFactory.create();// 添加没有命中配置规则时的回调stateMachineBuilder.setFailCallback(this::stateMachineFailCallback);// 初始化transitioninitTransition(stateMachineBuilder);stateMachine = stateMachineBuilder.build(MACHINE_ID);}/*** 触发流转*/public FulfillmentStatusEnum fireEvent(FulfillmentStatusEnum status,FulfillmentStatusEventEnum event,FulfillmentBillDTO fulfillmentBill) {FulfillmentStatusEnum resultStatus = stateMachine.fireEvent(status, event, fulfillmentBill);// 如果结果状态和源状态相同,代表流转失败if (resultStatus == status) {log.warn("履约单{}状态流转失败, from:{}, to:{}, event:{}",fulfillmentBill.getMainFulfillmentBill().getFulfillmentCode(),status.getStatus(),resultStatus.getDesc(),event);} else {log.info("履约单{}状态流转, from:{}, to:{}, event:{}",fulfillmentBill.getMainFulfillmentBill().getFulfillmentCode(),status.getStatus(),resultStatus.getDesc(),event);}return resultStatus;}/*** 没有命中配置规则时的回调*/private void stateMachineFailCallback(FulfillmentStatusEnum status,FulfillmentStatusEventEnum event,FulfillmentBillDTO fulfillmentBill) {log.error("履约单{}状态流转失败: 未找到匹配的流转规则, from:{}, event:{}",fulfillmentBill.getMainFulfillmentBill().getId(),status.getDesc(),event);}/*** 初始化transition*/private void initTransition(StateMachineBuilder<FulfillmentStatusEnum, FulfillmentStatusEventEnum,FulfillmentBillDTO> builder) {fulfillmentStatusTransitions.forEach(transition -> {switch (transition.getTransitionType()) {case INTERNAL:if (transition.getWithin().isPresent()) {builder.internalTransition().within(transition.getWithin().get()).on(transition.getEvent()).when(transition.getCondition()).perform(transition.getAction());} else {log.error("初始化履约单内部状态流转错误: 缺少within参数");throw new IllegalArgumentException("履约状态状态机初始化失败");}break;case EXTERNAL:if (transition.getFrom().isPresent() && transition.getTo().isPresent()) {builder.externalTransition().from(transition.getFrom().get()).to(transition.getTo().get()).on(transition.getEvent()).when(transition.getCondition()).perform(transition.getAction());} else {log.error("初始化履约单外部状态流转错误: 缺少from或to参数");throw new IllegalArgumentException("履约状态状态机初始化失败");}break;case EXTERNALS:if (transition.getFromAmong().isPresent() && transition.getTo().isPresent()) {builder.externalTransitions().fromAmong(transition.getFromAmong().get()).to(transition.getTo().get()).on(transition.getEvent()).when(transition.getCondition()).perform(transition.getAction());} else {log.error("初始化履约单多状态外部状态流转错误: 缺少fromAmong或to参数");throw new IllegalArgumentException("履约状态状态机初始化失败");}break;default:log.error("不支持的流转类型:{}", transition.getTransitionType());}});}
}

六、准备流转接口

package com.lx.designPattern.statepattern.statemachine.statustransition;import com.alibaba.cola.statemachine.Action;
import com.alibaba.cola.statemachine.Condition;
import com.lx.designPattern.statepattern.statemachine.dto.FulfillmentBillDTO;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEnum;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEventEnum;
import com.lx.designPattern.statepattern.statemachine.enums.TransitionTypeEnum;import java.util.Optional;/*** 履约单状态流转* @author lwp* @date 2023-07-06 15:08:18* @version 1.0*/
public interface FulfillmentStatusTransition {/*** 获取类转类型* @return 流转类型*/TransitionTypeEnum getTransitionType();/*** 获取within参数(内部流转必需)* @return within*/default Optional<FulfillmentStatusEnum> getWithin() {return Optional.empty();}/*** 获取from参数(外部流转必需)* @return from*/default Optional<FulfillmentStatusEnum> getFrom() {return Optional.empty();}/*** 获取fromAmong参数(多状态外部流转必需)* @return fromAmong*/default Optional<FulfillmentStatusEnum[]> getFromAmong() {return Optional.empty();}/*** 获取to参数(外部流转和多状态外部流转必需)* @return to*/default Optional<FulfillmentStatusEnum> getTo() {return Optional.empty();};/*** 获取event* @return on参数*/FulfillmentStatusEventEnum getEvent();/*** 获取condition* @return when*/Condition<FulfillmentBillDTO> getCondition();/*** 获取action* @return preform*/Action<FulfillmentStatusEnum, FulfillmentStatusEventEnum, FulfillmentBillDTO> getAction();
}

七、实现流转接口和定义流转规则

package com.lx.designPattern.statepattern.statemachine.statustransition;import com.alibaba.cola.statemachine.Action;
import com.alibaba.cola.statemachine.Condition;
import com.lx.designPattern.statepattern.statemachine.dto.FulfillmentBillDTO;
import com.lx.designPattern.statepattern.statemachine.dto.MainFulfillmentBill;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEnum;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEventEnum;
import com.lx.designPattern.statepattern.statemachine.enums.TransitionTypeEnum;
import org.springframework.stereotype.Component;import java.util.Optional;/*** 完成履约状态流转* @author lwp* @date 2023-07-12 10:30:32* @version 1.0*/
@Component
public class CompleteFulfillmentTransition implements FulfillmentStatusTransition {//@Autowired//private FulfillmentBillDaoService fulfillmentBillDaoService;@Overridepublic TransitionTypeEnum getTransitionType() {return TransitionTypeEnum.EXTERNAL;}@Overridepublic Optional<FulfillmentStatusEnum> getFrom() {return Optional.of(FulfillmentStatusEnum.IN_PROGRESS);}@Overridepublic Optional<FulfillmentStatusEnum> getTo() {return Optional.of(FulfillmentStatusEnum.COMPLETED);}@Overridepublic FulfillmentStatusEventEnum getEvent() {return FulfillmentStatusEventEnum.COMPLETE_RENT_DELIVER;}@Overridepublic Condition<FulfillmentBillDTO> getCondition() {return (fulfillmentBillDTO -> true);}@Overridepublic Action<FulfillmentStatusEnum, FulfillmentStatusEventEnum, FulfillmentBillDTO> getAction() {return (srcState, tarState, event, fulfillmentBillDTO) -> {// 修改履约单状态MainFulfillmentBill updateMainBill = new MainFulfillmentBill();updateMainBill.setId(fulfillmentBillDTO.getMainFulfillmentBill().getId());updateMainBill.setStatus(tarState.getStatus());//fulfillmentBillDaoService.updateMainBillById(updateMainBill);System.out.println("状态改为完成了");};}
}

八、准备测试类测试

package com.lx.designPattern;import com.lx.designPattern.statepattern.statemachine.FulfillmentStatusStateMachine;
import com.lx.designPattern.statepattern.statemachine.business.InsuranceStatusChangeServiceImpl;
import com.lx.designPattern.statepattern.statemachine.dto.FulfillmentBillDTO;
import com.lx.designPattern.statepattern.statemachine.dto.MainFulfillmentBill;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEnum;
import com.lx.designPattern.statepattern.statemachine.enums.FulfillmentStatusEventEnum;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;/*** @Desc 阿里状态机测试类* @author lwp* @version 1.0* @date 2024-01-13 22:16:22*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "dev")
public class StateMachineTest {@Autowiredprivate FulfillmentStatusStateMachine fulfillmentStatusStateMachine;@Testpublic void handStatusChangeComplete() {FulfillmentBillDTO billDTO = new FulfillmentBillDTO();MainFulfillmentBill mainFulfillmentBill = new MainFulfillmentBill();mainFulfillmentBill.setFulfillmentCode("LY001");mainFulfillmentBill.setStatus(1);billDTO.setMainFulfillmentBill(mainFulfillmentBill);fulfillmentStatusStateMachine.fireEvent(FulfillmentStatusEnum.getByStatus(3),FulfillmentStatusEventEnum.COMPLETE_RENT_DELIVER,billDTO);}}

 九、测试效果如下图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/620634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go定时器

Go语言定时器简介 Go语言的定时器是一个非常强大的工具&#xff0c;它可以帮助我们轻松地实现各种定时任务和超时控制。定时器算法的原理也很简单&#xff0c;它是一种基于时间轮算法实现的。 Go语言定时器原理 Go语言的定时器是基于时间轮算法实现的&#xff0c;时间轮算法…

python期末考试:控制语句

第3章 控制语句 1. 以下关于 Python 的控制结构&#xff0c;错误的是&#xff08; &#xff09;。 A. 每个 if 条件后要使用冒号&#xff08;&#xff1a;&#xff09; B. 在 Python 中&#xff0c;没有 switch-case 语句 C. Python 中的 pass 是空语句&#xff0c;一般用作…

ChatGPT绘画生成软件MidTool:智能艺术的新纪元

在人工智能的黄金时代&#xff0c;创新技术不断涌现&#xff0c;改变着我们的生活和工作方式。其中&#xff0c;ChatGPT绘画生成软件MidTool无疑是这一变革浪潮中的佼佼者。它不仅是一个软件&#xff0c;更是一位艺术家&#xff0c;一位智能助手&#xff0c;它的出现预示着智能…

大创项目推荐 深度学习疲劳检测 驾驶行为检测 - python opencv cnn

文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习加…

AWS Directory Service 开启ldaps

启用客户端 LDAPS 要启用客户端 LDAPS&#xff0c;您需要将证书颁发机构&#xff08;CA&#xff09;证书导入 AWS Managed Microsoft AD&#xff0c;然后在目录上启用 LDAPS。启用后&#xff0c;AWS 应用程序与您自行管理的 Active Directory 之间的所有 LDAP 通信将通过安全套…

虚拟机配置固定IP

1.DHCP 当前我们虚拟机的Linux操作系统&#xff0c;其IP地址是通过DHCP服务获取的。 DHCP&#xff1a;动态获取IP地址&#xff0c;即每次重启设备后都会获取一次&#xff0c;可能导致IP地址频繁变更&#xff0c;这就会给我们带来不方便&#xff0c;因为如果我们每次重启设备都…

2024年AMC8模拟考试实测流程、注意事项和常见问题

和往年的AMC8比赛一样&#xff0c;在正式比赛的前一周左右会开放两天的模拟考试时间&#xff0c;AMC8的主办方建议所有的参赛选手重视且参加模拟考试&#xff0c;以测试设备、熟悉流程&#xff0c;避免将来正式考试不小心违规&#xff0c;或者设备不给力。 2024年的AMC8模拟考…

线性代数——(期末突击)概率统计习题(概率的性质、全概率公式)

目录 概率的性质 题一 全概率公式 题二 题三 概率的性质 有限可加性&#xff1a; 若有限个事件互不相容&#xff0c;则 单调性&#xff1a; 互补性&#xff1a; 加法公式&#xff1a; 可分性&#xff1a; 题一 在某城市中共发行三种报纸&#xff1a;甲、乙、丙。在这个…

Flutter之运行错误:Error: Member notfound: ‘SystemChrome .setEnabledSystemuIOverlays‘

项目由于引入的包导致报错&#xff1a; Error: Member notfound: SystemChrome .setEnabledSystemuIOverlays 主要原因是因为包里的方法有变动。 解决办法&#xff1a; 将AppDate\Local\Pub\Cache\hosted\pub.dev\r_scan-0.1.61\lib\src\r_scan_view.dart文件中的 原方法&am…

使用内网穿透与Termux完成手机上部署web项目

1.开发环境&#xff1a;安卓9&#xff0c;termux&#xff0c;python3.11&#xff0c;cpolar 2.步骤&#xff1a; 2.1先实现内网访问&#xff0c;之后再尝试内网穿透 安装Termux&#xff1a; Termux是一个在Android上运行的终端模拟器&#xff0c;它提供了一个Linux-like环境…

设计模式——1_4 外观(Facade)

文章目录 定义图纸一个例子&#xff1a;自动生成一杯茶沏茶的流程组合方式一&#xff1a;直接组合方法二&#xff1a;外观 碎碎念多个外观对象外观和封装外观和单例姑妄言之 定义 为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这…

【120版本】最新谷歌浏览器驱动下载地址

在使用selenium时可能会遇到谷歌浏览器和谷歌驱动器版本不一致的问题&#xff0c;并且国内可以搜到的谷歌浏览器下载地址里面最新的驱动器只有114版本的&#xff0c;但目前谷歌浏览器最新版本是120。所以这里记录下最新版本120谷歌驱动器下载地址&#xff1a; Chrome for Test…

Dobbo---分布式系统通信方式

通信方式 分布式系统通信方式1. RMIRMI 通信实现案例2. RPC常用RPC框架 分布式系统通信方式 1. RMI RMI ( Remote Method Invocation 远程方法调用) 图1.1 客户端-服务端通信方式 客户端将要调用的方法及参数&#xff0c;打包为辅助对象&#xff0c;通过网络socket&#xff…

【自控实验】3. 带有饱和非线性环节控制系统相平面分析

本科课程实验报告&#xff0c;有太多公式和图片了&#xff0c;干脆直接转成图片了 仅分享和记录&#xff0c;不保证全对 实验内容&#xff1a; 有无非线性环节的相轨迹对比&#xff0c;并求超调量。 在输入单位阶跃信号Xsr时&#xff0c;用示波器观察和记录系统输入饱和非线…

融资项目——EasyExcel操作Excel文件

EasyExcel是Alibaba集团开源的EasyExcel技术&#xff0c;该技术是针对Apache POI技术的封装和优化&#xff0c;主要解决了POI技术的耗内存问题&#xff0c;并且提供了较好的API使用。不需要大量的代码就可以实现excel的操作功能。 1.EasyExcel的配置 首先引入依赖&#xff0c;…

Hadoop-HA高可用

一、集群规划 二、HDFS高可用 官方地址 在opt目录下创建一个ha文件夹&#xff0c;将/opt/module/下的 hadoop-3.1.3拷贝到/opt/ha目录下&#xff08;记得删除data 和 log目录&#xff09; 配置core-site.xml hdfs-site.xml <configuration><!-- NameNode数据存…

记一次数据修复,需要生成十万条sql进行数据回滚

一、背景 数据回滚 二、难点 2.1 需要处理的数据涉及多达数万个用户&#xff0c;每个用户涉及的表达到10个 2.2 时间紧急&#xff0c;需要快速回滚,数据需要完整 2.3 数据存在重复或空缺问题 三、解决方案 3.1 数据多&#xff0c;使用分批处理&#xff0c;把大任务分割成若…

个人网站制作 Part 4 添加响应式设计 | Web开发项目

文章目录 &#x1f469;‍&#x1f4bb; 基础Web开发练手项目系列&#xff1a;个人网站制作&#x1f680; 添加响应式设计&#x1f528;移动优先的响应式样式&#x1f527;步骤 1: 添加媒体查询 &#x1f528;图片和布局调整&#x1f527;步骤 2: 使用响应式图片&#x1f527;步…

如何使用网络测试仪构造特殊流量

为什么要仿真特殊流量 在现网中&#xff0c;网络流量时常伴随着突发&#xff0c;突发流量可能会造成网络的拥塞&#xff0c;从而产生丢包、抖动和时延&#xff0c;导致网络服务质量整体下降。面对宏观上的突发&#xff0c;通常采用在网络设备入向限速或者流量整形功能来消除突…

数据结构-无向图(C++)

文章目录 对称矩阵构造与析构下标访问的实现输入输出删除行列插入行列 无向图数据结构构造与析构图的顶点数特殊顶点的操作查找顶点第i个顶点的第1个邻接顶点第i个顶点的下一个邻接顶点 插入顶点删除顶点输入与输出 采用形式化的定义&#xff0c;图 G G G由两个集合 V V V和 E …