查看之前的博客可以点击顶部的【分类专栏】

流程实例

1、什么是流程实例

一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。例如:用户或程序按照流程定义内容发起一个流程,这就是一个流程实例。

个人理解的流程实例:是具体到某一个流程定义的一个实际例子,叫流程实例。比如公司的请假流程叫做【流程定义】,它规定请假要经过多少人审批。而张三发起的请假申请,是流程实例,是具体的某一个案例,因此叫流程实例。

Activiti 工作流系统如何与我们实际业务整合呢?

比如部署系统请假流程后,如果某用户要申请请假这时就需要执行这个流程,如果另外一个用户也要申请请假则也需要执行该流程,每个执行互不影响,每个执行是单独的流程实例。

启动流程实例时,指定的 businesskey,就会在 act_ru_execution #流程实例执行表中存储 businesskey。

Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。

比如:请假流程启动一个流程实例,就可以将出请假的id作为业务标识存储到 activiti 中,将来查询 activiti 的流程实例信息就可以获取出请假的id从而关联查询业务系统数据库得到请假单信息。

启动流程实例的代码:

    /*** 启动流程实例,增加 businessKey*/@Testpublic void addBusinessKey(){//创建 ProcessEngineProcessEngine engine = ProcessEngines.getDefaultProcessEngine();//得到 RuntimeServiceRuntimeService runtimeService = engine.getRuntimeService();//启动流程实例,同时还要指定业务标识 businessKey,也就是请假申请单id,这里是1001ProcessInstance instance = runtimeService.startProcessInstanceByKey("myApply","1001");System.out.println("busniessKey="+instance.getBusinessKey());}

运行结果:

busniessKey=1001

数据库表: act_ru_execution

流程实例执行,如果当前只有一个分支时,一个流程实例只有一条记录且执行表的主键id和流程实例id相同,如果当前有多个分支正在运行则该执行表中有多条记录,存在执行表的主键和流程实例id不相同的记录。不论当前有几个分支总会有一条记录的执行表的主键和流程实例id相同。

一个流程实例运行完成,此表中与流程实例相关的记录删除。

2、挂起、激活流程实例

某些情况可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行。

2-1 全部流程实例挂起

说明:因为之前为了测试,弄了几条部署的流程,导致冗余数据较多,因此我把数据库删掉,重新建表,只部署了一个实例来测试。

操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停:

流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行。

全部流程暂停 or 挂起的代码:

    /*** 全部流程挂起与激活*/@Testpublic void suspendAllProcessInstance(){//创建 ProcessEngineProcessEngine engine = ProcessEngines.getDefaultProcessEngine();//获取RepositoryService实例RepositoryService repositoryService = engine.getRepositoryService();//查询流程定义的对象ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myApply")//根据流程定义的key查询.singleResult();//得到当前流程定义的实例是否都为暂停状态boolean flag = processDefinition.isSuspended();if(flag){//如果暂停,就激活。参数:流程ID,是否激活,激活时间repositoryService.activateProcessDefinitionById(processDefinition.getId(),true, null);System.out.println("流程定义id="+processDefinition.getId()+" 已激活");}else{//如果是激活状态,我们就暂停。参数:流程ID,是否暂停,暂停时间repositoryService.suspendProcessDefinitionById(processDefinition.getId(),true,null);System.out.println("流程定义id="+processDefinition.getId()+" 已挂起");}}

测试:

流程定义id=myApply:1:4 已挂起

查看数据库表:(我们通过对日志文件搜索【update ACT_】就知道它更新了哪些表了。)

act_ru_task  和 act_re_procdef 的状态 SUSPENSION_STATE_ 都改为2。

再点击测试:

流程定义id=myApply:1:4 已激活

状态改为了1。因此:1=激活,2=挂起状态。

2-2 单个流程实例挂起

操作流程实例对象,针对单个流程执行挂起操作,某个流程实例挂起则此流程不再继续执行,完成该流程实例的当前任务将报异常。

代码:(要寻找流程实例ID,可以去表:act_ru_task 寻找。)

    /*** 单个流程实例挂起与激活*/@Testpublic void suspendSingleProcessInstance(){//创建 ProcessEngineProcessEngine engine = ProcessEngines.getDefaultProcessEngine();RuntimeService runtimeService = engine.getRuntimeService();//查询流程定义的对象ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("2501").singleResult();boolean flag = processInstance.isSuspended();if(flag){//如果是暂停状态,则激活runtimeService.activateProcessInstanceById(processInstance.getId());System.out.println("流程实例 id ="+processInstance.getId()+",已激活");}else{runtimeService.suspendProcessInstanceById(processInstance.getId());System.out.println("流程实例 id ="+processInstance.getId()+",已挂起");}}

启动测试:

流程实例 id =2501,已挂起

然后我们查看数据库:(我们通过对日志文件搜索【update ACT_】就知道它更新了哪些表了。)

表:act_ru_task

表:act_ru_execution

在暂停状态,我们是否可以继续完成个人任务呢?

我们增加完成个人任务的测试方法:

    /*** 测试完成个人任务*/@Testpublic void completeTask(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//获取任务 ServiceTaskService taskService = processEngine.getTaskService();//完成任务,参数:流程实例id,完成 zhangsan 的任务Task task = taskService.createTaskQuery().processInstanceId("2501").taskAssignee("lisi").singleResult();System.out.println("流程实例id="+task.getProcessInstanceId());System.out.println("任务Id="+task.getId());System.out.println("任务负责人="+task.getAssignee());System.out.println("任务名称="+task.getName());taskService.complete(task.getId());}

点击测试:

org.activiti.engine.ActivitiException: Cannot complete a suspended task

at org.activiti.engine.impl.cmd.NeedsActiveTaskCmd.execute(NeedsActiveTaskCmd.java:53)
    at org.activiti.engine.impl.interceptor.CommandInvoker$1.run(CommandInvoker.java:37)

发现报错:不能完成已挂起的任务。

说明当单个任务被挂起之后,是不能继续完成的。

我们可以再次把已挂起的任务激活,重新测试。就是测试上一个方法。

流程实例 id =2501,已激活

然后,再次点击完成任务的测试:

任务已经完成了。

个人任务

1、分配任务负责人

1-1 固定分配(了解即可,实际开发不会用到)

在进行业务流程建模时指定固定的任务负责人,在 properties 视图中,填写 Assignee 项为任务负责人。

1-2 表达式分配

1-2-1 UEL 表达式 

Activiti 使用 UEL 表达式, UEL 是 java EE6 规范的一部分, UEL(Unified Expression Language)即统一表达式语言, activiti 支持两个 UEL 表达式: UEL-valueUEL-method

UEL-value 方式,语法:${assignee}   或者 :${user.assignee}

assignee 这个变量是 activiti 的一个流程变量。user 也是 activiti 的一个流程变量, user.assignee 表示通过调用 user 的 getter 方法获取值。

UEL-method 方式,语法:${UserBean.getUserId()}

userBean 是 spring 容器中的一个 bean,表示调用该 bean 的 getUserId()方法。

UEL-method 与 UEL-value 结合 

${ldapService.findManagerForEmployee(emp)}
ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti 是流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中。

其它:

表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。
如下:${order.price > 100 && order.price < 250}

1-2-2 编写代码使用 UEL 配置负责人 

我们需要重新定义一个流程,以区分之前测试的。那我们就定义一个报销流程吧。

创建一个 reimburse.bpmn 文件,可以查看前面的博客来创建。

完整 xml 代码:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1623595618934" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><process id="myReimburse" isClosed="false" isExecutable="true" name="报销流程" processType="None"><startEvent id="_2" name="报销流程"/><userTask activiti:assignee="${assignee0}" activiti:exclusive="true" id="_3" name="发起报销申请"/><userTask activiti:assignee="${assignee1}" activiti:exclusive="true" id="_4" name="经理审批"/><userTask activiti:assignee="${assignee2}" activiti:exclusive="true" id="_5" name="财务审批"/><endEvent id="_6" name="流程结束"/><sequenceFlow id="_7" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_8" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_9" sourceRef="_4" targetRef="_5"/><sequenceFlow id="_10" sourceRef="_5" targetRef="_6"/></process><bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"><bpmndi:BPMNPlane bpmnElement="myReimburse"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="180.0" y="30.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="55.0" width="85.0" x="155.0" y="120.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="160.0" y="225.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="55.0" width="85.0" x="160.0" y="330.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6"><omgdc:Bounds height="32.0" width="32.0" x="190.0" y="425.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="196.0" y="62.0"/><omgdi:waypoint x="196.0" y="120.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_4"><omgdi:waypoint x="200.0" y="175.0"/><omgdi:waypoint x="200.0" y="225.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_4" targetElement="_5"><omgdi:waypoint x="202.5" y="280.0"/><omgdi:waypoint x="202.5" y="330.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_5" targetElement="_6"><omgdi:waypoint x="206.0" y="385.0"/><omgdi:waypoint x="206.0" y="425.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

然后生成 reimburse.png 图片。并且放到 resources 目录下。

然后部署流程定义。(跟前面介绍的一样的部署方式)

    /*** 部署流程定义*/@Testpublic void testUELDeployment(){//创建 ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//得到 RepositoryService 实例RepositoryService service = processEngine.getRepositoryService();//使用 RepositoryService 实例进行部署Deployment deployment = service.createDeployment().addClasspathResource("bpmn/reimburse.bpmn") //添加 bpmn 资源.addClasspathResource("bpmn/reimburse.png") //添加 png 资源.name("报销流程").deploy();System.out.println("流程部署Id="+deployment.getId());System.out.println("流程部署name="+deployment.getName());}

运行结果:

流程部署Id=22501
流程部署name=报销流程

然后,启动流程实例(需要设置流程的变量)注意,我们不能使用前面说的方法直接启动流程实例,因为还没指定人,会导致审批人为空的情况。代码如下:

    /*** 启动 UEL 流程实例*/@Testpublic void testStartUELProcess(){//1、创建 ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//2、获取 RunTimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();//设置 assignee 的取值,用户可以在页面上设置流程的执行Map<String,Object> map = new HashMap<>();map.put("assignee0","大师兄");map.put("assignee1","二师兄");map.put("assignee2","三师兄");//根据流程定义ID启动流程ProcessInstance instance = runtimeService.startProcessInstanceByKey("myReimburse",map);System.out.println("流程定义id=" + instance.getProcessDefinitionId());System.out.println("流程实例id=" + instance.getId());System.out.println("当前活动Id=" + instance.getActivityId());}

测试:

流程定义id=myReimburse:1:22504
流程实例id=25001
当前活动Id=null

act_re_deployment     流程定义部署表:

在表:act_ru_variable  可以看到结果:

1-2-3 注意事项

由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如:
某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在流程变量中存在,否则 activiti 异常。

1-3 监听器分配

可以使用监听器来完成很多Activiti流程的业务。我们使用监听器的方式来指定负责人,那么在流程设计时就不需要指定assignee。

任务监听器是发生对应的任务相关事件时执行自定义 java 逻辑 或表达式。

我们再创建一个流程定义:离职审批流程。myLeave.bpmn

点击 Task Listeners 右边的文件夹图标,然后 Event 选择 Create。

Event的选项包含:

Create:任务创建后触发。
Assignment:任务分配后触发。
Delete:任务完成后触发。
All:所有事件发生都触发。

然后 Type 选择 Class。这个 Class 从哪里来呢?是需要我们自己创建并监听 Activiti 的接口的。

我们先创建 MyListener:在包:com.study.listener  下面。

package com.study.listener;import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;/*** @author biandan* @description 监听器* @signature 让天下没有难写的代码* @create 2021-06-13 下午 11:44*/
public class MyListener implements TaskListener {/*** 回调函数** @param delegateTask*/@Overridepublic void notify(DelegateTask delegateTask) {//判断是离职审批,并且是经理审批,才创建审批人if (delegateTask.getExecution().getProcessDefinitionId().startsWith("myLeave")&& delegateTask.getName().equals("经理审批")&& delegateTask.getEventName().equals("create")) {//指定审批负责人delegateTask.setAssignee("马芸");}//判断是离职审批,并且是人资审批,才创建审批人if (delegateTask.getExecution().getProcessDefinitionId().startsWith("myLeave")&& delegateTask.getName().equals("人资审批")&& delegateTask.getEventName().equals("create")) {//指定审批负责人delegateTask.setAssignee("刘备");}}
}

然后,我们把 MyListener 的全路径粘贴到 Class 中:

myLeave.xml 如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1623598573463" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><process id="myLeave" isClosed="false" isExecutable="true" name="离职审批" processType="None"><startEvent id="_2" name="离职审批"/><userTask activiti:exclusive="true" id="_3" name="经理审批"><extensionElements><activiti:taskListener class="com.study.listener.MyListener" event="create"/></extensionElements></userTask><userTask activiti:exclusive="true" id="_4" name="人资审批"><extensionElements><activiti:taskListener class="com.study.listener.MyListener" event="create"/></extensionElements></userTask><endEvent id="_5" name="流程结束"/><sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/></process><bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"><bpmndi:BPMNPlane bpmnElement="myLeave"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="160.0" y="20.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="55.0" width="85.0" x="140.0" y="105.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="135.0" y="205.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="32.0" width="32.0" x="160.0" y="300.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="176.0" y="52.0"/><omgdi:waypoint x="176.0" y="105.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4"><omgdi:waypoint x="180.0" y="160.0"/><omgdi:waypoint x="180.0" y="205.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5"><omgdi:waypoint x="176.0" y="260.0"/><omgdi:waypoint x="176.0" y="300.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

然后还是生成 myLeave.png ,放到 resources 下,部署离职的流程定义。

    /*** 部署流程定义:离职审批*/@Testpublic void testMyLeaveDeployment(){//创建 ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//得到 RepositoryService 实例RepositoryService service = processEngine.getRepositoryService();//使用 RepositoryService 实例进行部署Deployment deployment = service.createDeployment().addClasspathResource("bpmn/myLeave.bpmn") //添加 bpmn 资源.addClasspathResource("bpmn/myLeave.png") //添加 png 资源.name("离职审批").deploy();System.out.println("流程部署Id="+deployment.getId());System.out.println("流程部署name="+deployment.getName());}

结果:

流程部署Id=27501
流程部署name=离职审批

然后,启动离职流程的流程实例 注意打上断点查看数据的变化:

delegateTask 实例如下:

注意事项:使用监听器分配方式,按照监听事件去执行监听类的 notify 方法,方法如果不能正常执行也会影响任务的执行。

2-2 查询任务

2-2-1 查询任务负责人的待办任务并且关联 businessKey 

在 activiti 实际应用时,查询待办任务可能要显示出业务系统的一些相关信息。比如:查询待审批报销任务列表需要将报销单的日期、 报销金额等信息显示出来。

报销金额等信息在业务系统中存在,而并没有在 activiti 数据库中存在,所以是无法通过 activiti 的 api 查询到报销金额等信息。
实现:
在查询待办任务时,通过 businessKey(业务标识 )我们再去关联查询业务系统的报销表,查询报销金额等信息。

    /*** 查询当前个人待执行的任务 并查询出 businessKey*/@Testpublic void testFindProcessInstance() {//获取processEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//获取TaskServiceTaskService taskService = processEngine.getTaskService();//获取RuntimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();//查询流程定义的对象Task task = taskService.createTaskQuery().processDefinitionKey("myReimburse").taskAssignee("大师兄").singleResult();//使用task对象获取实例idString processInstanceId = task.getProcessInstanceId();//使用实例id,获取流程实例对象ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();//使用processInstance,得到 businessKeyString businessKey = processInstance.getBusinessKey();System.out.println("businessKey =" + businessKey);}

2-3 办理业务

注意:在实际应用中,完成任务前需要校验任务的负责人是否具有该任务的办理权限。

    /*** 完成任务,判断当前用户是否有权限*/@Testpublic void testComplete() {//任务idString taskId = "25001";//任务负责人String assignee = "大师兄";//获取processEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 创建TaskServiceTaskService taskService = processEngine.getTaskService();// 完成任务前,需要校验该负责人可以完成当前任务//校验方法:根据任务id和任务负责人查询当前任务,如果查到该用户有权限,就完成Task task = taskService.createTaskQuery().taskId(taskId).taskAssignee(assignee).singleResult();if (task != null) {taskService.complete(taskId);System.out.println("完成任务");}}

系列学习 SpringBoot + Activiti7 工作流之第 3 篇 —— 【进阶篇】流程实例、个人任务相关推荐

  1. 计算机编程书籍-笨办法学Python 3:基础篇+进阶篇

    编辑推荐: 适读人群 :本书适合所有已经开始使用Python的技术人员,包括初级开发人员和已经升级到Python 3.6版本以上的经验丰富的Python程序员. "笨办法学"系列, ...

  2. Activiti7学习笔记、非常详细 | 进阶篇

    Activiti进阶 一.流程实例 什么是流程实例 流程实例(ProcessInstance)代表流程定义的执行实例. 一个流程实例包括了所有的运行节点.我们可以利用这个对象来了解当前流程实例的进度等 ...

  3. C++语言程序设计视频教程_清华大学_郑莉(基础篇+进阶篇)

    C++语言程序设计视频教程_清华大学_郑莉(基础篇) 第一章:绪论 1.1 导学 1.2 计算机系统简介 1.3计算机语言和程序设计方法的发展 1.4 面向对象的基本概念 1.5 程序的开发过程 1. ...

  4. django 菜鸟篇+进阶篇

    django自带web server, 故django开发的项目可以独立的运行,也可以安置在apache(+mod_python)下运行 django wiki django主页 django源码和a ...

  5. WDA-文档-基础篇/进阶篇/讨论篇

    本文介绍SAP官方Dynpro开发文档NET310,以及资深开发顾问编写的完整教程.   链接:http://pan.baidu.com/s/1eR9axpg 密码:kf5m NET310 ABAP ...

  6. Activiti7工作流-使用Idea开发体验Activti_请假流程---工作流工作笔记006

    然后上一个文章我们已经创建了一个请假流程,然后然后我们用这个请假流程来做一下,审批 来使用一下activiti完成一个简单的工作流 首先我们是来部署,可以看到,部署首先要拿到ProcessEngine ...

  7. WEB开发基础篇 ---- 进阶篇CSS3学习

    此篇文章为进阶知识点HTML5的学习,为本人学习时的笔记记录,同时也适合初学者学习.喜欢的友友可以关注一下,后续会补充JavaScript,TypeScript,vue2.0,vue3.0以及uni框 ...

  8. 黑马SQL入门到精通笔记 —— 进阶篇

    进阶篇 进阶篇 1 存储引擎 1.1 MySQL体系结构: 1.2 InnoDB 1.3 MyISAM 1.4 Memory 1.5 存储引擎特点 1.6 存储引擎的选择 2 索引 2.1 索引结构 ...

  9. Android实现动态贴纸,Android开发之仿微博贴纸效果实现——进阶篇

    上个月写了一篇<Android开发之仿微博贴纸效果实现--基础篇>,文章中提到还有一篇进阶篇要写,很早就想动笔了,因中途去维护了开源库<高仿微信图片选择器2.0版本>,导致耽搁 ...

最新文章

  1. 动态加载子节点_微信小游戏开发之场景切换和常驻节点传递数据
  2. Netty笔记(一)第一个程序
  3. linux网络掉线频繁怎么设置,ubuntu频繁掉线
  4. 云上快报 | 分布式架构引领核心系统架构转型新趋势
  5. 使用带有注释和JQuery的Spring MVC 3的Ajax
  6. ROS学习—opencv使用之图片传输
  7. 苹果公司反诉堡垒之夜开发商Epic,寻求惩罚性赔偿
  8. empty variable name
  9. 【iOS】使用storyboard界面跳转报错:unrecognized selector sent to instance 0x7
  10. oracle 概念复习,oracle复习整理
  11. 【数据结构和算法笔记】c语言实现顺序表和链表
  12. html状态码206,HTTP状态码206
  13. ES6新特性总结之解构赋值和字符串模板
  14. 如何在手机上编码python_如何在Python中进行热编码?
  15. 搜款网根据关键词取商品列表 API 返回值说明
  16. 常见电容器图片_常用电容器大全 (附图片)
  17. JS简单的时间控件分享
  18. rstp 小米网络摄像头_小米哪个家庭摄像头好用?
  19. 关于诡辩--偷换概念
  20. 11.03 CSS的基础应用

热门文章

  1. Java 标准 I/O 流编程学习笔记(下)
  2. win10系统bug:默认中文输入法在系统更新后突然变成了微软拼音
  3. 用KFServing加速联邦学习模型的部署
  4. Java WAV转MP3
  5. 手把手带你学python—牛客网python基础 鸢尾花分类
  6. linux mysql mof提权,mysql提权之mof提权
  7. 华为近场通讯nfc在哪里打开_NFC近场通讯简单介绍
  8. qpython3l如何使用_qpython3l怎么用
  9. pd虚拟机安装linux系统,Mac利用PD虚拟机安装CentOS 7
  10. 增强现实 ar_将AR项目从想象力变为现实