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

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

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

自由了   2022-11-25 我要评论

前言

最近项目有用到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的子任务)的生成方法,暂时不支持生成子流程,待我再多研究研究。

后话

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

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们