一、前言

 

    上一篇文章我们将流程实例的启动与查询,任务的办理查询都进行了介绍,我们这篇文章来介绍activiti中的流程变量。

 

二、正文

 

    流程变量与我们平常理解的变量是一样的,只不过是用在了我们activiti中,所以称为流程变量,流程变量在整个工作流扮演着很重要的角色。

 

    例如,请假流程中有请假天数、请假原因等一些参数都是流程变量使用的范围,流程变量的作用域范围是只对应一个流程实例。也就是说各个流程实例的流程变量是不互相影响的。流程实例结束完成以后流程变量还保存在数据库中(存放在流程变量的历史表中)。

 

如图:

 

 

    关于流程实例的例子,我们先来看下流程图的processVariables.bpmn的配置文件:

 

 

  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
    <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">
  3.  
    <process id="processVariables" name="processVariables【流程请假】" isExecutable="true">
  4.  
    <startEvent id="startevent1" name="Start"></startEvent>
  5.  
    <endEvent id="endevent1" name="End"></endEvent>
  6.  
    <userTask id="usertask1" name="提交申请"></userTask>
  7.  
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
  8.  
    <userTask id="usertask2" name="审批【总经理】" activiti:assignee="王二"></userTask>
  9.  
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
  10.  
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
  11.  
    </process>
  12.  
    <bpmndi:BPMNDiagram id="BPMNDiagram_processVariables">
  13.  
    <bpmndi:BPMNPlane bpmnElement="processVariables" id="BPMNPlane_processVariables">
  14.  
    <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
  15.  
    <omgdc:Bounds height="35.0" width="35.0" x="350.0" y="90.0"></omgdc:Bounds>
  16.  
    </bpmndi:BPMNShape>
  17.  
    <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
  18.  
    <omgdc:Bounds height="35.0" width="35.0" x="350.0" y="420.0"></omgdc:Bounds>
  19.  
    </bpmndi:BPMNShape>
  20.  
    <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
  21.  
    <omgdc:Bounds height="55.0" width="105.0" x="315.0" y="190.0"></omgdc:Bounds>
  22.  
    </bpmndi:BPMNShape>
  23.  
    <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
  24.  
    <omgdc:Bounds height="55.0" width="105.0" x="315.0" y="300.0"></omgdc:Bounds>
  25.  
    </bpmndi:BPMNShape>
  26.  
    <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
  27.  
    <omgdi:waypoint x="367.0" y="125.0"></omgdi:waypoint>
  28.  
    <omgdi:waypoint x="367.0" y="190.0"></omgdi:waypoint>
  29.  
    </bpmndi:BPMNEdge>
  30.  
    <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
  31.  
    <omgdi:waypoint x="367.0" y="245.0"></omgdi:waypoint>
  32.  
    <omgdi:waypoint x="367.0" y="300.0"></omgdi:waypoint>
  33.  
    </bpmndi:BPMNEdge>
  34.  
    <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
  35.  
    <omgdi:waypoint x="367.0" y="355.0"></omgdi:waypoint>
  36.  
    <omgdi:waypoint x="367.0" y="420.0"></omgdi:waypoint>
  37.  
    </bpmndi:BPMNEdge>
  38.  
    </bpmndi:BPMNPlane>
  39.  
    </bpmndi:BPMNDiagram>
  40.  
    </definitions>


    一个很简单的流程图processVariables.png:

 

 

部署流程定义:

 

  1.  
    /**
  2.  
    * 部署流程定义(从inputStream)
  3.  
    */
  4.  
    @Test
  5.  
    public void deploymentProcessDefinition_inputStream() {
  6.  
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
  7.  
     
  8.  
    InputStream inputStreamBpmn = this.getClass().getResourceAsStream(
  9.  
    "/diagrams/processVariables.bpmn");
  10.  
    InputStream inputStreamPng = this.getClass().getResourceAsStream(
  11.  
    "/diagrams/processVariables.png");
  12.  
    Deployment deployment = processEngine.getRepositoryService()// 与流程定义和部署对象相关的Service
  13.  
    .createDeployment()// 创建一个部署对象
  14.  
    .name("流程定义")// 添加部署名称
  15.  
    .addInputStream("processVariables.bpmn", inputStreamBpmn)// 使用资源文件的名称(要求:与资源文件的名称要一致),和输入流完成部署
  16.  
    .addInputStream("processVariables.png", inputStreamPng)// 使用资源文件的名称(要求:与资源文件的名称要一致),和输入流完成部署
  17.  
    .deploy();// 完成部署
  18.  
    System.out.println("部署ID:" + deployment.getId());
  19.  
    System.out.println("部署名称:" + deployment.getName());
  20.  
    }


运行结果:

 

    部署ID:701

    部署名称:流程定义

 

 

