Activiti常用API,这一篇就够了。
目录
CandidateUser和Parallel Gateway区别
流程部署
两种部署方式,1. 通过代码的方法部署;2. 将流程文件放在一定位置,系统启动的时候自动部署。
手动部署
RepositoryController.deploy
DeploymentBuilder deployment = repositoryService.createDeployment();
InputStream inputStream = new FileInputStream(new File("d:/hello.bpmn"));
deployment.addInputStream("hello.bpmn", inputStream );
deployment.deploy();
系统自动部署
集成SprintBoot,配置流程文件位置,启动即可部署
spring:
activiti:
process-definition-location-prefix: classpath:/processes/
启动流程
RuntimeController
http://localhost:8080/startProcess
//根据 流程key 启动流程,切记不是ID,id是带了版本号的 类似: buyProcess:1:4
ProcessInstance p = this.runtimeService.startProcessInstanceByKey("buyProcess");
System.out.println("流程ID:" + p.getProcessDefinitionId());
System.out.println("实例ID:" + p.getProcessInstanceId());
OUT:
流程ID:buyProcess:1:4
实例ID:2501
startProcessInstanceByKey 是 从表:act_re_procdef中查询
流程实例:act_ru_execution,自动到了第一个节点
注意act_ru_task表
另外:startProcessInstanceByKey的重载方法
1.支持多租户
2.支持参数businesskey,或者变量类型map
查询待执行任务
TaskController
http://localhost:8080/queryTask
TaskQuery query = taskService.createTaskQuery();
/*query.processDefinitionId("流程ID");
query.processInstanceBusinessKey("业务ID");
query.taskCandidateGroup("用户组ID");
query.taskCandidateUser("用户ID");*/
List<Task> list = query.list();
list.forEach(t ->{
System.out.println("流程定义ID:"+t.getProcessDefinitionId());
System.out.println("流程实例ID:"+t.getProcessInstanceId());
System.out.println("任务定义key:"+t.getTaskDefinitionKey());
System.out.println("任务ID:"+t.getId());
System.out.println("流程Name:"+t.getName());
});
OUT:
流程定义ID:buyProcess:1:4
流程实例ID:2501
任务定义key:doCreate
任务ID:2505
流程Name:采购申请
其实都是从act_ru_task表中查询出的。
条件:
/*query.processDefinitionId("流程ID");
query.processInstanceBusinessKey("业务ID");
query.taskCandidateGroup("用户组ID");
query.taskCandidateUser("用户ID");*/
执行任务
TaskController
http://localhost:8080/execTask
// 根据TaskID完成 当前任务
taskService.complete("2505");
OUT:
流程定义ID:buyProcess:1:4
流程实例ID:2501
任务定义key:doCreate
任务ID:2505
流程Name:采购申请
-------------------------------------------
流程定义ID:buyProcess:1:4
流程实例ID:2501
任务定义key:doCheck
任务ID:5002
流程Name:采购审核
表:act_ru_task
表:act_ru_execution
查询任务历史
HistoryController
http://localhost:8080/getHistoryTask
HistoricTaskInstanceQuery query =
this.historyService.createHistoricTaskInstanceQuery();
// 分页代码:query.listPage(firstResult, maxResults)
// 流程定义:query.processDefinitionKey("");
// 业务key:query.processInstanceBusinessKey("");
// 操作人ID:query.taskAssignee("")
/* 操作时间:query.taskCompletedAfter(endDate)
query.taskCompletedBefore(endDate)
query.taskCompletedOn(endDate)*/
List<HistoricTaskInstance> list = query.list();
list.forEach(t -> {
System.out.println(t.getId() + "" + t.getName());
});
// 统计数量 query.count();
分支和条件
在执行上一个节点的时候 设置分支中的变量就行。
- 流程图使用网关
- 网关对于的边需要设置条件
- 执行任务的时候 设置变量值即可
this.taskService.setVariable("5002", "变量名", "变量值");
添加用户
用户,用户组,关联表(坚持关系)
添加用户(表:act_id_user)
User user11 = identityService.newUser("1001");
user11.setFirstName("凯瑞11");
identityService.saveUser(user11);
添加用户组(表:act_id_group)
Group group10 = identityService.newGroup("1000");
group10.setName("Group10");
identityService.saveGroup(group10);
添加关系(表:act_id_membership)
// 管理用户组和用户
identityService.createMembership("1001", "1000");
设置变量
设置流程变量(RuntimeService)的方法:
void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);
//读取变量(基于TaskService)
Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass);
taskService.complete(String taskId, Map<String,Object> variables) //variables下一次任务所需要的参数
taskService.complete(String taskId, Map<String,Object> variables, boolean localScope)
taskId(对应act_ru_task中的id_),variables(下一次任务所需要的参数),localScope(存储范围:本任务)
localScope:(如果为true,通过的变量将会随着本任务存亡(本任务结束,变量删除,称之为任务变量(局部)),默认为false,即为complete(String,Map) 那么这时候的变量为流程变量(全局))
//读取变量(基于execution 执行分支对象)
execution.getVariables();
execution.getVariables(Collection<String> variableNames);
execution.getVariable(String variableName);
execution.setVariables(Map<String, object> variables);
execution.setVariable(String variableName, Object value);
//表达式获取
${userid} //userid 变量
${user.id} //user变量的 getId方法
任务候选和签收
CandidateUser 候选人
taskService.claim(task.getId(),"yubuyun"); 签收
说明:
- 如果一个任务没法确定唯一执行人(Assignee)
- 可以确定是一个范围,可以设置候选组 CandidateGroup
- 如果确定范围中的 哪些人可以操作,那么这个人群就设定为候选人CandidateUser
- 候选人都可以通过id查询到任务,查询到任务先签收,保证这个任务只能自己执行了,当然也可以直接执行。
- 一个任务只能被签收一次,第二次会报异常
- 为此防止抛出异常,可以先查询任务是否被签收
- 签收:this.taskService.claim(taskId, userId);
- claim和setAssignee 区别:claim会检查是否有人签收,然后设置Assignee字段的值。
- claim后照样可以setAssignee值,setAssignee后就不可以claim,报错信息如下:org.activiti.engine.ActivitiTaskAlreadyClaimedException: Task '18' is already claimed by someone else.
补充6代码:
this.taskService.createTaskQuery()
.taskCandidateUser("候选人") // 查询某候选人
.taskUnassigned() // 并且没有被签收过
.list();
委托执行
taskService.delegateTask(task.getId(), "cc");
详细见下面:Owner和 Assignee的区别
会签多实例(待办)
两个或两个以上的机关] 在存档或发出的文件上共同签署。
只有这几个机关同时通过才能走下面的节点。
技术实现:Multi instance 实现即可
加签、减签任务
加签
一般是指固定流程中,原本没有这个人或角色签批的,要临时加人会签人员办理。
减签
就是把加签的,或者原本需要某某批准的,现在删除改审批节点。
加签类型
- 前加签:在当前任务的前面加签,如果选择此操作,则当前待办会消失,等待选择的加签人审批后才能办理当前任务。
- 后加签:即在当前任务的后面加签,选择此操作后会将任务发送给选择的加签人审批,加签人审批后再发给流程设计的下一步人审批。
- 并签:即和当前任务并列审批。
审批方式
- 所有加签人同意才通过:选择的加签人全部同意才通过
- 一个加签人同意即通过:选择的加签人只要有一个人同意就通过
- 按选择的加签人顺序审批:按选择的加签人顺序一个接着一个的审批
CandidateUser和Assignee区别
Assignee :特定一个人来完成一个任务
CandidateUser:候选人用户,可以有多个,用逗号分隔
区别:
1. CandidateUser 可被其中的任何一个人查询到;任何一个执行complete方法后该任务就被执行了。 一般用于组任务执行,即:任务给一个组,比如HR组的任务。
2. Assignee 则是特定指定一个人来完成,比如:直线经理只有一个,特定是被他来完成的。
3. 查询的方法有所不同:
this.taskService.createTaskQuery()
.taskAssignee("[李四1]")
.taskCandidateUser("李四1")
4. 上个节点执行时,设置本节点执行人的方法时不同:
this.taskService.claim("taskid", "userId");
this.taskService.setAssignee("taskid", "userId");
CandidateUser和Parallel Gateway区别
- CandidateUser 是多个人执行一个任务,只要一个人执行完就算完
- Parallel Gateway 是多个任务,一人一个,所有人执行完才算完
- CandidateUser 是执行人指定上的机制
- Parallel Geteway 是Gateway中的一种
Owner和 Assignee的区别
在act_ru_task表中有OWNER_和ASSIGNEE_两个字断。
这两个字段的意义是:
1.ASSIGNEE_(受理人):task任务的受理人,就是执行TASK的人,这个又分两种情况(有值,NULL)
有值的情况:XML流程里面定义的受理人,TASK会直接填入这个人;
NULL:XML没有指定受理人或者只指定了候选组;
没有值的时候,可以使用签收功能去指定受理人,就是候选组里面谁签收谁就成了受理人,即:CandidateUser/Group字段。
2.OWNER_(委托人):受理人委托其他人操作该TASK的时候,受理人就成了委托人OWNER_,其他人就成了受理人ASSIGNEE_
Owner字段就是用于受理人委托别人操作的时候运用的字段。
Task task=taskService.createTaskQuery().singleResult();
//签收
taskService.claim(task.getId(), "billy");
logger.info(taskService.createTaskQuery().singleResult().getAssignee());
//结果:billy
//委托
taskService.delegateTask(task.getId(), "cc");
logger.info(taskService.createTaskQuery().singleResult().getOwner());
logger.info(taskService.createTaskQuery().singleResult().getAssignee());
//结果:owner是Billy,assignee是cc
我不是雷锋,我不写日记。