流程变量
一、什么是流程变量
流程变量在activiti 中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和 activiti结合时少不了流程变量,流程变量就是activiti 在管理工作流时根据管理需要而设置的变量。比如在请假流程流转时如果请假天数大于 3 天则由总经理审核,否则由人事直接审核,请假天数就可以设置为流程变量,在流程流转时使用。
注意:
虽然流程变量中可以存储业务数据可以通过 activiti 的 api 查询流程变量从而实现 查询业务数据,但是不建议这样使用,因为业务数据查询由业务系统负责,activiti 设置流程变量是为了流程执行需要而创建。
二、流程变量类型
注意:
如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无法反序列化,需要生成serialVersionUID。
三、流程变量作用域
流程变量的作用域默认是一个流程实例,也可以是一个任务或一个执行实例,这三个作用域流程实例的范围最大,可以成为global变量,任务和执行实例仅仅是针对一个任务和一个执行实例范围,范围没有流程实例大,称为local变量;
global变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值;local变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响;local变量名也可以和global变量名相同,没有影响;
四、流程变量的使用方法
1、设置流程变量
2、通过UEL表达式使用流程变量
2.1 可以在activiti处设置UEL表达式,表达式的值为任务的负责人;
比如:${assignee},assignee就是一个流程变量名称;
activiti获取UEL表达式的值,即流程变量assignee的值,将assignee的值作为任务的负责人进行任务分配;
2.2 可以在连线上设置UEL表达式,决定流程走向;
比如:${price>=10000}和${price<10000};price就是一个流程变量名称,UEL表达式结果类型为布尔类型;
如果UEL表达式是true,要巨鼎流程执行走向;
五、使用global变量控制流程
1、需求
创建请假审批流程,有部门经理审批,部门经理审批通过后请假三天以下有人事经理直接审批,三天以上先有总经理审批,再有人事经理存档;
2、流程定义
请假天数小于等于三天:
请假天数大于三天:
六、设置global流程变量
在部门经理审批前设置流程变量,变量值为请假单信息,部门经理审批后可以根据流程变量的值决定流程走向;
1、启动流程时设置
在启动流程时设置流程变量,变量的作用域是整个流程实例;
通过Map
Holiday实体类:
package com.zn.entity; import java.io.Serializable; import java.util.Date; /** * 业务实体 */ public class Holiday implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String holidayName; //申请人 private Date startDate; //开始时间 private Date endDate; //结束时间 private Integer num; //请假天数 private String reason; //请假事由 private String type; //请假类型 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getHolidayName() { return holidayName; } public void setHolidayName(String holidayName) { this.holidayName = holidayName; } public Date getStartDate() { return startDate; } public void setStartDate(Date startDate) { this.startDate = startDate; } public Date getEndDate() { return endDate; } public void setEndDate(Date endDate) { this.endDate = endDate; } public Integer getNum() { return num; } public void setNum(Integer num) { this.num = num; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
流程部署:
package com.zn; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.junit.Test; public class Holiday01Test { /** * 流程部署 */ @Test public void deployment() { //获取ProcessEngine对象 默认配置文件名称:activiti.cfg.xml 并且configuration的Bean实例ID为processEngineConfiguration ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取RepositoryService对象进行流程部署 RepositoryService repositoryService = processEngine.getRepositoryService(); //进行部署,将对应的流程定义文件生成到数据库当中,作为记录进行保存 Deployment deployment = repositoryService.createDeployment() .addClasspathResource("bmpnfiles/holiday01.bpmn") //加载流程文件 .addClasspathResource("bmpnfiles/holiday01.png") .name("请假流程-流程变量") //设置流程名称 .key("holiday01") .deploy(); //部署 //输出部署信息 System.out.println("流程名称:" + deployment.getName()); System.out.println("流程ID:" + deployment.getId()); System.out.println("流程Key:" + deployment.getKey()); } }
启动流程实例:
package com.zn; import com.zn.entity.Holiday; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.runtime.ProcessInstance; import org.junit.Test; import java.util.HashMap; import java.util.Map; public class Holiday01Test { /** * 启动流程实例 */ @Test public void startInstance() { //获取ProcessEngine对象 默认配置文件名称:activiti.cfg.xml 并且configuration的Bean实例ID为processEngineConfiguration ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取RuntimeService RuntimeService runtimeService = processEngine.getRuntimeService(); //设置流程变量 Holiday holiday = new Holiday(); holiday.setNum(3); //定义一个Map集合,存放流程变量的值 MapassMap = new HashMap<>(); assMap.put("holiday", holiday); //启动流程 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday01", assMap); System.out.println("流程实例启动成功~"); } }
2、任务办理时设置
在完成任务时设置流程变量,该流程只有在该任务完成后其他节点才可使用该变量,它的作用域是整个流程实例,如果设置的流程变量的key在流程实例中已经存在相同的名字则后设置的变量替换前边设置的变量;
这里需要在创建请假单任务完后时设置流程变量;
package com.zn; import com.zn.entity.Holiday; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; public class Holiday01Test { /** * 任务执行时,设置流程变量 */ @Test public void runTask() { //获取ProcessEngine对象 默认配置文件名称:activiti.cfg.xml 并且configuration的Bean实例ID为processEngineConfiguration ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取一个TaskService对象 TaskService taskService = processEngine.getTaskService(); //查询代办业务 createTaskQuery查询任务 taskCandidateOrAssigned查询任务执行者 processDefinitionKey:查询流程 /** * taskCandidateOrAssigned匹配规则:1.Assigned 2.配置bpmn文件中定义的值 * taskAssignee匹配规则:1.Assigned */ Listlist = taskService.createTaskQuery().taskAssignee("lisi").processDefinitionKey("holiday01").list(); for (Task task : list) { System.out.println("任务名称:" + task.getName()); System.out.println("任务执行人:" + task.getAssignee()); System.out.println("任务ID:" + task.getId()); //设置流程变量 Holiday holiday = new Holiday(); holiday.setNum(3); //定义一个Map集合,存放流程变量的值 Map assMap = new HashMap<>(); assMap.put("holiday", holiday); //处理任务 taskService.complete(task.getId(),assMap); System.out.println("流程实例ID:" + task.getProcessInstanceId()); } } }
说明:
通过当前任务设置流程变量,需要指定当前任务id,如果当前执行的任务ID不存在则抛出异常,任务办理时也是通过map
3、通过流程实例ID设置流程变量的值
通过流程实例ID设置全局变量,该流程实例必须未执行完成;
package com.zn; import com.zn.entity.Holiday; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; public class Holiday01Test { /** * 获取到流程实例ID,跟据流程实例设置流程变量的值 */ @Test public void getInstanceVar(){ //获取ProcessEngine对象 默认配置文件名称:activiti.cfg.xml 并且configuration的Bean实例ID为processEngineConfiguration ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取RuntimeService RuntimeService runtimeService = processEngine.getRuntimeService(); //设置流程变量 Holiday holiday = new Holiday(); holiday.setNum(3); //设置流程变量 runtimeService.setVariable("10001","holiday",holiday); } }
注意:
流程实例ID必须当前未结束的的,通常此id设置流程实例的ID,也可以通过runtimeService.getVariable()获取流程变量;
4、根据任务ID,设置流程变量
package com.zn; import com.zn.entity.Holiday; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; public class Holiday01Test { /** * 根据任务ID,设置流程变量 */ @Test public void runTask1() { //获取ProcessEngine对象 默认配置文件名称:activiti.cfg.xml 并且configuration的Bean实例ID为processEngineConfiguration ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取一个TaskService对象 TaskService taskService = processEngine.getTaskService(); //查询代办业务 createTaskQuery查询任务 taskCandidateOrAssigned查询任务执行者 processDefinitionKey:查询流程 /** * taskCandidateOrAssigned匹配规则:1.Assigned 2.配置bpmn文件中定义的值 * taskAssignee匹配规则:1.Assigned */ Listlist = taskService.createTaskQuery().taskAssignee("lisi").processDefinitionKey("holiday01").list(); for (Task task : list) { System.out.println("任务名称:" + task.getName()); System.out.println("任务执行人:" + task.getAssignee()); System.out.println("任务ID:" + task.getId()); //设置流程变量 Holiday holiday = new Holiday(); holiday.setNum(5); taskService.setVariable(task.getId(),"holiday",holiday); //处理任务 taskService.complete(task.getId()); System.out.println("流程实例ID:" + task.getProcessInstanceId()); } } }
注意:
任务ID必须是当前代办任务ID,如果该任务已经结束,就会报异常;
七、注意事项
1、如果UEL表达式中流程变量不存在则报错;
2、如果UEL表达式中流程变量为空NULL,流程不按UEL表达式执行,而流程结束;
3、如果UEL表达式都不符合条件,流程结束;
4、如果连线不设置条件,会走flow序号小的那条线;