启动流程实例:

 

  1.  
    /**
  2.  
    * 启动流程实例
  3.  
    */
  4.  
    @Test
  5.  
    public void startProcessInstance() {
  6.  
    // 流程定义的key
  7.  
    String processDefinitionKey = "processVariables";
  8.  
    ProcessInstance pi = processEngine.getRuntimeService()// 与正在执行的流程实例和执行对象相关的service
  9.  
    .startProcessInstanceByKey(processDefinitionKey);// 使用流程定义的key启动流程实例,key对应processVariables文件中的id的属性值,使用key值启动,默认是按照最新版本进行启动
  10.  
     
  11.  
    System.out.println("流程实例ID:" + pi.getId());
  12.  
    System.out.println("流程定义ID:" + pi.getProcessDefinitionId());
  13.  
    System.out.println("流程实例ID" + pi.getProcessInstanceId());
  14.  
     
  15.  
    }


运行结果:

 

    流程实例ID:801

    流程定义ID:processVariables:1:704

    流程实例ID801

 

查询任务

 

  1.  
    /**
  2.  
    * 查询任务通过流程实例id
  3.  
    */
  4.  
    @Test
  5.  
    public void findTask(){
  6.  
    String processInstanceId="801";
  7.  
    List<HistoricTaskInstance> list = processEngine.getHistoryService()//与历史数据(历史表)相关的service
  8.  
    .createHistoricTaskInstanceQuery()//创建历史任务实例查询
  9.  
    .processInstanceId(processInstanceId)
  10.  
    .list();
  11.  
    if(list!=null && list.size()>0){
  12.  
    for(HistoricTaskInstance hti:list){
  13.  
    System.out.println(hti.getId()+" "+hti.getName()+" "+hti.getProcessInstanceId()+" "+hti.getStartTime()+" "+hti.getEndTime()+" "+hti.getDurationInMillis());
  14.  
    System.out.println("################################");
  15.  
    }
  16.  
    }
  17.  
    }


运行结果:

 

    804    提交申请   801   Fri Jun 26 10:55:02 CST2015   null   null

    ################################

 

 

    关于部署流程定义、启动流程实例和查询正在办理的任务我们前面的文章已经介绍过了,所以我们不再详细介绍,下面开始我们的设置流程变量,设置流程变量我们这里提供了两种方式,分别是使用基本数据类型和使用javabean的方法,同意获取流程变量也是不一样的:

 

使用基本数据类型:

 

设置流程变量

 

  1.  
    /**
  2.  
    * 设置流程变量
  3.  
    */
  4.  
    @Test
  5.  
    public void setVariables() {
  6.  
    // 与任务相关的service,正在执行的service
  7.  
    TaskService taskService = processEngine.getTaskService();
  8.  
     
  9.  
    // 任务ID
  10.  
    String taskId = "804";
  11.  
     
  12.  
    // 1.设置流程变量,使用基本数据类型
  13.  
    taskService.setVariable(taskId, "请假天数", 7);// 与任务ID邦德
  14.  
    taskService.setVariable(taskId, "请假日期", new Date());
  15.  
    taskService.setVariableLocal(taskId, "请假原因", "回去探亲,一起吃个饭123");
  16.  
     
  17.  
    System.out.println("设置流程变量成功!");
  18.  
     
  19.  
    }

 

运行结果:

 

    设置流程变量成功!

 

获取流程变量

 

  1.  
    /**
  2.  
    * 获取流程变量
  3.  
    */
  4.  
    @Test
  5.  
    public void getVariables() {
  6.  
    // 与任务(正在执行的service)
  7.  
    TaskService taskService = processEngine.getTaskService();
  8.  
    // 任务Id
  9.  
    String taskId = "804";
  10.  
    // 1.获取流程变量,使用基本数据类型
  11.  
    Integer days = (Integer) taskService.getVariable(taskId, "请假天数");
  12.  
    Date date = (Date) taskService.getVariable(taskId, "请假日期");
  13.  
    String reason = (String) taskService.getVariable(taskId, "请假原因");
  14.  
     
  15.  
    System.out.println("请假天数:" + days);
  16.  
    System.out.println("请假日期:" + date);
  17.  
    System.out.println("请假原因:" + reason);
  18.  
     
  19.  
    }


运行结果:

 

    请假天数:7

    请假日期:Fri Jun 2611:07:28 CST 2015

    请假原因:回去探亲,一起吃个饭123

 

 

使用javabean

 

