首页 >分析 > > 正文

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

博客园 2023-06-07 11:42:56
背景

在分析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链路图业务应用示例

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

关闭订单的简单流程图

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

添加依赖

    com.alibaba.cola    cola-component-statemachine    4.3.1

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

@Data@Builderpublic 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;    }}

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

@Componentpublic class StateMachineBuilderConfig {    @Autowired    UserCloseAction userCloseAction;    @Bean("orderOperaMachine")    public StateMachine orderOperaMachine() {        String ORDER_OPERA = "order_opera";        StateMachineBuilder 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 checkCondition() {        return (ctx) -> {            return true;        };    }    private Action doAction() {        return (from, to, event, ctx) -> {            System.out.println(ctx.getOrderName() + " 正在操作 " + ctx.getOrderId() + " from:" + from + " to:" + to + " on:" + event);        };    }}

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

@Componentpublic class UserCloseAction implements Action {    @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 的操作接口

@RestControllerpublic class OrderOperaController {    @Autowired    @Qualifier("orderOperaMachine")    StateMachine 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;    }}

启动程序

安装UML

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

最后运行下

上一篇:全球观点:淮滨县多方联动全力抢收75万亩弱筋小麦确保夏粮颗粒归仓 下一篇:最后一页
x
推荐阅读

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

2023-06-07

全球观点:淮滨县多方联动全力抢收75万亩弱筋小麦确保夏粮颗粒归仓

2023-06-07

凹凸世界凯莉被雷狮吸一晚_雷狮大猫猫是什么梗凹凸世界雷狮为什么被叫做大猫猫

2023-06-07

联想发布新品,持续加码商用PC市场

2023-06-07

吉林珲春进口百万吨煤炭产业园项目竣工_环球信息

2023-06-07

世界速看:75岁知名富豪再度当爸,娇妻成功怀上三胎,直言不为钱只为爱情

2023-06-07

金箍棒全程_完美金箍棒 世界快看点

2023-06-07

暖心!张家界机场为高考生再次开启“空中静音”模式_天天快消息

2023-06-07

全球热消息:安德烈·吉申科

2023-06-07

小孩子有必要购买重疾险吗?小孩子可以买哪种重疾险?

2023-06-07

项羽自刎乌江的图片_项羽自刎乌江在哪里

2023-06-07

交大昂立或面临退市风险!现任管理层回应年报“难产”:前任管理层严重损害上市公司利益-动态焦点

2023-06-07

全款房没有房产证怎么贷款

2023-06-07

荆州站北站房钢结构屋盖网架完成首次提升|热资讯

2023-06-07

小非农是什么时候_小非农是什么 环球观焦点

2023-06-07

华洋赛车6月13日北交所首发上会 拟募资4.8亿元 头条焦点

2023-06-07

全球视讯!宏达电5月营收3.59亿元新台币 同比增长18.28%

2023-06-07

观速讯丨少得意忘形了动图女优_得意忘形什么意思

2023-06-07

日本文化厅:公开销售AI生成物可构成侵权

2023-06-06

【天天热闻】全国总工会启动关爱货车司机行动

2023-06-06

2023广东韶关市乳源瑶族自治县“青年人才”暨事业单位人员招聘(事业单位人员岗位)拟聘用公示(第一批)

2023-06-06

汉滨区关家镇洛河村扶贫互助协会_关于汉滨区关家镇洛河村扶贫互助协会简述|环球信息

2023-06-06

新疆阿瓦提县:沤制绿肥助力林果业提质增效 环球视点

2023-06-06

A股收评:沪指跌超1%再度失守3200点 房地产产业链个股再度活跃

2023-06-06

环球新消息丨驻马店市第九中学举行经典诵读活动

2023-06-06

全球今日报丨L‘OCCITANE(00973)5月转拨5.64万股库存股

2023-06-06

全球关注:大牛股跌去80%,实控人夫妇财富缩水170亿!什么原因?

2023-06-06

京投发展(600683)龙虎榜数据(06-06)

2023-06-06

死诸葛亮吓走活仲达阅读感想_死诸葛亮吓走活仲达

2023-06-06

售价约2.5万元!苹果首款头显Vision Pro开启空间计算时代

2023-06-06

榆木圪垯和榆木疙瘩盆栽_榆木圪垯

2023-06-06

2023新乡端午节放假通知 2023新乡端午节放假通知图片 天天热文

2023-06-06

减产利好程度有限 当前滚动

2023-06-06

【全球独家】减肥神药调查②跨国巨头与本土药企激战百亿减肥市场,谁能拔得头筹

2023-06-06

海报|世界环境日:理一份“减塑”清单_观速讯

2023-06-06

试用转正定级自我鉴定

2023-06-06

无线鼠标多少钱比较合适(无线鼠标多少钱)

2023-06-06

昔日千亿房企走到退市边缘,老板是他

2023-06-06

缅甸仰光发生一起爆炸 致6人受伤

2023-06-06

陈情表必考重点句子_陈情表重点句子翻译 焦点要闻

2023-06-06

程远凤:奉献在基层当好贴心人

2023-06-06

qq语音怎么变声器_手机qq语音变声器 每日关注

2023-06-06

菏泽职业学院占地面积多少平方米(菏泽职业学院占地面积)

2023-06-06

怎样系鞋带好看又简单慢教程_怎样系鞋带好看_当前热点

2023-06-06

王欣瑜/谢淑薇晋级法网女双八强

2023-06-06

支持阳泉市盂县智慧寄递物流建设项目

2023-06-05

享受在家玩耍/工作的感觉 这些显示器是你的首选

2023-06-05

当前视讯!北京儿童阅读月首场活动在北京图书大厦举办

2023-06-05

视讯!没有想到,一套古装,就将明星们现代装的美貌撕得粉碎

2023-06-05

2023端午天津峰山药王古寺地址_消息

2023-06-05

宿迁移动与启明星辰达成战略合作-今日热议

2023-06-05

人生有幸一定要朝圣世界极光之都 最清澈星空、一年有8个月可以追极光! 全球今头条

2023-06-05

鸿博股份涨停

2023-06-05

无广告小说类软件推荐

2023-06-05

今起,开放冷风!_世界速看料

2023-06-05

世界速读:申港证券给予比亚迪买入评级 公司点评:5月销量创历史新高腾势连续破万

2023-06-05

第四届武汉儿童戏剧节渐入佳境,34场演出等你来看!|全球观速讯

2023-06-05

公司问答 | 彩蝶实业:关于碳中和方面公司尚未涉及_环球滚动

2023-06-05

《塞尔达传说王国之泪》戒心长刀获取攻略

2023-06-05

数学教学设计:找规律

2023-06-05

一问到底丨载人登月发展,动力如何先行?-世界快资讯

2023-06-05

“无限服务”金名片,徐工塔机携手客户共筑安全防线_天天热闻

2023-06-05

每日快讯!地震横波和纵波的图像_地震波横波纵波图示

2023-06-05

6月5日生意社环己酮基准价为9262.50元/吨|今日热讯

2023-06-05

世界观焦点:香港旅发局:今年前5月访港旅客突破千万人次

2023-06-05

小九寨沟珠海_小九寨

2023-06-05

骆驼祥子好词好句摘抄及感悟_骆驼祥子好词 世界看点

2023-06-05

于月仙个人资料_于月仙个人简介_当前焦点

2023-06-05

世界观热点:设置了分隔符怎么让页码连续_word分隔符后页码连续

2023-06-05

每日热讯!鲈鱼和桂鱼哪个贵一点

2023-06-04

每日聚焦:男子团购10斤小龙虾称重仅5斤详细内容

2023-06-04

2023年6月湖南三板企业市值TOP100:9家企业去年净利润超3000万元

2023-06-04

青苹果影院mp3_青苹果播放器-焦点短讯

2023-06-04

中甲:苏祖绝平!杨浩点球难救主!广州1-1济南兴洲,连续8轮不胜|焦点信息

2023-06-04

小米随身wifi驱动官方下载电脑版(小米随身)

2023-06-04

全球时讯:孕妇吃什么降火_孕妇上火了吃什么降火最快

2023-06-04

中国星辰 | “出差”半年 神十五乘组科学实验创多个“首次”|热头条

2023-06-04

最新消息:飞利浦电视机服务电话

2023-06-04

IT'S TiME此刻,智未来 一汽丰田2023款亚洲狮 超越“级”限 智焕新生|快报

2023-06-04

天天讯息:新闻特写:“延安我把你追寻”革命后代回延安

2023-06-04

建设人与自然和谐共生的现代化 聚看点

2023-06-04

焦点消息!混合现实行业深度报告:MR能否成为下一个爆款?

2023-06-04

最美儿童文学读本—《夏天里的苹果梦》_对于最美儿童文学读本—《夏天里的苹果梦》简单介绍

2023-06-04

福建推出高考考点分钟级天气预报和交管信息服务

2023-06-04

【世界新要闻】漂亮朋友作者是谁_漂亮朋友作者是莫泊桑

2023-06-04

焦点热讯:第三十三篇(1209字)

2023-06-04

源远流长同义词_源远流长的近义词-焦点播报

2023-06-04

六年级语文教学工作计划第一学期_六年级语文教学工作计划 当前视讯

2023-06-04

多路段临时封闭!未来12小时降水持续!西安紧急连发多项预警

2023-06-04

牧原股份:下半年公司养殖成本预计将保持下降趋势

2023-06-04

中超-科维奇梅开二度救主 河南队2-1逆转梅州客家

2023-06-03

长沙小吃一条街坡子街(长沙小吃一条街)_天天播报

2023-06-03

2023中考怎么样才能考好 怎么才能逆袭

2023-06-03

青海省人民代表大会常务委员会任命名单(2023年6月2日青海省第十四届人民代表大会常务委员会第二次会议通过)|报道

2023-06-03

环球百事通!凝聚正蓝支持 胡志强现身帮侯友宜背书

2023-06-03

Mysteel调研:东北钢厂新增四条线材轧机停产

2023-06-03

每日快讯!快手小店能开通2次吗?入驻要求有哪些?

2023-06-03

“绿动青岛·太平山打卡健步行”活力开启 探寻“公园城市”美好_每日报道

2023-06-03

【数说经济】抓住恢复和扩大需求这个关键_世界快看点

2023-06-03

泡泡龙传奇_泡泡龙瞄准器_每日快讯

2023-06-03