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

2023-06-07 13:07:40 来源:博客园

打印 放大 缩小
背景

在分析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中

最后运行下

关键词:

责任编辑:ERM523

相关阅读

精彩推送

项目管理中,如何养成结构化表达习惯? 世界快资讯 焦点消息!欣旺达APS项目实施
当前消息!如果选择合适的企业数据防泄漏解决方案 Ping32文档透明加密,保护您的企业数据安全。
NixOS 与 Nix Flakes 新手入门 李湘教女儿高尔夫球,林志颖儿子玩赛车,有钱人的教育就是不一样
聊聊Cola-StateMachine轻量级状态机的实现_独家 168电影网_关于168电影网的介绍
环球精选!PDD直播与弹幕吵架,啃老言论惹争议,LOL行业巨头,成功激怒粉丝 “续航”和“亮相”二选一!2023年北京高考作文题公布_焦点短讯
回归巴萨之路被堵死!下一站梅西选多金沙特,还是小贝的迈阿密 【全球新视野】沙伊两国增信释疑 双边关系持续改善
国外最大的CSGO交易平台是哪个 最新CSGO饰品交易排行榜公布 腰痛宁胶囊多少钱一盒? 腰痛宁胶囊多少钱一盒
2023年6月7日江苏省醋酸丁酯价格最新行情预测 2023年6月7日河北省防水蜂窝活性炭价格最新行情预测
北京一考生走错考场,交警8分钟闪送! 环球动态 2023年6月7日山东省次氯酸钠价格最新行情预测
观点:2023年6月7日山东省氢氧化钙价格最新行情预测 世界快资讯丨张字甲骨文到楷体的演变 张字的演变过程从甲骨文到楷书表格
【全球独家】2023年6月7日正十五烷价格最新行情预测 2023年6月7日山东省玉米淀粉价格最新行情预测-环球报资讯
2023年6月7日安徽省环己胺价格最新行情预测|动态焦点 2023年6月7日江苏省小苏打价格最新行情预测|热资讯
2023年6月7日安徽省环己酮价格最新行情预测 精选!蜜蜂教学设计
东亚机械:6月6日融资买入187.61万元,融资融券余额3833.8万元-环球观点 德尔玛:6月6日融资买入1641.31万元,融资融券余额4832.01万元
诺思格:6月6日融资买入139.89万元,融资融券余额1315.5万元-全球观焦点 全球今日讯!北向资金半日净买入27.77亿元
天振股份:6月6日融资买入178.83万元,融资融券余额4441.85万元 华人健康:6月6日融资买入425.33万元,融资融券余额4294.9万元_最资讯
每日消息!矩阵股份:6月6日融资净买入202.55万元,连续3日累计净买入456.33万元 18只个股上午主力净流入超1亿元 华工科技居首
报道:午评:沪指震荡微涨,旅游、传媒等板块拉升,CPO概念等活跃 趣睡科技:6月6日融资买入172.23万元,融资融券余额2335.17万元 世界热点评
熵基科技:6月6日融资买入2049.05万元,融资融券余额1.22亿元 世界消息 环球最资讯丨德尔玛:6月6日融资买入1641.31万元,融资融券余额4832.01万元
荣旗科技:6月6日融资买入1921.56万元,融资融券余额4046.62万元 信息:武汉当代:决定对“20当代01”展期
众智科技:6月6日融资买入2695.06万元,融资融券余额5339.31万元 每日快报!东方铁塔:中标9129.78万元国家电网采购项目
养肺清肺最好的食物(养肺的最好方法)_每日视点 原创组图 | 海南三亚:考生冒雨赶考
北京电信多条千兆专线护航通信展览会 全力做好通信保障服务 速看 乱象丛生!这些网上健康咨询的“坑”你遇到过吗?
环球滚动:吉网高考现场丨亲友团“花式”送考:愿你鱼跃龙门,一举夺魁! 今头条!cf手游王者轮回抽完要多少钱
贵州“村超”负责人表示,以后邀请外地人参加 每日观察!吉林省企业团组参加韩国国际食品展收获颇丰
世界微动态丨海南加强监督检查、优化服务保障 维护考试公平公正 热点在线丨人为什么会做梦预知未来某些片段(人为什么会做梦中梦)
苹果新专利获批,iPhone顶部和侧面引入物理指纹识别 北京市2023年06月07日10时35分发布大风蓝色预警信号
英伟达RTX 40 SUPER系显卡曝光:显存带宽均升级|当前通讯 高考首日开考!衡阳 5万多名考生走上高考考场
全球动态:华为正式发布全球首款800GE数据中心核心交换机 乌军反攻失败?绍伊古:乌5个旅从7个方向进攻,损失超1600人后放弃,俄军71人丧失
中超前瞻:成都PK津门虎谁保不败金身 泰山客战三镇目标复仇-重点聚焦 记者:别无选择,梅西需要耐心等待,球迷:巴萨耍流氓
当前视点!三国吕布被曹操处死前大喊,这6个字为何让刘备听了尴尬 古代嫔妃畏惧冷宫,为何太监们却抢着进冷宫当差,此差事好在哪? 世界热推荐
【天天热闻】6月7日金市早评:全球经济预期今年将上调 黄金弱势震荡 全球观察:首航新能源重拳出击,光储市场迎来技术变革
加拿大野火持续蔓延 烟雾笼罩首都渥太华 实时焦点 pictures是什么意思 翻译_pictures是什么意思 世界今热点
中国石油多项排放量持续减少 新能源开发利用能力达800万吨标煤/年-环球聚看点 郭碧婷带娃变得这么憔悴了?穿休闲装梳马尾太邋遢,都不敢认了|世界今头条
高考第一天作息依旧,衡水中学考生6点集体跑操,早晚自习正常进行|快看 【全球速看料】日本计划到2030年普及柔性太阳能电池板
被指控操纵比赛 梁文博等10名中国斯诺克球员被判禁赛 今日最新!涉及年产60万吨石英砂等光伏项目 关于2023年陕南发展专项资金项目的公示
黛西法罗DAISY FELLOWES:时尚界的新宠儿,在上海时装周上闪耀登场! 美联储通胀持续存在 黄金区间震荡依旧
药师帮通过港交所上市聆讯 “营销及推广费用”收缩至15% 消费者需警惕网络美容消费陷阱
5G已融入超六成国民经济大类 当前播报:儿童青少年眼健康引关注 “政校研企”共同探讨近视防控之道
16省份公布去年平均工资,这个行业亮了 太湖能谷与新凤鸣、信达电子正式签署用户侧储能及绿电服务合作协议_世界报资讯
日均不到10单,多地对网约车按下“暂停键” 喷雾、菜刀、电池……特殊商品如何“七天无理由退货”?_当前热门
王楼乡多措并举做好“三夏”工作 天天动态 对中国F1车手周冠宇使用歧视性词汇,英国天空体育道歉
在深打工,但医保不在这,能参保吗?|世界快消息 焦点要闻:常州机场:6月11日 机场新增九寨沟航线
前5月403家首店落户京城 常州市场监管局:常州两部门发布2023年高考中考期间食品安全提示
每日报道:中方:日方核污水排海计划极不负责任 最资讯丨北京榜样5月月榜
世行上调中国2023年经济增速预期至5.6%-天天热闻 东湖评论:对“按键伤人”的行为坚决“亮剑”
世界报道:南通开发区昔日用水大户的绿色蝶变 世界速读:淮安市教育局顺利完成省中小学生实验知识竞赛各项工作
苹果向所有用户免费开放iOS 17、watchOS 10等开发者测试版 即插即用,iPadOS 17 新增支持外置 USB-C 摄像头
淮安区:全面落实惠企政策 降低企业经营成本 缪志春同志现场检查督导演唱会安保工作
全球今亮点!马来西亚拟对2007年后出生公民全面禁烟 今日报丨眼病应早筛查早诊治 多项义诊讲座等你来