Activiti6.0 多级审批流程 代码执行

背景:公司要求有流程审批系统以便于适应不同客户的审批层级;确定以Activiti6.0作为流程引擎;

这里给出一个简单的多级审批流程:

  • 创建流程图,我这里流程图在eclipse中生成的,使用了Activiti Eclipse BPMN 2.0 Designer插件;流程图为.bpmn格式,我们在解析的时候,可以重命名为.bpmn20.xml;

这里给出一个多级审批的流程图:

这个图我加了一些文字说明,丑了点,将就着看吧;

然后我给出这个流程图对应的源码:文件全名称为ApprovalProcess.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn"xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"targetNamespace="http://www.activiti.org/test"><process id="myProcess" name="流程审批" isExecutable="true"><startEvent id="startEvent" name="开始"></startEvent><userTask id="Submit" name="填写信息提交校对"><extensionElements><activiti:formProperty id="SubmitMessage" name="提交时填写的信息" type="string"required="true"></activiti:formProperty><activiti:formProperty id="SubmitUserName" name="申请人" type="string"required="true"></activiti:formProperty><activiti:formProperty id="SubmitTime" name="提交时间" type="date" datePattern="yyyy-MM-dd"required="true"></activiti:formProperty><activiti:formProperty id="SubmitType" name="是否提交校对" type="string"required="true"></activiti:formProperty></extensionElements></userTask><sequenceFlow id="flow1" sourceRef="startEvent" targetRef="Submit"></sequenceFlow><exclusiveGateway id="decideSubmit" name="提交校对或者取消"></exclusiveGateway><sequenceFlow id="flow2" sourceRef="Submit" targetRef="decideSubmit"></sequenceFlow><userTask id="Proofread" name="校对"><extensionElements><activiti:formProperty id="ProofreadMessage" name="校对时填写的信息" type="string"required="true"></activiti:formProperty><activiti:formProperty id="ProofreadUserName" name="校对人" type="string"required="true"></activiti:formProperty><activiti:formProperty id="ProofreadTime" name="校对时间" type="date" datePattern="yyyy-MM-dd"required="true"></activiti:formProperty><activiti:formProperty id="ProofreadType" name="是否校对通过" type="string"required="true"></activiti:formProperty></extensionElements></userTask><sequenceFlow id="flow3" sourceRef="decideSubmit" targetRef="Proofread"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${SubmitType=="Y" || SubmitType=="y"}]]></conditionExpression></sequenceFlow><exclusiveGateway id="decideProofread" name="校对通过或者失败"></exclusiveGateway><sequenceFlow id="flow4" sourceRef="Proofread" targetRef="decideProofread"></sequenceFlow><userTask id="Review" name="审核"><extensionElements><activiti:formProperty id="ReviewMesage" name="审核时填写的信息" type="string"required="true"></activiti:formProperty><activiti:formProperty id="ReviewUserName" name="审核人" type="string"required="true"></activiti:formProperty><activiti:formProperty id="ReviewTime" name="审核时间" type="date" datePattern="yyyy-MM-dd"required="true"></activiti:formProperty><activiti:formProperty id="ReviewType" name="是否审核通过" type="string"required="true"></activiti:formProperty></extensionElements></userTask><sequenceFlow id="flow5" sourceRef="decideProofread" targetRef="Review"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${ProofreadType=="Y" || ProofreadType=="y"}]]></conditionExpression></sequenceFlow><exclusiveGateway id="decideReview" name="审核通过或者失败"></exclusiveGateway><sequenceFlow id="flow6" sourceRef="Review" targetRef="decideReview"></sequenceFlow><endEvent id="endEvent1" name="结束"></endEvent><sequenceFlow id="flow7" sourceRef="decideReview" targetRef="endEvent1"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${ReviewType=="Y" || ReviewType=="y"}]]></conditionExpression></sequenceFlow><endEvent id="endEventCancel" name="取消"></endEvent><sequenceFlow id="flow8" sourceRef="decideSubmit" targetRef="endEventCancel"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${SubmitType=="N" || SubmitType=="n"}]]></conditionExpression></sequenceFlow><sequenceFlow id="flow9" sourceRef="decideProofread" targetRef="Submit"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${ProofreadType=="N" || ProofreadType=="n"}]]></conditionExpression></sequenceFlow><sequenceFlow id="flow10" sourceRef="decideReview" targetRef="Submit"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${ReviewType=="N" || ReviewType=="n"}]]></conditionExpression></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_myProcess"><bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess"><bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent"><omgdc:Bounds height="35.0" width="35.0" x="130.0" y="260.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="Submit" id="BPMNShape_Submit"><omgdc:Bounds height="55.0" width="105.0" x="210.0" y="250.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="decideSubmit" id="BPMNShape_decideSubmit"><omgdc:Bounds height="40.0" width="40.0" x="360.0" y="258.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="Proofread" id="BPMNShape_Proofread"><omgdc:Bounds height="55.0" width="105.0" x="445.0" y="251.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="decideProofread" id="BPMNShape_decideProofread"><omgdc:Bounds height="40.0" width="40.0" x="595.0" y="259.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="Review" id="BPMNShape_Review"><omgdc:Bounds height="55.0" width="105.0" x="680.0" y="252.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="decideReview" id="BPMNShape_decideReview"><omgdc:Bounds height="40.0" width="40.0" x="830.0" y="260.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endEvent1" id="BPMNShape_endEvent1"><omgdc:Bounds height="35.0" width="35.0" x="915.0" y="263.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endEventCancel" id="BPMNShape_endEventCancel"><omgdc:Bounds height="35.0" width="35.0" x="440.0" y="350.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"><omgdi:waypoint x="165.0" y="277.0"></omgdi:waypoint><omgdi:waypoint x="210.0" y="277.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"><omgdi:waypoint x="315.0" y="277.0"></omgdi:waypoint><omgdi:waypoint x="360.0" y="278.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"><omgdi:waypoint x="400.0" y="278.0"></omgdi:waypoint><omgdi:waypoint x="445.0" y="278.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"><omgdi:waypoint x="550.0" y="278.0"></omgdi:waypoint><omgdi:waypoint x="595.0" y="279.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"><omgdi:waypoint x="635.0" y="279.0"></omgdi:waypoint><omgdi:waypoint x="680.0" y="279.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"><omgdi:waypoint x="785.0" y="279.0"></omgdi:waypoint><omgdi:waypoint x="830.0" y="280.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7"><omgdi:waypoint x="870.0" y="280.0"></omgdi:waypoint><omgdi:waypoint x="915.0" y="280.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8"><omgdi:waypoint x="380.0" y="298.0"></omgdi:waypoint><omgdi:waypoint x="380.0" y="367.0"></omgdi:waypoint><omgdi:waypoint x="440.0" y="367.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9"><omgdi:waypoint x="615.0" y="299.0"></omgdi:waypoint><omgdi:waypoint x="614.0" y="401.0"></omgdi:waypoint><omgdi:waypoint x="262.0" y="398.0"></omgdi:waypoint><omgdi:waypoint x="262.0" y="305.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10"><omgdi:waypoint x="850.0" y="260.0"></omgdi:waypoint><omgdi:waypoint x="850.0" y="87.0"></omgdi:waypoint><omgdi:waypoint x="565.0" y="87.0"></omgdi:waypoint><omgdi:waypoint x="262.0" y="87.0"></omgdi:waypoint><omgdi:waypoint x="262.0" y="250.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>
  • maven项目引入dependency依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.sd</groupId><artifactId>process</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.activiti</groupId><artifactId>activiti-engine</artifactId><version>6.0.0</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>28.2-jre</version></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><version>1.4.200</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version><scope>provided</scope></dependency></dependencies>
