五 操作流程定义
5.1 分页查询
@Autowired RepositoryService repositoryService; /** * 分页条件查询流程定义列表数据 */ @Test public void getProcDefList() { ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); String name = "请假"; if(StringUtils.isNotBlank(name)) { // 条件查询 query.processDefinitionNameLike("%"+name+"%"); } // 如果多个相同key, 只查询最新版本的流程定义, query.latestVersion(); // 按key降序 query.orderByProcessDefinitionKey().desc(); // 当前页码 int current = 1; // 每页显示多少条 int size = 5; // 当前页第1条数据的下标 int firstResult = (current-1) * size; // 分页查询 List<ProcessDefinition> processDefinitionList = query.listPage(firstResult, size); for (ProcessDefinition pd : processDefinitionList) { System.out.print("流程部署id:" + pd.getDeploymentId()); System.out.print(",流程定义id:" + pd.getId()); System.out.print(",流程定义key: " + pd.getKey()); System.out.print(",流程定义名称:" + pd.getName()); System.out.print(",版本号:" + pd.getVersion()); System.out.println(",状态:" + ( pd.isSuspended() ? "挂起(暂停)" : "激活(开启)") ); } // 总记录数 long total = query.count(); System.out.println("满足条件的流程定义总记录:" + total); }
5.2 修改流程定义状态
/** * 挂起或激活流程定义 :对应 act_re_procdef 表中的 SUSPENSION_STATE_ 字段,1是激活,2是挂起 * - 流程定义被挂起:此流程定义下的所有流程实例不允许继续往后流转了,就被停止了。 * - 流程定义被激活:此流程定义下的所有流程实例允许继续往后流转。 * - 为什么会被挂起? * - 可能当前公司的请假流程发现了一些不合理的地方,然后就把此流程定义挂起。 * - 流程不合理解决办法: * - 方式一:可以先挂起流程定义,然后更新流程定义,然后激活流程定义。 * - 方式二:挂起了就不激活了,重新创建一个新的请假流程定义。 */ @Test public void updateProcDefState() { // processDefinitionId 为 act_re_procdef 表id String processDefinitionId = "leaveProcess:2:f6a379a1-7cdb-11f6-8052-2c337a6d7e1d"; ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefinitionId) .singleResult(); // 判断是否挂起,true则挂起,false则激活 if(processDefinition.isSuspended()) { // 将当前为挂起状态更新为激活状态 // 参数说明:参数1:流程定义id,参数2:是否激活(true是否级联对应流程实例,激活了则对应流程实例都可以审批),参数3:什么时候激活,如果为null则立即激活,如果为具体时间则到达此时间后激活 repositoryService.activateProcessDefinitionById(processDefinitionId, true, null); }else { // 将当前为激活状态更新为挂起状态 // 参数说明:参数1:流程定义id,参数2:是否挂起(true是否级联对应流程实例,挂起了则对应流程实例都不可以审批),参数3:什么时候挂起,如果为null则立即挂起,如果为具体时间则到达此时间后挂起 repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null); } }
5.3 导出流程定义文件
/** * 导出流程定义文件(xml或png) */ @Test public void exportProcDefFile() throws Exception{ String processDefinitionId = "leaveProcess:2:f6a379a1-7cdb-11f6-8052-2c337a6d7e1d"; ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); // 获取的是 xml 资源名 String resourceName = processDefinition.getResourceName(); // 获取 png 图片资源名 resourceName = processDefinition.getDiagramResourceName(); // 查询到相关的资源输入流 (deploymentId, resourceName) InputStream input = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName); // 创建输出流 File file = new File("D:/" + resourceName); FileOutputStream output = new FileOutputStream(file); IOUtils.copy(input, output); input.close(); output.close(); System.out.println("流程定义资源文件导出成功: " + resourceName); }
六 操作流程实例
6.1 启动流程实例
@Autowired RuntimeService runtimeService; /** * 涉及到的数据表: * ACT_HI_TASKINST * ACT_HI_PROCINST 流程实例 * ACT_HI_ACTINST 节点实例表 * ACT_HI_IDENTITYLINK 流程实例相关办理人 * ACT_RU_EXECUTION * ACT_RU_TASK * ACT_RU_IDENTITYLINK */ @Test public void startProcessInstance() { // 流程定义唯一标识key String processKey = "leaveProcess"; // 业务id String businessKey = "10000"; // 启动当前流程实例的用户(会保存到 act_hi_procinst 表中 start_user_id 字段中) Authentication.setAuthenticatedUserId("catch"); // 启动流程实例(流程定义唯一标识key, 业务id),采用流程key对应的最新版本的流程定义数据 ProcessInstance pi = runtimeService.startProcessInstanceByKey(processKey, businessKey); // 将流程定义名称 作为 流程实例名称 runtimeService.setProcessInstanceName(pi.getProcessInstanceId(), pi.getProcessDefinitionName()); System.out.println("启动流程实例成功:" + pi.getProcessInstanceId()); }
6.2 查询流程实例
6.2.1 查询正在运行的流程实例
/** * 查询正在运行中的流程实例 * 核心表:act_ru_execution ,其中 parent_id 为空,就是正在运行的流程实例 */ @Test public void getProcInstListRunning() { List<ProcessInstance> list = runtimeService.createProcessInstanceQuery() .processInstanceNameLike("%请假%") .list(); for (ProcessInstance pi : list) { System.out.println("流程定义key: " + pi.getProcessDefinitionKey()); System.out.println("流程定义版本号:" + pi.getProcessDefinitionVersion()); System.out.println("流程实例Id: " + pi.getProcessInstanceId()); System.out.println("流程实例名称:" + pi.getName()); System.out.println("业务key(业务主键id):" + pi.getBusinessKey()); System.out.println("发起人:" + pi.getStartUserId()); System.out.println("流程实例状态:" + ( pi.isSuspended() ? "已挂起(暂停)" : "已激活(启动)" ) ); } }
6.3 激活或挂起流程实例
注意:区别于5.2,5.2是修改流程定义的状态,6.3是修改流程实例的状态。
/** * 激活或挂起流程实例 * 流程定义: * 激活:激活流程定义后,对应所有的流程实例都可以继续向下流转 * 挂起:挂起流程定义后,对应所有的流程实例都不可以继续向下流转 * 流程实例: * 激活:激活流程实例后,此流程实例可继续向下流转。 * 挂起:挂起流程实例后,此流程实例不可以向下流转。 */ @Test public void updateProcInstState() { String procInstId = "c1b97f6f-7d0f-11f6-bc11-2c337a6d7e1d"; // 1. 查询指定流程实例的数据 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(procInstId) .singleResult(); // 2. 判断当前流程实例的状态 if(processInstance.isSuspended()) { // 如果是已挂起,则更新为激活状态 runtimeService.activateProcessInstanceById(procInstId); System.out.println("激活流程实例成功"); }else { // 如果是已激活,则更新为挂起状态 runtimeService.suspendProcessInstanceById(procInstId); System.out.println("挂起流程实例成功"); } }
6.4 删除流程实例
@Autowired HistoryService historyService; /** * 删除流程实例: * 涉及到到的数据表: * ACT_RU_IDENTITYLINK * ACT_RU_TASK * ACT_RU_EXECUTION */ @Test public void deleteProcInst() { String procInstId = "11d21740-7f7d-11f6-9f0c-2c337a6d7e1d"; // 1. 查询指定流程实例的数据 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(procInstId) .singleResult(); if(processInstance == null) { System.out.println("流程实例不存在"); return; } // 删除流程实例(流程实例id,删除原因), 不会删除流程实例相关历史数据 runtimeService.deleteProcessInstance(procInstId, "xxx作废了当前流程申请"); // 删除流程实例历史数据 //historyService.deleteHistoricProcessInstance(procInstId); }
七 操作任务
7.1 查询指定办理人任务
@Test public void findWaitTask() { // 办理人 String assignee = "snow"; // 查询个人待办任务 List<Task> list = taskService.createTaskQuery() .taskAssignee(assignee) // 具体办理人 .orderByTaskCreateTime() .desc() .list(); for (Task task : list) { System.out.println("流程实例ID: " + task.getProcessInstanceId()); System.out.println("任务id: " + task.getId()); System.out.println("任务名称:" + task.getName()); System.out.println("任务办理人:" + task.getAssignee()); } }
7.2 查询指定候选人任务
@Test public void findWaitTask() { // 办理人 String assignee = "catch"; List<Task> list = taskService.createTaskQuery() .taskCandidateOrAssigned(assignee) // 作为候选人或者是办理人 .orderByTaskCreateTime() .desc() .list(); for (Task task : list) { System.out.println("流程实例ID: " + task.getProcessInstanceId()); System.out.println("任务id: " + task.getId()); System.out.println("任务名称:" + task.getName()); System.out.println("任务办理人:" + task.getAssignee()); } }
7.3 办理个人任务
/** * 完成任务 */ @Test public void completeTask() { String taskId = "cdbdce28-7e6e-11f6-9939-2c337a6d7e1d"; // 办理前 获取到当前登录人 进行判断 不能办理别人的任务 // 判断完成后,办理 taskService.complete(taskId); }
7.4 拾取候选人任务
候选人 是 出现在组任务中的概念,个人任务不存在候选人的说法;
在组任务中,可以指定多个办理人,多个办理人就是该组任务的候选人。
/** * 拾取候选任务 */ @Test public void claimTask() { String taskId = "6903fa10-7e79-11f6-8210-2c337a6d7e1d"; String userId = "catch"; // 注意:即使拾取任务的办理人,不在候选人中,也可以进行拾取成功。 // 所以最好在拾取之前判断是否为当前任务的候选人 /*List<IdentityLink> identityLinkList = taskService.getIdentityLinksForTask(taskId); for (IdentityLink identityLink : identityLinkList) { System.out.println(identityLink.getUserId()); }*/ // 拾取候选任务,将 catch 作为该组任务的办理人 taskService.claim(taskId, userId); }
7.5 归还组任务
/** * 任务办理人归还组任务中 */ @Test public void assigneeToGroupTask() { String taskId = "6903fa10-7e79-11f6-8210-2c337a6d7e1d"; String assignee = "catch"; //办理人 // 1. 查询办理人任务 Task task = taskService.createTaskQuery() //.processDefinitionKey("此处是key") .taskAssignee(assignee) .singleResult(); // 2. 归还组任务中 if(task != null) { // 直接将办理人设置为null,即归还到了组任务中 taskService.setAssignee(task.getId(), null); } }
7.6 转办任务
/** * 转办任务 */ @Test public void turnTask() { String taskId = "6903fa10-7e79-11f6-8210-2c337a6d7e1d"; String assignee = "catch"; //办理人 String candidateuser = "jones"; // 转办的目标办理人 // 1. 查询办理人任务 Task task = taskService.createTaskQuery() //.processDefinitionKey("此处写key") .taskAssignee(assignee) .taskId(taskId) .singleResult(); // 将任务转办给 jones 用户 if(task != null) { taskService.setAssignee(task.getId(), candidateuser); } }
7.7 办理组任务
将组任务拾取后,就成为了个人任务。办理同7.3。
八 历史数据
8.1 查询个人已办任务
表 ACT_HI_TASKINST
@Autowired HistoryService historyService; @Test public void findCompleteTask() { // 查询 List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery() .taskAssignee("catch") // 办理人 .includeProcessVariables() .orderByTaskCreateTime() .desc() // 任务创建时间降序排列 .finished() .list(); for (HistoricTaskInstance task : taskList) { System.out.print(" 任务ID: " + task.getId()); System.out.print(" ,任务名称: " + task.getName()); System.out.print(" ,任务开始时间: " + task.getStartTime()); System.out.print(" ,任务结束时间: " + task.getEndTime()); System.out.print(" ,办理人: " + task.getAssignee()); System.out.print(" ,流程定义id: " + task.getProcessDefinitionId()); System.out.print(" ,流程实例id: " + task.getProcessInstanceId()); System.out.print(" ,业务id: " + task.getBusinessKey()); System.out.println(",流程变量:" + task.getProcessVariables()); } }
8.2 查询流程实例的办理历史节点信息
@Test public void historyInfo() { // 1. 获取查询对象 HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery(); // 2. 开始查询 List<HistoricActivityInstance> list = query.processInstanceId("流程实例id") .orderByHistoricActivityInstanceStartTime() .asc() .list(); for (HistoricActivityInstance hi : list) { System.out.print("流程定义id:" + hi.getProcessDefinitionId()); System.out.print(",流程实例Id: " + hi.getProcessInstanceId()); System.out.print(",节点id: " + hi.getActivityId()); System.out.print(",节点名称:" + hi.getActivityName()); System.out.println(",任务办理人:" + hi.getAssignee()); } }
8.3 查询已经结束的历史流程实例
@Test public void getProcInstListFinish() { List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery() .orderByProcessInstanceEndTime() .desc() .finished() .list(); for (HistoricProcessInstance hpi : list) { System.out.print("流程实例id: " + hpi.getId()); System.out.print(",流程实例名称:" + hpi.getName()); System.out.print(", 流程标识key:" + hpi.getProcessDefinitionKey()); System.out.print(", 流程定义版本号:" + hpi.getProcessDefinitionVersion()); System.out.print(", 业务id:" + hpi.getBusinessKey()); System.out.print(", 流程发起人:" + hpi.getStartUserId()); System.out.print(", 开始时间:" + hpi.getStartTime()); System.out.print(", 结束时间:" + hpi.getEndTime()); System.out.println(", 删除原因详情:" + hpi.getDeleteReason()); } }
8.4 删除已结束的历史流程实例
/** * 删除已结束的流程实例 * ACT_HI_DETAIL * ACT_HI_VARINST * ACT_HI_TASKINST * ACT_HI_PROCINST * ACT_HI_ACTINST * ACT_HI_IDENTITYLINK * ACT_HI_COMMENT */ @Test public void deleteFinishProcInst() { String procInstId = "流程实例id"; // 1. 查询流程实例是否已结束 HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(procInstId) .finished() .singleResult(); if(instance == null) { System.out.println("流程实例未结束或不存在"); return; } // 2. 删除已结束流程实例(如果实例未结束,会抛出异常,如果需要删除 historyService.deleteHistoricProcessInstance(procInstId); }
九 加流程参数
9.1 启动时加入
@Autowired RuntimeService runtimeService; // 启动流程实例 @Test public void startProcess() { // 流程变量 Map<String, Object> variables = new HashMap<>(); // 加入参数 variables.put("duration", 2); runtimeService.startProcessInstanceByKey("testInclusiveGateway", variables); }
9.2 办理任务时加入流程参数
@Autowired TaskService taskService; @Test public void complete() { String taskId = "5a17a43e-8010-11f6-9aa6-2c337a6d7e1d"; // 流程变量 Map<String, Object> variables = new HashMap<>(); // 请假天数, variables.put("duration", 5); taskService.complete(taskId, variables); }