目录
一、前言
二、流程变量介绍
1、设置流程变量
2、在流程线上使用流程变量
3、流程变量存储
4、经验总结
一、前言
流程变量也是流程使用中一个很重要的东西,主要承担传递业务参数的作用,其作用范围仅在当前流程实例中有效,因此也常用来指定某个环节的任务处理人。本文就简单介绍下流程变量的设置、传递和获取,流程还是基于系列三的请假流程。
二、流程变量介绍
先看下面给出的一份流程案例代码:
@Test
public void variableDemoTest() {
// 发布流程
Deployment deployment = repositoryService.createDeployment().name("请假小流程").addClasspathResource("processes/vocationDemo.bpmn20.xml").deploy();
// 启动一个流程实例,同时设置流程变量,可以通过在启动或完成任务的时候传递变量,当然也可以单独设置变量
Map<String, Object> variableMap = new HashMap<>();
// 基本类型的变量在activiti中可直接存储
variableMap.put("userId", "123");
variableMap.put("leaveDays", 3);
variableMap.put("leaveTime", new Date());
// 对象以流的方式存储,包括javabean类型(必须实现序列化接口)
variableMap.put("users", Lists.newArrayList("zhangsan"));
variableMap.put("user", new User("李四"));
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vocation", variableMap);
// 查询所有任务
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).list();
System.out.println("Task size:" + tasks.size());
Task task = tasks.get(0);
// 也可以为某个任务单独设置变量,单独设置变量在实际中其实不建议存储到activiti中,由业务方自行存储比较好
taskService.setVariable(task.getId(), "当前任务处理人", task.getAssignee());
// 获取变量
System.out.println("直属经理任务处理人" + taskService.getVariable(task.getId(), "当前任务处理人"));
}
1、设置流程变量
设置流程变量大概可以分为两种:
- 基本类型变量设置
- javaBean变量设置
且流程变量一般都是使用在流程启动、流转或完成的阶段,为了传递某些业务参数使得在业务监听器中能获取到这些变量,以完成业务方自己的需求,因此单独设置流程变量在Activiti中其实是不推荐的,即使用taskService的设置变量方式,一般由业务方自行实现即可。
2、在流程线上使用流程变量
流程变量的另一个用处便是作用在流程线上,当某个环节有多个出线时,Activiti需要知道该走那一条出线,这时就需要在线上使用流程变量来判断流程走向,下面为了演示将会建一个新的请假流程,使用Activiti-app绘制的流程图如下:
可以看到直属经理审批环节的出线有两条,当请假超过三天时还需要经过总经理审批,否则可直接结束,对于这种多出线的情况,我们便可以在流程线上设置变量条件来满足,点击请假超过三天流程线,然后配置对应执行条件,如下:
${}是特定的格式,中间的内容要使用boolean类型的表达式,用来判断所要执行的连线,nextBranch即指定的流程变量名称。然后保存当前流程并导出xml文件,为方便你们做案例,给出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/processdef">
<process id="vocation" name="多分支请假流程" isExecutable="true">
<startEvent id="startEvent1"></startEvent>
<userTask id="sid-042D76FB-6812-4099-A8E1-3CCC4A8D1896" name="直属经理审批" activiti:candidateUsers="test">
<extensionElements>
<modeler:user-info-firstname-test xmlns:modeler="http://activiti.com/modeler"><![CDATA[test]]></modeler:user-info-firstname-test>
<modeler:activiti-idm-candidate-user xmlns:modeler="http://activiti.com/modeler"><![CDATA[true]]></modeler:activiti-idm-candidate-user>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sid-D3C4F10F-0829-4168-8AF4-40B7FF375217" sourceRef="startEvent1" targetRef="sid-042D76FB-6812-4099-A8E1-3CCC4A8D1896"></sequenceFlow>
<userTask id="sid-32EDE0A5-D28C-474B-86F0-E0221DD5D26E" name="总经理审批" activiti:candidateUsers="test">
<extensionElements>
<modeler:user-info-firstname-test xmlns:modeler="http://activiti.com/modeler"><![CDATA[test]]></modeler:user-info-firstname-test>
<modeler:activiti-idm-candidate-user xmlns:modeler="http://activiti.com/modeler"><![CDATA[true]]></modeler:activiti-idm-candidate-user>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<endEvent id="sid-5879817C-644B-4A5E-86B8-16ED025C91AF"></endEvent>
<sequenceFlow id="sid-FFBFCF5B-5B4D-420A-8D82-06506D546993" sourceRef="sid-32EDE0A5-D28C-474B-86F0-E0221DD5D26E" targetRef="sid-5879817C-644B-4A5E-86B8-16ED025C91AF"></sequenceFlow>
<sequenceFlow id="sid-A37138F4-6D40-4EB7-961A-0242D63D8F9D" name="请假超过三天" sourceRef="sid-042D76FB-6812-4099-A8E1-3CCC4A8D1896" targetRef="sid-32EDE0A5-D28C-474B-86F0-E0221DD5D26E">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${nextBranch=='超过三天'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="sid-D371A73D-E97E-45D3-ABEE-48221B30BBC0" name="请假天数较短" sourceRef="sid-042D76FB-6812-4099-A8E1-3CCC4A8D1896" targetRef="sid-5879817C-644B-4A5E-86B8-16ED025C91AF">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${nextBranch=='三天以内'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_vocation">
<bpmndi:BPMNPlane bpmnElement="vocation" id="BPMNPlane_vocation">
<bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
<omgdc:Bounds height="30.0" width="30.0" x="120.0" y="163.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-042D76FB-6812-4099-A8E1-3CCC4A8D1896" id="BPMNShape_sid-042D76FB-6812-4099-A8E1-3CCC4A8D1896">
<omgdc:Bounds height="80.0" width="100.0" x="240.0" y="140.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-32EDE0A5-D28C-474B-86F0-E0221DD5D26E" id="BPMNShape_sid-32EDE0A5-D28C-474B-86F0-E0221DD5D26E">
<omgdc:Bounds height="80.0" width="100.0" x="405.0" y="30.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-5879817C-644B-4A5E-86B8-16ED025C91AF" id="BPMNShape_sid-5879817C-644B-4A5E-86B8-16ED025C91AF">
<omgdc:Bounds height="28.0" width="28.0" x="585.0" y="164.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-D3C4F10F-0829-4168-8AF4-40B7FF375217" id="BPMNEdge_sid-D3C4F10F-0829-4168-8AF4-40B7FF375217">
<omgdi:waypoint x="149.99875145663177" y="178.19353227685977"></omgdi:waypoint>
<omgdi:waypoint x="240.0" y="179.35483870967744"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-D371A73D-E97E-45D3-ABEE-48221B30BBC0" id="BPMNEdge_sid-D371A73D-E97E-45D3-ABEE-48221B30BBC0">
<omgdi:waypoint x="340.0" y="179.67637540453075"></omgdi:waypoint>
<omgdi:waypoint x="585.000293242847" y="178.09061298871944"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-FFBFCF5B-5B4D-420A-8D82-06506D546993" id="BPMNEdge_sid-FFBFCF5B-5B4D-420A-8D82-06506D546993">
<omgdi:waypoint x="505.0" y="107.5"></omgdi:waypoint>
<omgdi:waypoint x="587.8" y="169.6"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-A37138F4-6D40-4EB7-961A-0242D63D8F9D" id="BPMNEdge_sid-A37138F4-6D40-4EB7-961A-0242D63D8F9D">
<omgdi:waypoint x="340.0" y="146.66666666666666"></omgdi:waypoint>
<omgdi:waypoint x="405.0" y="103.33333333333333"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
接着同之前的代码一样,赋予nextBranch变量分别不同的值来查看效果:
@Test
public void multiBranchDemoTest() {
// 1、发布流程
Deployment deployment = repositoryService.createDeployment().name("多分支请假流程").addClasspathResource("processes/vocationDemo2.bpmn20.xml").deploy();
// 2、启动一个流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vocation");
// 3、查询所有任务
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).list();
Task task = tasks.get(0);
// 4、完成直属经理审批环节任务的同时设置流程变量,来告诉Activiti该走哪条线
Map<String, Object> variables = new HashMap<>();
variables.put("nextBranch", "超过三天");
taskService.complete(task.getId(), variables);
}
可以看到运行任务表act_ru_task中当前流程实例自动流转总经理审批环节了
改变nextBranch的值为"三天以内"此时则直接流转结束。
当该流程变量的值无法匹配所有流程线上定义的值时则会抛错,因此在实际业务使用时通常设该值为流程线的id,当然流程线的配置也支持选中是否为默认线,即不满足任何条件时执行该条流程线,但是除了判断网关不同环节的多出线一般不设置。
3、流程变量存储
Activiti的流程变量基本都存储在act_ru_variable表中,上面六个变量在表中的存储如下:
可以看到基本类型的变量类型都得以保留,而javaBean类型都是以流的方式存储,因此javeBean必须实现序列化接口,具体数据都是以二进制方式存储在act_ge_bytearray,后面的7509和7512即作为关联字段,可以看到act_ge_bytearray表内容如下:
如果需要在流程流转过程中设置变量,建议将变量存储在业务方自己的表中,与Activiti进行区分,比如在流程线上有设置变量的需求等等。
4、经验总结
由上面可以发现对于那些javaBean的变量,Activiti都是存储到act_ge_bytearray表中,因此在使用流程变量的过程中,请不要将太多的大变量存储到Activiti中,否则日以夜继,Activiti在查询该表的时候性能会受到很大影响,整个业务方也将受到影响。