Activiti7通过代码动态生成工作流实现详解

 更新时间:2022年11月24日 09:50:46   作者:自由了  
这篇文章主要为大家介绍了Activiti7通过代码动态生成工作流实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

最近项目有用到Activiti工作流,但是需求有点特殊,需要通过参数去生成BPMN图,查阅了资料后,能实现简单的工作流生成,那接下来看看如何通过代码动态生成工作流的吧。

一.设计思路

1.以普通的请假流程为例

(1)生成开始节点加第1个任务和调整申请任务(拒绝或者退回操作)以及其排他网关

(2)循环审批列表,生成第2至第N-1个任务,并每个任务后都有1个排他网关,用于连接调整申请任务

(3)最后1个节点,后面无排他任务,故需要单独处理

二.具体实现代码

    List<String> roles=new ArrayList<>();
        roles.add("1508574");
        roles.add("13765234");
        roles.add("18834222");
        listMap.put("province",roles);
          for (String auditRole : processParamsDto.getAuditRoles()) {
        if (auditRole.equals(processParamsDto.getAuditRoles().get(0))) {
            //开始连线
            process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "审批".concat(auditRole), auditRole));
            process.addFlowElement(createSequenceFlow("start", "task".concat("_").concat(auditRole), null));
            //正常的 第一个网关 process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole)));
            //第一个排他网关连线 任务->排他网关
            process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null));
            //重新申请分支  创建重新申请任务
            process.addFlowElement(createUserTask("task".concat("_").concat("重新申请"), "指定人".concat("审批"), "${startBy}"));
            //申请网关->申请任务
            process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申请"), "${flag==false}"));
            //申请网关
            process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat("重新申请"), "exclusiveGateWay".concat("_").concat("重新申请")));
            //申请任务->申请网关
            process.addFlowElement(createSequenceFlow("task".concat("_").concat("重新申请"),"exclusiveGateWay".concat("_").concat("重新申请"), null));
        } else if (!auditRole.equals(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1))) {
            //创建排他网关  每个任务后都有一个排他网关
            //第二个任务至第size-1个任务
            process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "审批".concat(auditRole), auditRole));
            //第一个网关->第二个任务  任务之前的节点 网关->第二个任务....第N个任务 true
            process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(getPreAuditRole(auditRole,processParamsDto.getAuditRoles())), "task".concat("_").concat(auditRole), "${flag==true}"));
            //网关->申请任务 false
            process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay(当前)".concat("_").concat(auditRole)));
            process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null));
            //排他网关—>重新申请任务
            process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申请"),"#{flag==false}"));
        } else if (auditRole.equals(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1))) {
            String lastNode=processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1);
            System.out.println("当前节点"+lastNode);
            process.addFlowElement(createUserTask("task".concat(lastNode), "审批".concat(auditRole), auditRole));
            process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(getPreAuditRole(auditRole,processParamsDto.getAuditRoles())),"task".concat(lastNode),"#{flag==true}"));
            process.addFlowElement(createEndEvent());
            process.addFlowElement(createSequenceFlow("task".concat(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1)), "end", "${flag==true}"));     process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat("重新申请"), "end", "${flag==false}"));
  process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat("重新申请"), "task".concat("_").concat(processParamsDto.getAuditRoles().get(0)), "${flag==true}"));
        }
    }     
     new BpmnAutoLayout(model).execute();
    //定义并设置流程变量
    Map<String, Object> variables = new HashMap<>();
        variables.put("flag", 1 == 2);
    //deploy
    Deployment deployment = repositoryService.createDeployment().addBpmnModel("process/dynamic-model.bpmn", model).name("Dynamic process deployment").key("test_bpmn").deploy();
