主要分为一下几个步骤:
1.画图
2.部署流程-把图的信息转入到数据表格中
3.创建流程实例-开始一个流程-实际发起了一个流程
4.执行任务:获取任务+完成任务
1.画图
画了一个简单的流程图,图形文件名称是:qj01.bpmn id:myProcess_1
流程: 请假(qingjia)--->审批(shenpi)--->结束
指定了这一步骤的名称和执行人 Assignee:dcc 执行人时dcc
指定了第二步的名称和执行人 Assignee:jcc 执行人时jcc
2.部署流程
2.1方法1
(本地测试可以用下,实际项目不使用)
private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//流程定义
@Test
public void deploy(){
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment de = repositoryService.createDeployment().addClasspathResource("bpmn/qj01.bpmn").name("qj").deploy(); //这里name里面传入中文,到act_re_deployment表可能出现乱码
System.out.println("部署id"+de.getId());
/*
流程定义:
流程部署表 re_deployment
流程定义表 re_procdef
资源信息表 ge_bytearray
*/
}
addClasspathResource("bpmn/qj01.bpmn"),这里文件是bpmn图形文件的路径
执行,在数据库中查看,影响到3张数据表格:流程部署表 re_deployment 流程定义表 re_procdef 资源信息表 ge_bytearray
2.2方法2:上传压缩文件的方式
2.2.1第一步:把bpmnt图形文件压缩成zip文件
2.2.2编码
这里我省略了上传zip文件的过程,直接从本地读取的
@Test
public void deploy2() throws FileNotFoundException {
RepositoryService repositoryService = processEngine.getRepositoryService();
InputStream in = new FileInputStream("C:\\Users\\Administrator\\IdeaProjects\\jsnhcopy\\src\\main\\resources\\bpmn\\qj01.zip"); //zip文件路径
ZipInputStream zipInputStream = new ZipInputStream(in);
Deployment deploy = repositoryService.createDeployment().addZipInputStream(zipInputStream).name("qjlc").deploy();
System.out.println("部署id"+deploy.getId());
/*
流程定义:
流程部署表 re_deployment
流程定义表 re_procdef
资源信息表 ge_bytearray
*/
}
2.3中文乱码问题
存在中文的时候,出现乱码,尝试了各种方法,都没有生效
1)idea安装目录下两个文件加入配置:-Dfile.encoding=UTF-8,没有用
2)配置idea,无效
file-setting-editor-fileencoding
3)pom文件加入配置,无效
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.1.4.RELEASE</spring.version>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
最后没有办法,只能不用中文
3.创建流程实例-启动流程
//启动流程实例
@Test
public void run(){
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myProcess_1");//表re_procdef里面的key字段
System.out.println("实例id"+myProcess_1.getId());
System.out.println("流程定义id"+myProcess_1.getProcessDefinitionId());
/*
启动流程实例
运行时任务表:ru_task
运行时流程执行表:ru_execution
运行时执行主体信息表:ru_identitylink
*/
}
其中 myProcess_1的值是有图形的id决定的。会成为表act_re_procdef里面的KEY_的值,这个属性用来标识流程。相同的KEY_的流程表示同一流程的不同版本。默认启动的是同一流程的最新版本
执行,影响到三张表 运行时任务表:ru_task 运行时流程执行表:ru_execution 运行时执行主体信息表:ru_identitylink,此时一个流程被发起,有了任务act_ru_task
除了使用KEY_来创建流程实例,还可以通过流程的id等其它属性来创建流程实例 runtimeService.startProcessInstanceById(1)
4.执行任务
4.1获取任务
@Test
public void findtask(){
//获取任务
TaskService taskService = processEngine.getTaskService();
List<Task> task_list = taskService.createTaskQuery().taskAssignee("dcc").list();//查询dcc的任务
task_list.stream().forEach((x)->{
System.out.println("任务id"+x.getId());
System.out.println("任务名称"+x.getName());
});
这里是通过任务执行人来获取的任务,获取的是dcc的任务。这里获取到id为25005的任务
4.2完成任务
@Test
public void complete() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("25005");
System.out.println("完成任务");
/*
任务id2505
完成任务id2505
*/
/*
完成任务:
ru的几张表的数据清楚了
历史相关表:
历史任务表:hi_taskinst
历史流程实例表:hi_procinst
历史流程参与者表:hi_identitylink
历史活动节点表:hi_actinst
*/
}
这里通过任务id来完成任务
在完成了这个任务后,流程就走到了审批流程,表中ru_task表中id为25005任务没有了,出现了一个新的任务-审批
上面执行,完成了第一个步骤-请假,再依照上面,获取任务-完成任务,完成第二个步骤-审批,整个流程就走完了。
流程走完后,此时act_ru_的几张表的数据会清空,历史信息进入历史表,涉及到一下四张表
历史任务表:hi_taskinst
历史流程实例表:hi_procinst
历史流程参与者表:hi_identitylink
历史活动节点表:hi_actinst
5.流程的CRUD
5.1新增
新增一个流程也就是流程部署,也就是上面标题2的内容
5.2修改
流程本身是不能修改的。只能通过发布新的版本的流程来实现。
这个属性,也就是表act_re_procdef的KEY_属性值,相同表示同一流程,版本号增加。
如下图,我共画了3张图,重复发布,总共发布了7次,但是没修改id,流程的KEY_是相同的,都是"myProcess_1",所以KEY_值相同,版本号增加。如果此时通过KEY_来创建流程实例,默认是创建的最新版本的流程实例。
5.3删除
不建议删除
5.4查询
可以通过多个条件去查询KEy_ 、id等
@Test
public void query(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
ProcessDefinitionQuery processDefinitionQuery = processEngine.getRepositoryService().createProcessDefinitionQuery();
List<ProcessDefinition> myProcess_1 = processDefinitionQuery.processDefinitionKey("myProcess_1").list();
if(!myProcess_1.isEmpty()){
myProcess_1.stream().forEach(x->{
System.out.println(x.getKey());
System.out.println(x.getId());
});
}
}
6.历史的查询
6.1查询历史任务
可以通过多种条件查询 id、时间等
@Test
public void queryHi(){
HistoricTaskInstanceQuery historicTaskInstanceQuery = processEngine.getHistoryService().createHistoricTaskInstanceQuery();
List<HistoricTaskInstance> myProcess_11 = historicTaskInstanceQuery.processDefinitionKey("myProcess_1").list();
if(!myProcess_11.isEmpty()){
myProcess_11.stream().forEach(x->{
System.out.println(x.getName());
System.out.println(x.getId());
});
}
}
7.查询流程实例
可以通过多个条件查询,KEY_、id、name等
@Test
public void queryDeployVo(){
ProcessInstanceQuery processInstanceQuery = processEngine.getRuntimeService().createProcessInstanceQuery();
List<ProcessInstance> myProcess_1 = processInstanceQuery.processDefinitionKey("myProcess_1").list();
if(!myProcess_1.isEmpty()){
myProcess_1.stream().forEach(x->{
System.out.println(x.getName());
System.out.println(x.getId());
});
}
}
8.流程中的参数传递
8.1基本说明
这里的参数是指创建流程实例-执行任务中的参数传递。支持的数据类型包括基本数据类型、序列化对象
参数分为两类:任务节点本地变量和全局流程实例变量,前者在流程的指定节点有效,后者整个流程实例过程有效,一般使用后面的
8.2实例
8.2.1流程图
8.2.2部署流程
@Test
public void deploy(){
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment de = repositoryService.createDeployment().addClasspathResource("bpmn/qj01.bpmn").name("qj").deploy();
}
8.2.3启动一个流程实例并传递参数
@Test
public void run(){
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> pa = new HashMap<>();
pa.put("start","qidong");
ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myid2",pa);//表re_procdef里面的key字段
}
这里传递了一个名为start的参数
8.2.4执行任务
先创建一个对象PoTe,序列化,这样子就可以作为参数传递
public class PoTe implements Serializable { //需要序列化
private String username;
private String password;
public PoTe() {
}
public PoTe(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "PoTe{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
执行请假任务
@Test
public void complete() {
TaskService taskService = processEngine.getTaskService();
Object start = taskService.getVariable("40006", "start");
System.out.println("启动变量"+start); //启动变量qidong
taskService.setVariable("40006","username","hahaha");
taskService.setVariable("40006","password","123");
taskService.setVariable("40006","po",new PoTe("hahaha","123"));
/*
Map<String,Object> pa = new HashMap<>();
pa.put("username","hahaha");
pa.put("password","123");
pa.put("po",new PoTe("hahaha","123"));
taskService.setVariables("25005",pa);
*/
taskService.complete("40006");
System.out.println("完成任务");
}
获取到了前面添加的名称为start的变量。并且又添加了三个变量
执行审批任务
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
String username = taskService.getVariable("42507", "username", String.class);
String password = taskService.getVariable("42507", "password", String.class);
String start = taskService.getVariable("42507", "start", String.class);
PoTe po = taskService.getVariable("42507", "po", PoTe.class);
System.out.println(username); //hahaha
System.out.println(password); //123
System.out.println(start); //qidong
System.out.println(po); //PoTe{username='hahaha', password='123'}
Map<String, VariableInstance> variableInstances = taskService.getVariableInstances("42507");
variableInstances.keySet().stream().forEach(x->{
VariableInstance variableInstance = variableInstances.get(x);
System.out.println(variableInstance.toString());
//VariableInstanceEntity[id=42502, name=password, type=string, textValue=123]
//VariableInstanceEntity[id=40002, name=start, type=string, textValue=qidong]
//VariableInstanceEntity[id=42501, name=username, type=string, textValue=hahaha]
//VariableInstanceEntity[id=42504, name=po, type=serializable, byteArrayValueId=42503]
});
taskService.complete("42507");
System.out.println("完成任务 42507");
}
这里获取到了start等4个参数。流程结束。
9.流程不同的分支走向-连线中的表达式
9.1画图
图的文件名:qj02.bpmn 图的id:myid3
这里的流程是:
请假(qjia)--->部门审批(shenpi)--->天数小于等于5->流程结束
--->天数大于5->领导审批(shenpi2)->流程结束
在这条连线设置了条件表达式:days>5
这里连线添加了条件:day<=5
9.2部署流程
//流程定义
@Test
public void deploy(){
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment de = repositoryService.createDeployment().addClasspathResource("bpmn/qj02.bpmn").name("qj").deploy();
System.out.println("部署id"+de.getId());
}
9.3创建流程实例
@Test
public void run(){
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> pa = new HashMap<>();
pa.put("start","qidong");
ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myid3",pa);//表re_procdef里面的key字段
System.out.println("实例id"+myProcess_1.getId());
System.out.println("流程定义id"+myProcess_1.getProcessDefinitionId());
}
9.4.执行任务
9.4.1第一个任务-请假
此时任务表,有一个任务,id为67507,执行人时dcc,也就是请假这一步
执行任务
@Test
public void complete() {
TaskService taskService = processEngine.getTaskService();
taskService.setVariable("67507","days",3);
taskService.complete("67507"); System.out.println("完成任务");
}
注意,这里传递了一个参数days为3
9.4.2第二个任务-部门审批
上面任务执行完成后,再看任务表。有一个任务,id为70002,执行人为jcc,也就是走到了第一个审批
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("70002");
}
执行任务,执行完成后,发现任务表为空,整个流程完成了,因为day为3,所以没有走第二个审批
下面我们把days换做6
9.5创建流程实例
@Test
public void run(){
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> pa = new HashMap<>();
pa.put("start","qidong");
ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myid3",pa);//表re_procdef里面的key字段
}
9.6执行任务
9.6.1第一个任务-请假
任务表有一个任务,id为75007,执行人为dcc,也就是第一步-请假
@Test
public void complete() {
TaskService taskService = processEngine.getTaskService();
taskService.setVariable("85006","days",6);
taskService.complete("85006");
System.out.println("完成任务");
}
注意,这里传递的days的参数是6
9.6.2第二个任务-部门审批
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("87503");
System.out.println("完成任务");
}
9.6.3第三个任务-领导审批
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("90002");
System.out.println("完成任务");
}
执行后,任务表没有任务了,流程走完了
10条件表达式
activiti支持两个UEL表达式:UEL-value和UEL-method
11.网关
11.1排他网关
几条不同的线,只走其中一条线
11.1.1画图
图形名称:qj03.bpmn 图形id:myid4
流程: 请假(qjia)--->请假天数<=5天--->部门审批(shenpi)--->结束
--->请假天数>5天--->领导审批(shenpi2)--->结束
11.1.2代码测试
和上面的代码差不多,我这里就不贴出来了。先测试3天,再测试6天。发现3天时,是部门审批,6天时,是领导审批
11.2并行网关
并行网关是指,几条线都需要执行通过,才能往下走
11.2.1画图
图名:qj04.bpmn id:myid6
流程: 请假(qjia)--->部门审批(shenpi1)+领导审批(shenpi2)--->老板审批(shenpi3)--->结束
这里部门审批和领导审批都需要审批,这里就没有设计条件表达式了,因为都要去审批
11.2.1部署流程
@Test
public void deploy(){
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment de = repositoryService.createDeployment().addClasspathResource("bpmn/qj04.bpmn").name("qj").deploy();
System.out.println("部署id"+de.getId());
}
11.2.2创建流程实例
@Test
public void run(){
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> pa = new HashMap<>();
ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myid6",pa);//表re_procdef里面的key字段
}
11.2.3执行任务
11.2.3.1第一步任务-请假
有一个任务 请假(qjia)
执行任务
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("107505");
System.out.println("完成任务");
}
11.2.3.2第二步-部门审批(shenpi)+领导审批(shenpi2)
上面完成后,任务里面有两个,分别是部门审批(shenpi)和领导审批(shenpi2)
先执行一个审批,随便先执行哪一个都可以
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("110004");
System.out.println("完成任务");
}
一个审批完成后,发现第三步审批任务还没有,任务里面还剩下一个领导审批
继续执行领导审批
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("110007");
System.out.println("完成任务");
}
11.2.3.3第三步-老板审批(shenpi3)
上面2个审批都执行完后,任务里面出现了老板审批(shenpi3)的任务
执行
@Test
public void complete2() {
TaskService taskService = processEngine.getTaskService();
taskService.complete("115003");
System.out.println("完成任务");
}
执行完成后,没有任务了,流程执行完
12.任务分配
前面我们画图的时候,每一步任务由谁执行,都是固定写死的,现在我们使用表达式
写死的:
表达式:
12.1画图
图形bpmn文件名称:qj05.bpmn id:myid11
流程:员工(employee)请假--->部门领导审批(leader)--->结束
12.2部署流程
//流程定义
@Test
public void deploy(){
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment de = repositoryService.createDeployment().addClasspathResource("bpmn/qj05.bpmn").name("qj").deploy();
System.out.println("部署id"+de.getId());
}
12.3启动流程实例
//启动流程实例
@Test
public void run(){
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> pa = new HashMap<>();
pa.put("employee","ddd");
ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myid10",pa);//表re_procdef里面的key字段
}
启动流程的时候,设置哪些人可以请假,这里设置ddd可以请假
此时有任务,执行人就是ddd
12.4执行任务
12.4.1第一步-请假
ddd可以获取到任务,并执行
获取
@Test
public void findtask(){
//获取任务
TaskService taskService = processEngine.getTaskService();
List<Task> task_list = taskService.createTaskQuery().taskAssignee("ddd").list();//查询dcc的任务
}
执行,执行时指定由谁来审批,这里指定的是jjj
@Test
public void complete() {
TaskService taskService = processEngine.getTaskService();
taskService.setVariable("150006","leader","jjj");
taskService.complete("150006");
System.out.println("完成任务");
}
12.4.2第二步-审批
jjj获取任务并执行
@Test
public void findtask(){
//获取任务
TaskService taskService = processEngine.getTaskService();
List<Task> task_list = taskService.createTaskQuery().taskAssignee("jjj").list();//查询dcc的任务
}
执行
@Test
public void complete() {
TaskService taskService = processEngine.getTaskService();
taskService.setVariable("152503","leader","jjj");
taskService.complete("152503");
System.out.println("完成任务");
}
流程走完了,任务没有了