</project>

这里说明一下因为是代码测试,因此数据库使用的是H2内存数据库;

  • 流程执行代码
package org.sd.processs;import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.Executors;/*** @author sword_happy*/
@Slf4j
public class ProcessMain {public static void main(String[] args) throws ParseException {log.info("启动我们的程序!");//1 创建流程引擎,基于内存的数据库处理ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();ProcessEngine processEngine = cfg.buildProcessEngine();String name = processEngine.getName();String version = ProcessEngine.VERSION;log.info("流程引擎名称:[{}] 版本:[{}]", name, version);//2 部署流程定义文件RepositoryService repositoryService = processEngine.getRepositoryService();DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();deploymentBuilder.addClasspathResource("ApprovalProcess.bpmn20.xml");Deployment deployment = deploymentBuilder.deploy();String deploymentId = deployment.getId();ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();log.info("流程定义文件 [{}],流程ID [{}]", processDefinition.getName(), processDefinition.getId());//3 启动运行流程RuntimeService runtimeService = processEngine.getRuntimeService();ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId());log.info("启动流程 [{}]", processInstance.getProcessDefinitionKey());//4 处理流程任务Scanner scanner = new Scanner(System.in);while (processInstance != null && !processInstance.isEnded()) {TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery().list();System.out.println("共计[" + list.size() + "]个任务");for (Task task : list) {log.info("待处理任务 [{}]", task.getName());FormService formService = processEngine.getFormService();TaskFormData taskFormData = formService.getTaskFormData(task.getId());List<FormProperty> formProperties = taskFormData.getFormProperties();Map<String, Object> variables = Maps.newHashMap();for (FormProperty formProperty : formProperties) {String line = null;if (StringFormType.class.isInstance(formProperty.getType())) {log.info("请输入 {} ?", formProperty.getName());line = scanner.nextLine();variables.put(formProperty.getId(), line);} else if (DateFormType.class.isInstance(formProperty.getType())) {log.info("请输入 {} ? 格式 (yyyy-MM-dd)", formProperty.getName());line = scanner.nextLine();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");Date date = simpleDateFormat.parse(line);variables.put(formProperty.getId(), date);} else {log.info("类型暂不支持 {}", formProperty.getType());}log.info("您输入的内容是 [{}] ?", line);}taskService.complete(task.getId(), variables);processInstance = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();}}log.info("结束我们的程序!");}
}

OK,到此为止,大功告成;

提示一下,这里是基于H2的内存数据库,因此构造对象的时候使用了Memory的方法;

后面的一些对象都是通过ProcessEngine进行获取或者间接获取的;==>意味着在Spring中,我们使用Activiti各种service的时候,只需要添加@Autowired注解就可以直接使用;

过段时间我会再写一篇基于SpringBoot的activiti6.0多级审批的博客.

希望本篇博客对你有帮助;

Activiti6.0 多级审批流程 代码执行相关推荐

