COLA statemachine 状态机引入实战

位置:首页>文章>详情   分类: 教程分享 > Java教程   阅读(163)   2024-04-02 15:01:29

Java 编程语言中,状态机主要有这几个 spring statemachine  、squirrel-foundation  、COLA-component-statemachine  调研后发现前两个都是有状态的,需要持久化,考虑到目前项目的复杂性选择了阿里开源的无状态状态机组件,下面是cola-component-statemachine 实战。

 

状态机主要解决问题是:

  • 多段的if else if... 
  • 同一个方法体内长篇审批逻辑...非常不便于维护

 

引入依赖

maven 参考:

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

 

案例

使用状态机管理一个简单的审批流程状态。

首先定义了一个状态机基础抽象,用于后续规范其他状态机

/**
 * 通用基础设定及方法
 * @param <S> 状态枚举/类
 * @param <E> 事件枚举/类
 * @param <C> 上下文数据对象
 */
public interface BaseMachine<S,E,C> {

    /**
     * 获取状态机id
     */
    String getMachineId();

    /**
     * 激活某个事件
     *
     * @param status  状态枚举
     * @param event   事件
     * @param context 上下文参数
     */
    default S fire(S status, E event, C context) {
        String machineId = getMachineId();
        StateMachine<S, E, C> objectObjectObjectStateMachine = StateMachineFactory.get(machineId);
        return objectObjectObjectStateMachine.fireEvent(status, event, context);
    }
}

 

然后定义审批的状态和事件

需要注意的是状态不等于事件,但是名称又往往相似

状态:

@Getter
public enum ComStates {

    PENDING_SUBMIT(0,"待提审"),
    AUDITING(2,"审核中(单/多人)"),
    SUCCESS(3,"已通过"),
    REJECT(4,"已驳回"),
    CANCEL(5,"已取消"),
    ;
    private final Integer value;
    private final String name;
    ComStates(Integer value,String name){
        this.value = value;
        this.name = name;
    }

    public static ComStates getByValue(Integer value){
        return new ArrayList<>(Arrays.asList(ComStates.values())).stream().filter(o-> Objects.equals(o.value,value)).findFirst().orElse(null);
    }
}

 

事件:

@Getter
public enum ComEvents {
    SUBMIT(1,"提交审核"),
    CANCEL(2,"撤销审核"),
    PASS_AUDIT(4,"通过审核"),
    REJECT_AUDIT(5,"驳回审核")
    ;
    private final Integer value;
    private final String name;
    ComEvents(Integer value,String name){
        this.value = value;
        this.name = name;
    }
}

 

审批事件流程参考

操作示例图-0c569563a4aa41a88c717f9899d44402.png
流程参考

 

 

一共五个事件,五个简易流程

 

演示项目结构参考:

操作示例图-4f604b4e422b4281aab60539e415a381.png

 

测试接口:

@GetMapping("/com/get")
public ComContext get(String dataId){
    return dbExample.get(dataId);
}

@GetMapping("/com/submit")
public Object submit(String dataId){
    ComContext context = dbExample.get(dataId);
    ComContext ctx=new ComContext();
    BeanUtils.copyProperties(context,ctx);
    return comAuditMachine.fire(ComStates.getByValue(context.getCurrentState()), ComEvents.SUBMIT, ctx);
}

@GetMapping("/com/cancel")
public Object cancel(String dataId){
    ComContext context = dbExample.get(dataId);
    ComContext ctx=new ComContext();
    BeanUtils.copyProperties(context,ctx);
    return comAuditMachine.fire(ComStates.getByValue(context.getCurrentState()), ComEvents.CANCEL, ctx);
}


@GetMapping("/com/audit")
public Object audit(String dataId,Long suid,Integer state,String msg){
    ComContext context = dbExample.get(dataId);
    ComContext ctx=new ComContext();
    BeanUtils.copyProperties(context,ctx);
    ctx.setSessionUserId(suid);
    ctx.setCurrentNodeAuditState(state);
    ctx.setCurrentNodeReason(msg);
    ComEvents comEvents;
    if (Objects.equals(1,state)){
        comEvents = ComEvents.PASS_AUDIT;
    }else{
        comEvents = ComEvents.REJECT_AUDIT;
    }
    return comAuditMachine.fire(ComStates.getByValue(context.getCurrentState()),comEvents,ctx);
}

主要包含,提交审批/取消审批/审批。另外一个get获取当前审核数据信息

下面模拟流程: 提交审批->取消审批

操作示例图-29a947e7b4754f569c30136574932b33.png
提交审批->取消审批

 

上面操作,一切都按预计执行。

 

下面执行以下流程:提交审批->1号审核人员通过->2号人员驳回

操作示例图-b84c580522e545f49d3a141468468f19.png

按预计执行完毕。

 

其他流程这里就不展开描述了,感兴趣的可以下载demo源码尝试

demo-boot-statemachine.zip (访问密码: 9987)

相关操作接口:

查看审核信息
http://localhost:8080/com/get?dataId=1

提交审核
http://localhost:8080/com/submit?dataId=1


取消审核
http://localhost:8080/com/cancel?dataId=1


首次审核不通过
http://localhost:8080/com/audit?dataId=1&suid=1&state=2&msg=notfond


1号人审核通过
http://localhost:8080/com/audit?dataId=1&suid=1&state=1


2号不通过
http://localhost:8080/com/audit?dataId=1&suid=2&state=2&msg=2notfond


2号通过
http://localhost:8080/com/audit?dataId=1&suid=2&state=1

 

 

需要注意的是引用状态机模式,并不能减少业务代码的编写,只是优化的整个编码的细节,如COLA的下图一样形象的讲解了这个

操作示例图-bf211086611a4a68b0424501d70df839.png

 

更多参考连接:

 

 

 

 

 

地址:https://www.leftso.com/article/2403281832589381.html

相关阅读

Java 编程语言中,状态机主要有这几个 spring statemachine 、squirrel-foundation 、下面是cola-component-statemachine 实战。
介绍在本教程中,我们将探索另一种流行的行为设计模式 - 状态设计模式
前端状态数据展示小技巧
一、spring boot shiro 无状态token认证项目结构图​二、无状态spring boot shiro相关配置2.1shiro redis 缓存配置首先是实现shiro的cache...
本文针对Java虚拟机对程序性能影响,通过设置不同的Java虚拟机参数来提升程序的性能。首先从Java虚拟机各个性能方面来进行监控,找出Java虚拟机中可能对程序性能影响较大的,然后先通过小实验...
MySQL5.6数据库双机主从热备配置
MySQL5.6配置双机互为主备
超频三刀锋S85 VS 大镰刀S950m 小机箱使用散热效果对比。
问题描述默认情况下,在使用spring的restTemplate调用接口,如果响应的http状态码是200则会成功返回数据
Hyper-V 微软windows系统自带虚拟机软件介绍