JavaBeanPerson

 

  1.  
    package com.tgb;
  2.  
     
  3.  
    import java.io.Serializable;
  4.  
    import java.util.Date;
  5.  
     
  6.  
    public class Person implements Serializable {
  7.  
     
  8.  
    private static final long serialVersionUID = 361866001729020143L;
  9.  
    //请假天数
  10.  
    private int id;
  11.  
    //请假人
  12.  
    private String name;
  13.  
    //请假原因
  14.  
    private String note;
  15.  
    //请假时间
  16.  
    private Date date;
  17.  
    public Date getDate() {
  18.  
    return date;
  19.  
    }
  20.  
    public void setDate() {
  21.  
    this.date = new Date();
  22.  
    }
  23.  
    public String getNote() {
  24.  
    return note;
  25.  
    }
  26.  
    public void setNote(String note) {
  27.  
    this.note = note;
  28.  
    }
  29.  
    public int getId() {
  30.  
    return id;
  31.  
    }
  32.  
    public void setId(int id) {
  33.  
    this.id = id;
  34.  
    }
  35.  
    public String getName() {
  36.  
    return name;
  37.  
    }
  38.  
    public void setName(String name) {
  39.  
    this.name = name;
  40.  
    }
  41.  
    }



 

设置流程变量

 

  1.  
    /**
  2.  
    * 设置流程变量
  3.  
    */
  4.  
    @Test
  5.  
    public void setVariables() {
  6.  
    // 与任务相关的service,正在执行的service
  7.  
    TaskService taskService = processEngine.getTaskService();
  8.  
     
  9.  
    // 任务ID
  10.  
    String taskId = "804";
  11.  
     
  12.  
    // 设置流程变量,使用javaBean方法
  13.  
    /**
  14.  
    * 当一个javaBean(实现序列号)放置到流程变量中,要求javabean的属性不能在发生变化 如果发生变化,再获取时,抛出异常
  15.  
    *
  16.  
    * 解决方案:在person对象中添加: private static final long
  17.  
    * serialVersionUID="6757393795687480331L"; 同时实现序列号接口
  18.  
    *
  19.  
    */
  20.  
    Person p = new Person();
  21.  
    p.setName("翠花");
  22.  
    p.setId(20);
  23.  
    p.setDate();;
  24.  
    p.setNote("回去探亲,一起吃个饭123");
  25.  
    taskService.setVariable(taskId, "人员信息(添加固定版本)", p);
  26.  
     
  27.  
    System.out.println("设置流程变量成功!");
  28.  
     
  29.  
    }


运行结果:

 

    设置流程变量成功!

 

获取流程变量

 

  1.  
    /**
  2.  
    * 获取流程变量
  3.  
    */
  4.  
    @Test
  5.  
    public void getVariables() {
  6.  
    // 与任务(正在执行的service)
  7.  
    TaskService taskService = processEngine.getTaskService();
  8.  
    // 任务Id
  9.  
    String taskId = "804";
  10.  
     
  11.  
    // 2.获取流程变量,使用javaBean类型
  12.  
    Person p = (Person)taskService.getVariable(taskId, "人员信息(添加固定版本)");
  13.  
    System.out.println(" 请假人: "+p.getName()+" 请假天数: "+p.getId()+" 请假时间:"+ p.getDate()+ " 请假原因: "+p.getNote());
  14.  
     
  15.  
    }


运行结果:

 

    请假人: 翠花  请假天数:  20  请假时间:Fri Jun 26 11:13:44 CST 2015  请假原因: 回去探亲,一起吃个饭123

 

 

查询历史流程变量

 

    可以根据变量名称查询该变量的所有历史信息

 

  1.  
    可以根据变量名称查询该变量的所有历史信息
  2.  
    /**
  3.  
    * 查询流程变量的历史表
  4.  
    */
  5.  
    @Test
  6.  
    public void findHistoryProcessVariables(){
  7.  
    List<HistoricVariableInstance> list = processEngine.getHistoryService()
  8.  
    .createHistoricVariableInstanceQuery()//创建一个历史的流程变量查询对象
  9.  
    .variableName("请假原因")
  10.  
    .list();
  11.  
    if (list!=null &&list.size()>0) {
  12.  
    for (HistoricVariableInstance hvi : list) {
  13.  
    System.out.println(hvi.getId()+" "+hvi.getProcessInstanceId()+" "+hvi.getVariableName()
  14.  
    +" "+hvi.getVariableTypeName()+" "+hvi.getValue());
  15.  
    System.out.println("########################################");
  16.  
    }
  17.  
    }
  18.  
     
  19.  
    }


 

流程变量支持的数据类型:

 

    流程变量支持的数据类型包括:TypeName、string、integer、short、long、double、boolean、data、binary、serializable,我们可以看出流程变量支持的包括了大部分封装类型和Date、String和实现了Serializable接口的类的类型。

 

 

三、总结

 

    我们这篇文章将流程变量的相关知识进行了介绍,除了介绍流程变量的相关定义外还通过具体代码例子介绍了通过不同方式来设置和获取流程变量以及流程变量支持的数据类型。