processEngine.getRuntimeService().startProcessInstanceByKey(processDefinition.getKey(), variables);
InputStream inputStreamXml = processEngine.getRepositoryService().getResourceAsStream(deployment.getId(), "process/dynamic-model.bpmn");
//保存到本地,方便查看生成后的文件
 FileUtils.copyInputStreamToFile(inputStreamXml, new File("D:\bpmn_data\process.bpmn.xml"));

三.注意事项

1.activiti-bpmn-layout.jar

//BPMN图布局自动调整需要添加
<dependency>
   <groupId>org.activiti</groupId>
   <artifactId>activiti-bpmn-layout</artifactId>
   <version>7.1.0.M4</version>
</dependency>

2.mxgraph-all.jar

//需要手动添加,其自带的mxgraph找不到方法,原因待确认,有时间去提个issue问问
<dependency>
   <groupId>com.mxgraph</groupId>
   <artifactId>mxgraph-all</artifactId>
   <version>4.2.2</version>
   <scope>system</scope>
</dependency>

3.使用了layout和不使用的生成的图对比

四.总结

通过代码生成的BPMN图其实很乱,即使加了BpmnAutoLayout方法去调整布局,但是不影响流程正常使用。还有就是看了一遍源码,没有找到子流程(SubProcess的子任务)的生成方法,暂时不支持生成子流程,待我再多研究研究。

后话

简单流程通过代码生成没问题,复杂流程还是建议用工具绘图,通过代码生成有时候容易出问题。毕竟有一些节点不能连线,而且复杂流程对于一些退回操作不是很友好,实现起来很麻烦。

以上就是Activiti7通过代码动态生成工作流实现详解的详细内容,更多关于Activiti7动态生成工作流的资料请关注脚本之家其它相关文章!

相关文章

  • Java实现批量导出导入数据及附件文件zip包

    Java实现批量导出导入数据及附件文件zip包

    这篇文章主要为大家详细介绍了Java实现批量导出导入数据及附件文件zip包的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一
    2022-09-09
  • Java面试题冲刺第十一天--集合框架篇(2)

    Java面试题冲刺第十一天--集合框架篇(2)

    这篇文章主要为大家分享了最有价值的两道集合框架的面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • springboot 集成支付宝支付的示例代码

    springboot 集成支付宝支付的示例代码

    这篇文章主要介绍了springboot 集成支付宝支付的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • Java多线程编程中的两种常用并发容器讲解

    Java多线程编程中的两种常用并发容器讲解

    这篇文章主要介绍了Java多线程编程中的两种常用并发容器讲解,分别是ConcurrentHashMap与ConcurrentHashMap,需要的朋友可以参考下
    2015-12-12
  • springboot实现yml里的自定义配置方法

    springboot实现yml里的自定义配置方法

    这篇文章主要介绍了springboot实现yml里的自定义配置方法,主要介绍三种,字符串配置,数组配置和带默认值的配置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Java并发工具辅助类代码实例

    Java并发工具辅助类代码实例

    这篇文章主要介绍了Java并发工具辅助类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Java中转换器设计模式深入讲解

    Java中转换器设计模式深入讲解

    这篇文章主要给大家介绍了关于Java中转换器设计模式的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-04-04
  • SpringBoot的WebSocket实现单聊群聊

    SpringBoot的WebSocket实现单聊群聊

    这篇文章主要为大家详细介绍了SpringBoot的WebSocket实现单聊群聊,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-02-02
  • SpringBoot配置Spring Native的详细步骤

    SpringBoot配置Spring Native的详细步骤

    配置 Spring Native 以减少 Spring Boot 应用的启动时间,涉及几个关键步骤,包括设置相应的依赖、配置文件以及构建过程,本文给大家就介绍了详细的步骤和配置示例,需要的朋友可以参考下
    2024-11-11
  • Java之Spring整合Junit

    Java之Spring整合Junit

    Java Spring框架是一个轻量级的开源框架,具有很高的凝聚力和吸引力,本篇文章带你了解如何配置数据源、注解开发以及整合Junit
    2023-04-04

最新评论