  1. Java项目(一)--MyBatis实现OA系统项目实战(7)--开发多级审批流程

    开发多级审批流程 请假流程 设计约束 每一个请假单对应一个审批流程. 请假单创建后,按业务规则生成部门经理.总经理审批任务. 审批任务的经办人只能审批自己辖区内的请假申请. 所有审批任务"通 ...

  2. 三星安卓5.0设备WifiCredService 远程代码执行

    netwind · 2015/11/26 14:24 From:http://blog.quarkslab.com/remote-code-execution-as-system-user-on-an ...

  3. java多级审批流程_[SharePoint 工作流] 如何设计一个通用的多级多审核工作流程(三):工作流开发...

    在上2篇博客中,我们有了工作流定义的列表,也有了关联表单和启动表单,现在就是开始开发这个通用工作流的时刻了. 工作流的基本构成就是:一个While循环控制工作流的运转,While里的Task Repl ...

  4. 2019.最新Activiti6.0删除部署流程表(两种删除方式)

    删除部署信息,但这种方式只能删除未启动流程实例的部署表,这种方式开开源删除部署的三张表 act_re_deployment.act_re_procdef.act_ge_bytearray /*** 删 ...

  5. activiti7在线流程设计器_springboot2.x集成activiti6.0在线流程设计器

    我在网上找了很多资料都没有找到关于activiti6.0的在线流程设计器,大多数都是基于5.x的.因为6.0的源码包中没有在线设计器的资源包,因此本文使用的是activiti 5.22.0中web资源 ...

  6. [系统安全] 十.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)及防御详解

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  7. idea安装activiti流程设计器_整合Activiti6.0流程设计器 | 字痕随行

    其它相关的文章索引: 最近一个多月都在尝试了解Activiti6.0,趁着放假整合编辑器这件事情终于有了些眉目,到此可以总结一下了. 第一步:下载源码 整合的时候肯定要从源码拷贝一些东西,有些问题出现 ...

  8. 【更新1.0:PoC发布】CVE-2020-1350: Windows DNS Server蠕虫级远程代码执行漏洞通告

    0x00 更新概览 2020年07月16日,360CERT监测到 FSecureLabs 发布了 PoC,可造成拒绝服务影响.本次更新标识该漏洞极易可能在短时间内出现大规模攻击态势. 具体更新详情可参 ...

  9. Apache DolphinScheduler v2.0.1 Master 和 Worker 执行流程分析系列(三)

    点亮 ⭐️ Star · 照亮开源之路 https://github.com/apache/dolphinscheduler 这是一系列关于 DolphinScheduler v2.0.1的源码分析文 ...

  10. 「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析

    「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析 前言 一.我的开发环境 二.使用 Vue CLI (Vue 脚手架)快速搭建项目 三.初始项目的目录结构 ...

最新文章

  1. wireshark: no interface can be used for capturing in this system
  2. Dev Lake 0.4.0 版本:开源、开放的研发效能数据平台
  3. Unity3d Shader开发(三)Pass(Fog )
  4. java中常见数据库字段类型与java.sql.Types的对应
  5. 在Android中查看和管理sqlite数据库
  6. 自然语言处理中的Attention机制
  7. 企业认证CMMI都需要那些流程?
  8. 使用开源库libyuv中替换开源汇编接口,解决汇编接口中的崩溃问题
  9. SMSBMS超市订单管理系统详解(一:准备工作)
  10. python 使用函数名的字符串调用函数(4种方法)
  11. 华为网络设备综合配置实验
  12. 800 8107.79
  13. Leetcode打卡——二叉树的4种遍历你真的会了吗(Leetcode官解迭代法解法解析)
  14. 在CSDN设置“关注博主即可阅读全文”方法增加粉丝量超简单
  15. oracle-1480,1400,1438错误一些解决方式
  16. macOS: 字体(font)文件 的 存放路径
  17. 热爱生活,更热爱代码
  18. 架构扫盲 | 四种常见的软件架构
  19. 【大数据开发】SparkCore——Spark作业执行流程、RDD编程的两种方式、简单算子
  20. 0~100之间所有数字的累计求和结果.python

热门文章

  1. jieba——分词、添加词典、词性标注、Tokenize
  2. Android对控件进行隐藏
  3. 2021年化工自动化控制仪表新版试题及化工自动化控制仪表找解析
  4. 如何使生成的exe程序默认以管理员权限启动
  5. Windows MFC 工程应用开发与框架原理完全剖析教程(上)
  6. 第七章 在51单片机上移植uc/os-2
  7. 《代码大全》读书笔记(转载)
  8. 手机测试软件对手机有影响吗,智能手机测试软件的猫腻
  9. scrapy框架常用从头到尾巴
  10. 2014 年度 Git@OSC【非GitHub】 最热门的 50 个项目