最近因为公司需要整流程,所以研究了下activiti。顺便记录下相关的东西。创建流程,任务认领,任务完成,任务驳回,任务结束,解析节点信息,解析模板,理解启动流程。
springboot2.X 结合aitiviti 参考
springboot2.2.2.RELEASE 集成Activiti**实践_叶巨岩的博客-CSDN博客
启动流程两种方式记录:
第一种就是加载模板信息后:
@Test public void loadModel(){ //第一步 部署流程文件 Deployment deployment = repositoryService//这里repositoryService是直接注入的 引擎包里面已经有了 .createDeployment() .name("测试3") .key("123") .addClasspathResource("processes/myProcesses.bpmn").deploy(); } //根据流程定义id 启动一个 流程实例 ProcessInstance processInstance = runtimeService.startProcessInstanceById("myProcess01",null,null); //myProcess01 是 模板的id
讯享网
第二种就是比较灵活的:
这里是你加载了一个模板后都会生成一个 ProcessDefinition 在表act_procdef_info中你可看到相关信息。这种就是比较灵活的,你可以根据它的名称或者key值 得到你想要实例的流程。你每改动一次 你的模板重新加载后才能生效,这个表就会再次生成一个记录,用version控制版本是最新的。中途不要改动模板的key和id
讯享网List<ProcessDefinition> list= repositoryService.createProcessDefinitionQuery().latestVersion().list();//这里是你加载了一个模板后都会生成一个 ProcessDefinition 在表act_procdef_info中你可看到相关信息。这种就是比较灵活的,你可以根据它的名称或者key值 得到你想要实例的流程。你每改动一次 你的模板重新加载后才能生效,这个表就会再次生成一个记录,用version控制版本是最新的。中途不要改动模板的key和id //启动一个流程 ProcessInstance processInstance = runtimeService.startProcessInstanceById(list.get(0).getId, businessId, variables);
接下来就是写了一些公共的方法抽取出来:
package com.dotmap.iomt.app.workflow.activitiUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.FlowElement; import org.activiti.bpmn.model.FlowNode; import org.activiti.bpmn.model.Process; import org.activiti.bpmn.model.SequenceFlow; import org.activiti.engine.ActivitiTaskAlreadyClaimedException; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.impl.identity.Authentication; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.Execution; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Comment; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; / * @title 操作流程的工具类 * @author: wangtingsong * @Date: 2020/6/20 11:47 * @since 版本号 */ @Service @Slf4j public class ActivitiUtil { @Autowired TaskService taskService; @Autowired RuntimeService runtimeService; @Autowired RepositoryService repositoryService; @Autowired HistoryService historyService; / * @param processDefinitionId 流程定义id 必须 * @param candidateUserIds 设置第一步领取审核的人多个, 可为空 * @param variables 全局参数内容 可为空 * @param businessId 业务参数 可为空 * @return */ public String startProcess(String processDefinitionId, List<String> candidateUserIds, Map<String, Object> variables, String businessId) { log.info("启动流程参数processDefinitionId:{},candidateUserIds:{}, variables:{}, businessId:{}", processDefinitionId, candidateUserIds, variables, businessId); //启动一个流程 ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessId, variables); //设置用户审核 if (!CollectionUtils.isEmpty(candidateUserIds)) { //查询出第一步的task任务 并设置有权限审核的用户 Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); for (String candidateUserId : candidateUserIds) { taskService.addCandidateUser(task.getId(), candidateUserId); } } return processInstance.getId(); } / * 获取最新版本的所有的流程定义列表 * * @return */ public List<ProcessDefinition> getLastVersionProcessDefinitions() { //我们需要的是最新的版本 return repositoryService.createProcessDefinitionQuery().latestVersion().list(); } / * 根据流程定义id 获取到对应的模板节点信息 节点名称,节点id,监听事件也可以获取 * * @param processDefinitionId * @return */ public List<FlowElement> getFlowElementByProcessDefId(String processDefinitionId) { log.info("根据流程定义获取节点信息入参:{}", processDefinitionId); //流程定义中的模板信息 BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); //模板中的所有流程 List<Process> processes = bpmnModel.getProcesses(); log.info("流程定义id:{}的流程条数大小:{}", processDefinitionId, processes.size()); //取得流程的节点包括 连线实体 Process process = processes.get(0); //把所有节点 用map装好。 Map<String, FlowElement> flowElements = process.getFlowElementMap(); List<FlowElement> flowElementList = new ArrayList<>(); if (CollectionUtils.isEmpty(flowElements)) { return flowElementList; } //转换一下 成为list for (Map.Entry<String, FlowElement> flowElement : flowElements.entrySet()) { flowElementList.add(flowElement.getValue()); } return flowElementList; } / * 根据流程实例id 获取到当前的流程进度 task * * @param processInstanceId * @return */ public Task getCurrentTaskByProcessIntanceId(String processInstanceId) { return taskService .createTaskQuery() .processInstanceId(processInstanceId) .singleResult(); } / * 根据用户id 或者该用户的所有 有权限审核的流程task * * @param userId * @return */ public List<Task> getAuthorityTaskByUserId(String userId) { return taskService .createTaskQuery() .taskCandidateUser(userId) .taskUnassigned() .list(); } / * 用户认领task,如果该用户有权限并且该task未被认领 * * @param taskId * @param userId */ public void claimTaskByUserId(String taskId, String userId) throws Exception { try { taskService.claim(taskId, userId); } catch (ActivitiTaskAlreadyClaimedException e) { log.warn("该任务已经被认领taskId:{},userId:{}", taskId, userId); throw new Exception("该任务已经被其他的人认领"); } catch (Exception e) { log.warn("无权限认领该任务:{},userId:{}", taskId, userId); } } / * 根据用户id 获取需要立即审核的流程task * * @param userId * @return */ public List<Task> getAssignedTaskByUserId(String userId) { return taskService.createTaskQuery().taskAssignee(userId).list(); } / * 完成当前节点 进入到下一步。 * * @param taskId 任务id * @param variables 下一步需要的参数 可为空 * @param userId 用户id * @param comment 完成时的批注内容 * @throws Exception */ public void completeTask(String taskId, Map<String, Object> variables, String userId,String comment) throws Exception { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); if (Objects.isNull(task)) { log.info("该任务taskId:{},已被完成或者不存在", taskId); throw new Exception("任务已被完成或者不存在"); } if (Objects.nonNull(task) && !userId.equals(task.getAssignee())) { log.info("该用户没有权限完成处理该任务taskId:{},userId:{},yUserId:{}", taskId, userId, task.getAssignee()); throw new Exception("该用户没有权限完成处理该任务"); } //如果批注信息不为空,新增批注信息内容 if (StringUtils.isNotBlank(comment)){ taskService.addComment(taskId, task.getProcessInstanceId(), comment); } taskService.complete(taskId, variables); } / * 根据实例id 获取已经完成的节点 * * @param processInstanceId * @return */ public List<HistoricTaskInstance> getHistoryTaskByProcessInstanceId(String processInstanceId) { return historyService .createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .finished().orderByTaskCreateTime().desc().list(); } / * 根据用户id获取到 用户处理过的所有任务信息 * @param userId * @return */ public List<HistoricTaskInstance> getHistoryTaskByUserId(String userId){ return historyService .createHistoricTaskInstanceQuery() .taskAssignee(userId).finished() .orderByTaskCreateTime().desc().list(); } / * 根据流程实例id 结束任务 任何时候都可以结束 * * @param processId * @return */ public void finishProcess(@RequestParam("processId") String processId) throws Exception { try { runtimeService.deleteProcessInstance(processId, "结束"); } catch (Exception e) { log.error("流程结束异常processId:{},异常信息:{}", processId, e); throw new Exception("任务结束异常"); } Task task = taskService.createTaskQuery().processInstanceId(processId).singleResult(); if (null == task) { log.info("已结束该任务实例id:{}", processId); } } / * 根据taskId 获取批注消息 * @param taskId 任务id * @return */ public Comment getComment(@RequestParam("taskId") String taskId){ return taskService.getComment(taskId); } / * 撤回或者驳回任务, 撤回是当前处理人 处理任务后后悔了,在下一个处理人还未处理的情况可以撤回 * 驳回:当前处理人 查看任务后发现上一步处理人未处理到位,可以驳回到上一个人。 * * @param processInstanceId 流程实例id * @param userId 当前用户id * @param setUserId 撤回或者驳回后的 设置用户处理人id * @param recallOrRebutFlag 是撤回还是驳回标识 1代表撤回 2代表驳回 * @param comment 撤回或者驳回时的批注内容 * @throws Exception */ public void cancel(String processInstanceId, String userId, String setUserId, Integer recallOrRebutFlag, String comment) throws Exception { log.info("撤回或者驳回的任务的参数processInstanceId:{}, userId:{},serUserId:{}, recallOrRebutFlag:{}", processInstanceId, userId, setUserId, recallOrRebutFlag); //参数验证 if (StringUtils.isBlank(processInstanceId)) { throw new Exception("流程实例id不能为空"); } if (StringUtils.isBlank(userId)) { throw new Exception("当前用户id不能为空"); } if (StringUtils.isBlank(setUserId)) { throw new Exception("撤回或者驳回后的处理人id不能为空"); } if (Objects.isNull(recallOrRebutFlag)) { throw new Exception("撤回或这驳回类型不能为空"); } //获取当前的task Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult(); if (task == null) { log.info("任务节点已完成或者未启动,无法撤回processInstanceId:{}", processInstanceId); throw new Exception("任务节点已完成或者未启动"); } //根据时间的正序 输出,最后的一个就是正在进行中的节点任务。 List<HistoricTaskInstance> historicTaskInstances = historyService .createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .orderByTaskCreateTime().asc().list(); //撤回的应该是 正在进行中的上一个节点 HistoricTaskInstance myTask = null; for (int i = 0; i < historicTaskInstances.size(); i++) { if (historicTaskInstances.get(i).getId().equals(task.getId()) && i > 0) { myTask = historicTaskInstances.get(i - 1); break; } } if (myTask == null) { log.error("流程实例id,{},上一步任务节点为空"); throw new Exception("上一步任务节点为空,无法撤回或驳回"); } log.info("流程实例id,{}的上一个节点的id:{},节点处理人:{}", myTask.getId(), myTask.getAssignee()); //权限校验 if (recallOrRebutFlag.equals(1)) { if (!userId.equals(myTask.getAssignee())) { log.info("流程实例id:{},用户id:{}无权限,需要用户id为:{}处理撤回", processInstanceId, userId, myTask.getAssignee()); throw new Exception("无权限撤回"); } } else if (recallOrRebutFlag.equals(2)) { if (!userId.equals(task.getAssignee())) { log.info("流程实例id:{},用户id:{}无权限,需要用户id为:{}处理驳回", processInstanceId, userId, myTask.getAssignee()); throw new Exception("无权限驳回"); } } else { log.info("流程实例id:{},类型标识:{},不是撤回也不是驳回类型", processInstanceId, recallOrRebutFlag); throw new Exception("类型标识无法识别"); } //获取到当前节点的上一个节点的id String myTaskId = myTask.getId(); String processDefinitionId = myTask.getProcessDefinitionId(); //获取上一个节点流程定义 ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService .createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); //获取到 历史的activity 节点 List<HistoricActivityInstance> haiList = historyService .createHistoricActivityInstanceQuery() .executionId(myTask.getExecutionId()) .finished().list(); String myActivityId = null; for (HistoricActivityInstance hai : haiList) { if (myTaskId.equals(hai.getTaskId())) { myActivityId = hai.getActivityId(); break; } } FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId); Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult(); //获取当前节点的 活动节点 String activityId = execution.getActivityId(); log.info("流程实例id:{},需要撤回的活动id:{},当前活动id:{}", processInstanceId, myActivityId, activityId); //获取当前的 node FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId); //记录当前task的节点活动方向 List<SequenceFlow> oriSequenceFlows = new ArrayList<>(); oriSequenceFlows.addAll(flowNode.getOutgoingFlows()); //清理当前的活动方向 flowNode.getOutgoingFlows().clear(); //建立新的方向 List<SequenceFlow> newSequenceFlowList = new ArrayList<>(); SequenceFlow newSequenceFlow = new SequenceFlow(); newSequenceFlow.setId("newSequenceFlowId"); newSequenceFlow.setSourceFlowElement(flowNode); newSequenceFlow.setTargetFlowElement(myFlowNode); newSequenceFlowList.add(newSequenceFlow); flowNode.setOutgoingFlows(newSequenceFlowList); taskService.addComment(task.getId(), task.getProcessInstanceId(), comment); taskService.complete(task.getId()); //设置回原来的 方向 flowNode.setOutgoingFlows(oriSequenceFlows); //再次获取到当前的 活动节点就已经是 撤销后的节点了 Task cuTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult(); //设置受理人 taskService.setAssignee(cuTask.getId(), setUserId); } }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/54842.html