Event Type
None Event(默认)、Message Event、Error Event、Timer Event
1、选择None Event时启动代码
runtimeService.startProcessInstanceByKey(“myProcess”);
2、Message Event
(1)在主流程属性中定义一个消息定义,名为msg,在开始节点Event Type属性选择Message Event,Message Ref中选msg,这样就可以使用所定义的消息来启动流程了。
(2)启动代码:runtimeService.startProcessInstanceByMessage(“msg”);
3、Error Event
错误事件可用来触发启动子流程,不能用于启动流程实例。下面演示错误开始事件如何触发子流程
(1)在主流程属性中定义一个错误,名为error,在子流程的开始节点Event Type属性选择Error Event,Message Ref中选error,主流程启动后直接执行一个服务任务(上一节演示了服务任务),如果服务任务执行时代码错误就会触发子流程启动,子流程启动后流程流转到UserTask用户任务节点。
(3)服务任务的执行类ThrowErrorDelegate
public class ThrowErrorDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
String errorCode = “500”;
System.out.println(“抛出错误,errorCode为:” + errorCode);
throw new BpmnError(errorCode);
}
}
(4)启动代码
先执行runtimeService.startProcessInstanceByKey(“myProcess”, variableMap);启动主流程,启动后就会执行ThrowErrorDelegate 抛出所定义的500错误,这样就触发启动了子流程。
4、Timer Event计时器事件
可以设置时间点启动一次,也可以用于特定时间间隔内循环启动。子进程不能具有计时器启动事件。无需调用startProcessInstanceByXXX启动流程,并且在startProcessInstanceByXXX调用时将导致再次启动。重新部署具有启动计时器事件的流程时,将删除与先前计时器对应的事件。
要使用定时任务,就要在application.yml中开启开启JOB引擎:activiti.jobExecutorActivate= true
(1)Date时间点
演示通过时间点Date来启动流程,设置2019-12-04T21:50:30时启动流程,直接重新发布流程定义后定时一到就会启动流程,流程节点到达UserTask
(2)Duration间隔
指定定时器之前要等待多长时间。 使用ISO 8601规定的格式 (由BPMN 2.0规定)。Expression中可填写以下格式内容:
P1D:代表1天后执行此时间定时器。
P1H:代表1小时后执行此时间定时器。
P1M:代表1分钟后执行此时间定时器。
(3)Cycle循环
指定定时器之前要等待多长时间。 使用ISO 8601规定的格式 (由BPMN 2.0规定)。Expression中可填写以下格式内容:
R4/2011-03-11T12:13/PT5M 流程将从2011年3月11日12:13开始每隔5分钟启动4次
Initiator
存储发起人id的变量名,在流程图的其他节点的{startUserId},指派了用户任务UserTask给发起人。
(2)启动流程的代码,假如发起流程人的id是123456,identityService.setAuthenticatedUserId(“123456”)相当给变量startUserId赋值为123456,UserTask的处理人就是123456
try {
identityService.setAuthenticatedUserId(“123456”);
Map variableMap = new HashMap();
ProcessInstance pi = runtimeService.startProcessInstanceByKey(“myProcess”, variableMap);
} finally {
identityService.setAuthenticatedUserId(null);
}
Form内置表单
在Activiti Explorer(activiti的一个已经开发好的系统,可以到官网直接下载下来使用)中支持表单属性,并将根据Form这些属性呈现表单,但我们正常来说不会直接使用Activiti Explorer来走流程,而是把activit整合到我们项目中,定义好表单属性后,通过formService.getStartFormData来获取表单属性到前端页面显示,发起流程的人填写表单的数据后通过formService.submitStartFormData来启动流程实例。
Id:一般用来作为页面input输入框的name属性的值。
Name:在页面中input输入框左边的名称,例如性别、姓名等。
Type:数据类型,可填string、long、enum 、date 、boolean 。
Expression:UEL值表达式,开始节点用不到这个,用户任务就可以使用,例如#{myBean.age},表示myBean的age的值赋给这个表单属性,其中myBean是流程变量,例如流程实例启动时设置的流程变量myBean,variableMap.put(“myBean”,myBean);
runtimeService.startProcessInstanceByKey(“myProcess”, variableMap);
Variable:流程变量名称,和Initiator有点相似。
Default:默认值
Date Pattern:时间格式,例如yyyy-MM-dd hh:mm:ss,date类型才设置这个属性
Readable:true/false,是否可读,设置false时formService.getStartFormData获取不到数据
Writable:true/false,是否可写
Required:true/false,是否必填
开始演示:
以下流程图定义三个表单属性分别为string、enum(Values枚举的值,我这里设置了left和right两个枚举值)、date(才有Date Pattern,我这里设置时间格式为yyyy-MM-dd hh:mm:ss)类型。
流程定义发布之后,接下来就是获取所定义的表单属性到前端页面显示:
StartFormData startFormData = formService.getStartFormData(“myProcess:7:45004”);
List formProperties = startFormData.getFormProperties();
在前端页面输入相应的参数之后,提交表单数据就可以使用以下代码启动流程实例,之前是使用runtimeService.startProcessInstanceByKey来启动,现在要使用formService.submitStartFormData来启动:
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put(“sex”,“女”);
paramsMap.put(“direction”,“right”);
paramsMap.put(“time”,“2019-12-14 12:12:12”);
ProcessInstance processInstance = formService.submitStartFormData(“myProcess:7:45004”, paramsMap);查询流程实例的所有填写过的表单历史数据:
List list = historyService.createHistoricDetailQuery().processInstanceId(“40001”)
.formProperties().list();
Form Key外置表单
Form Key用来填写外置表单form文件的路径,为开始节点绑定页面模板,比如我的start.form文件在springboot项目的resources下,那Form Key就写:start.form,可通过formService.getRenderedStartForm来获取表单的内容并打印回前端页面显示,让申请人填写,也是通过formService.getStartFormData发起流程。
开始演示:
1.流程图
2.start.form内容:
性别:
3.发布start.form,发布后formService.getRenderedStartForm才识别form文件
第一种和流程定义一起发布:
repositoryService.createDeployment().addClasspathResource(“processes/myProcess.bpmn”).addClasspathResource(“start.form”).deploy();
第二种:
repositoryService.getResourceAsStream(“流程定义发布deploymentId”, “start.form”);
4.获取form文件内容打印到前端显示
Object renderedStartForm = formService.getRenderedStartForm(“myProcess:9:50005”);
5.前端表单数据提交后,通过以下代码启动流程并保存表单数据
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put(“sex”,“男”);
ProcessInstance processInstance = formService.submitStartFormData(“myProcess:9:50005”, paramsMap);
Execution Listeners 执行监听器
1.Type为Class的情况演示:
设置Class:com.plancode.MyExecutionListener,在注入了两个字段,一个静态字段fixedValue值为开始节点;一个动态字段dynamicValue,值还不知道,启动流程时才给他赋值
流程图:
MyExecutionListener监听器实现代码:
package com.plancode;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.springframework.stereotype.Service;
import java.io.Serializable;
public class MyExecutionListener implements ExecutionListener , Serializable {
private static final long serialVersionUID = 8513750196548027535L;
private Expression fixedValue;
private Expression dynamicValue;
@Override
public void notify(DelegateExecution execution) throws Exception {
System.out.println("fixedValue"+ fixedValue.getValue(execution).toString());
System.out.println("dynamicValue"+ dynamicValue.getValue(execution).toString());
ExecutionEntity executionEntity=(ExecutionEntity) execution;
ActivityImpl activity = executionEntity.getActivity();
String startEvent= activity.getProperty("type")!=null?activity.getProperty("type").toString():"";
if("startEvent".equals(startEvent)){
}
}
}
流程启动代码:
Map variableMap = new HashMap();
variableMap.put("dynamicValue","开始启动");
ProcessInstance pi = runtimeService.startProcessInstanceByKey("myProcess", variableMap);
2.Type为Expression的情况演示:
设置Type为Expression,Expression为${myExecutionListener2.expressionNotify(execution,authenticatedUserId,“开始节点”)},其中authenticatedUserId是流程变量,流程发起者id,expressionNotify的参数可以任意添加
流程图:
MyExecutionListener2监听器实现代码:
package com.plancode;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import java.io.Serializable;
public class MyExecutionListener2 implements Serializable {
private static final long serialVersionUID = 8513750196548027535L;
public void expressionNotify(DelegateExecution execution,String startUserId,String nodeName) throws Exception {
System.out.println(“authenticatedUserId:”+ startUserId);
System.out.println(“nodeName:”+ nodeName);
}
}
启动流程代码:
try {
identityService.setAuthenticatedUserId("123456");
Map variableMap = new HashMap();
variableMap.put("myExecutionListener2",new MyExecutionListener2());
ProcessInstance pi = runtimeService.startProcessInstanceByKey("myProcess", variableMap);
} finally {
identityService.setAuthenticatedUserId(null);
}
3.Type为Delegate Expression的情况演示:
设置Type为Delegate Expression,Delegate Expression为${myExecutionListener},其中myExecutionListener是spring注入的bean,MyExecutionListener加上@Service
流程图:
MyExecutionListener监听器实现代码:
package com.plancode;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.springframework.stereotype.Service;
import java.io.Serializable;
@Service
public class MyExecutionListener implements ExecutionListener , Serializable {
private static final long serialVersionUID = 8513750196548027535L;
@Override
public void notify(DelegateExecution execution) throws Exception {
ExecutionEntity executionEntity=(ExecutionEntity) execution;
ActivityImpl activity = executionEntity.getActivity();
String startEvent= activity.getProperty("type")!=null?activity.getProperty("type").toString():"";
if("startEvent".equals(startEvent)){
}
}
}
启动流程代码:
Map variableMap = new HashMap();
ProcessInstance pi = runtimeService.startProcessInstanceByKey("myProcess", variableMap);