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

目录
  • 前言
  • 一.设计思路
  • 二.具体实现代码
  • 三.注意事项
    • 1.activiti-bpmn-layout.jar
    • 2.mxgraph-all.jar
    • 3.使用了layout和不使用的生成的图对比
  • 四.总结
    • 后话

前言

最近项目有用到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动态生成工作流的资料请关注我们其它相关文章!

(0)

相关推荐

  • Activiti7整合Springboot使用记录

    目录 0.Springboot项目创建 1.引入Activiti相关依赖 2.启动工程并创建activiti数据库 3.流程部署 4.流程实例启动 5.任务查询 6. 完成任务 7.流程结束,或流程流转过程中的历史信息查询 8.其他Api测试 8.1 流程定义信息查询 8.2 删除流程 9.demo源码下载 0.Springboot项目创建 通过https://start.spring.io/生成纯净的一个springboot工程 1.引入Activiti相关依赖 <dependency> &

  • 解决Springboot2.1.x配置Activiti7单独数据源问题

    1|1简介 最近基于最新的Activiti7配置了SpringBoot2. 简单上手使用了一番.发现市面上解决Activiti7的教程很少,采坑也比较多,在Activiti6配置数据源和Activiti7有所区别,基于Activiti6在Activiti7里是无法正常使用的.接下来让我们看下区别. 1|2问题 Activiti6多数据源配置 6的配置比较简单点. 先加入配置: # activiti 数据源 spring.datasource.activiti.driver=com.mysql.j

  • Springboot2.1.6集成activiti7出现登录验证的实现

    一.问题 Spring2.1.5集成activiti7.1.24时访问要输入用户名和密码. @Autowired private ProcessRuntime processRuntime; /** * 启动任务 */ @Test void startProcess(){ /** * 流程变量 * 给<userTask id="请假申请" name="请假申请" activiti:assignee="#{student}"></

  • java开发Activiti进阶篇流程实例详解

    目录 1.流程实例 1.1 什么是流程实例 1.2 业务管理 1.3 流程实例的挂起和激活 1.3.1 全部流程挂起 1.3.2 单个实例挂起 1.流程实例 1.1 什么是流程实例 流程实例(ProcessInstance)代表流程定义的执行实例 一个流程实例包括了所有的运行节点,我们可以利用这个对象来了解当前流程实例的进度等信息 例如:用户或者程序安装流程定义的内容发起了一个流程,这个就是一个流程实例 1.2 业务管理 ​流程定义部署在Activiti后,我们就可以在系统中通过Activiti

  • spring boot只需两步优雅整合activiti示例解析

    目录 前言 springboot整合activiti只需两步 1.添加boot的activiti模块 2.添加你的流程图文件 增强你的activiti,发布restful管理activiti resource 1.添加依赖 2.添加用户组以及用户,只有验证通过才能管理activiti 增强你的activiti,发布restful管理boot应用 1.添加依赖 2.相关接口信息 前言 本文描述的是怎么将activiti优雅的整合进你的spring boot应用,并增强你的activiti管理功能,

  • SpringBoot整合Activiti7的实现代码

    Activiti7发布正式版之后,它与SpringBoot2.x已经完全支持整合开发.我们可以将Activiti7与SpringBoot整合开发的坐标引入到工程中,从而达到SpringBoot支持Activti7整合. 1.使用IDEA创建SpringBoot项目 在工程的pom.xml文件中引入相关的依赖,具体依赖如下所示 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="ht

  • Activiti进阶之组任务实现示例详解

    目录 1.组任务 1.1.需求 1.2.设置任务候选人 1.3.组任务 1.3.1.组任务办理流程 1.3.2. 查询组任务 1.3.3 . 拾取组任务 1.3.4. 查询个人待办任务 1.3.5. 办理个人任务 1.3.6. 归还组任务 1.3.7. 任务交接 1.3.8. 数据库表操作 1.组任务 1.1.需求 在流程定义中在任务结点的 assignee 固定设置任务负责人,在流程定义时将参与者固定设置在.bpmn 文件中,如果临时任务负责人变更则需要修改流程定义,系统可扩展性差. 针对这种

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

    目录 前言 一.设计思路 二.具体实现代码 三.注意事项 1.activiti-bpmn-layout.jar 2.mxgraph-all.jar 3.使用了layout和不使用的生成的图对比 四.总结 后话 前言 最近项目有用到Activiti工作流,但是需求有点特殊,需要通过参数去生成BPMN图,查阅了资料后,能实现简单的工作流生成,那接下来看看如何通过代码动态生成工作流的吧. 一.设计思路 1.以普通的请假流程为例 (1)生成开始节点加第1个任务和调整申请任务(拒绝或者退回操作)以及其排他

  • vue中v-model动态生成的实例详解

    vue中v-model动态生成的实例详解 前言: 最近在做公司的项目中,有这么一个需求,每一行有一个input和一个select,其中行数是根据服务器返回的json数据动态变化的.那么问题来了,我们要怎样动态生成v-model? 现在项目做完了就整理了一下,直接贴代码了. <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <

  • JavaScript实现动态生成表格案例详解

    目录 前言 实现思路 实现代码  实现效果 前言 在这里实现一个动态添加表格的案例,当点击添加按钮时,可以弹出一个表单,然后将输入的内容添加到表格中,也可以将表格中的整行内容清除. 实现思路 先创建一个表格和一个表单,将表单中输入的内容动态添加进表格中,表单页面右上角有一个关闭按钮,当点击时,可以将表单页面关闭并将表格页面显示.为了页面美观,我将添加数据的按钮放在了表格的<tfoot></tfoot>中,将动态生成的表格数据添加到<tbody><tbody>

  • Java实现动态生成GIF图像详解

    目录 背景 特点 用途 AnimatedGifEncoder简介 GIF创作生成 一.创建maven项目 二.自定义生成 三.自定义将多张图片合成 话外题-怀念巨人 总结 背景 在互联网上有许多有趣的场景,其中的一种就是动图.这不是视频,而是一种GIF图像信息.虽然没有声音,却给我们带来了无穷的乐趣.如果说斗图是曾经聊天或者网聊的乐趣,那动图一定是承包了这种欢乐的技术原理. GIF的全称是Graphics Interchange Format,可译为图形交换格式,用于以超文本标志语言(Hyper

  • Java Spring动态生成Mysql存储过程详解

    一. 背景 由于公司业务需要动态配置一些存储过程来生成数据,之前尝试过使用jpa来完成,或多或少都存在一些问题,最后使用了spring的Jdbctemplate. 二. 环境 1.此随笔内容基于spring boot项目 2.数据库为mysql 5.7.9版本 3.jdk 版本为1.8 三. 说明 说明:为方便表示,下列存储过程在代码中的表示我称之为接口配置 四. 内容 1.定义接口和接口参数bean: 1)接口配置bean: @Entity @Table(name="qt_interface&

  • C语言编程gcc如何生成静态库.a和动态库.so示例详解

    目录 一.什么是静态库和动态库 二.gcc生成.a静态库和.so动态库 1.生成静态库(.a) 1.1编辑生成例子程序hello.h.hello.c和main.c 1.2将hello.c编译成.o文件 1.3由.o文件创建静态库 1.4在程序中使用静态库 1.5验证静态库的特点 2.生成动态库(.so) 2.1由.o文件创建动态库文件 2.2在程序中使用动态库 三.实例 1.实例1 1.1代码 1.2 静态库.a文件的生成与使用 1.3 动态库.so文件的生成与使用 2.实例2 2.1代码 2.

  • 关于动态执行代码(js的Eval)实例详解

    熟悉javascript的朋友对Eval()函数可能都不会陌生,我们可以用它来实现动态代码的执行,我自己甚至写过一个网页专门用来计算算术表达式的,计算能力上比google.baidu的计算器还要好一些,至少精度要高,但是如果超出了四则运算的话,表达式的形式会复杂很,比如以百度给出的例子: log((5+5)^2)-3+pi需要写成Math.log(Math.pow(5+5,2))*Math.LOG10E-3+Math.PI才能用Eval进行计算,对于这一点我还没有想到理想的解决方案.好了,这不是

  • 使用React代码动态生成栅格布局的方法

    作为 TerminalMACS 的一个子进程模块 - React Web管理端,使用Ant Design Pro作为框架. 本文应用到的知识1.样式文件less中方法的使用2.for循环创建按钮和栅格布局(flex布局) 1. 最终效果及源码链接 作为前端新手的我,做下面这个简单功能花了好几天时间,问了不少前端大佬(大佬们应该要不到半个小时,惭愧惭愧),现在回想问的问题都很基础(有点丢人,哈哈),多谢了哦. 先看看效果 点击浏览源码:开源项目对应源码 2. 代码简单讲解 2.1 TypeScri

  • Springboot Mybatis Plus自动生成工具类详解代码

    前言 代码生成器,也叫逆向工程,是根据数据库里的表结构,自动生成对应的实体类.映射文件和接口. 看到很多小伙伴在为数据库生成实体类发愁,现分享给大家,提高开发效率. 一.pom依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> &

  • Java中的引用和动态代理的实现详解

    我们知道,动态代理(这里指JDK的动态代理)与静态代理的区别在于,其真实的代理类是动态生成的.但具体是怎么生成,生成的代理类包含了哪些内容,以什么形式存在,它为什么一定要以接口为基础? 如果去看动态代理的源代码(java.lang.reflect.Proxy),会发现其原理很简单(真正二进制类文件的生成是在本地方法中完成,源代码中没有),但其中用到了一个缓冲类java.lang.reflect.WeakCache<ClassLoader,Class<?>[],Class<?>

随机推荐