目录

一、前言

二、流程变量介绍

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绘制的流程图如下:

activiti variables变量_Activiti

可以看到直属经理审批环节的出线有两条,当请假超过三天时还需要经过总经理审批,否则可直接结束,对于这种多出线的情况,我们便可以在流程线上设置变量条件来满足,点击请假超过三天流程线,然后配置对应执行条件,如下:

activiti variables变量_流程变量_02

${}是特定的格式,中间的内容要使用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中当前流程实例自动流转总经理审批环节了

activiti variables变量_Activiti_03

改变nextBranch的值为"三天以内"此时则直接流转结束。

当该流程变量的值无法匹配所有流程线上定义的值时则会抛错,因此在实际业务使用时通常设该值为流程线的id,当然流程线的配置也支持选中是否为默认线,即不满足任何条件时执行该条流程线,但是除了判断网关不同环节的多出线一般不设置。

 

3、流程变量存储

Activiti的流程变量基本都存储在act_ru_variable表中,上面六个变量在表中的存储如下:

activiti variables变量_java_04

可以看到基本类型的变量类型都得以保留,而javaBean类型都是以流的方式存储,因此javeBean必须实现序列化接口,具体数据都是以二进制方式存储在act_ge_bytearray,后面的7509和7512即作为关联字段,可以看到act_ge_bytearray表内容如下:

activiti variables变量_java_05

如果需要在流程流转过程中设置变量,建议将变量存储在业务方自己的表中,与Activiti进行区分,比如在流程线上有设置变量的需求等等。

4、经验总结

由上面可以发现对于那些javaBean的变量,Activiti都是存储到act_ge_bytearray表中,因此在使用流程变量的过程中,请不要将太多的大变量存储到Activiti中,否则日以夜继,Activiti在查询该表的时候性能会受到很大影响,整个业务方也将受到影响。