工作流flowable在项目中的应用实例 您所在的位置:网站首页 工作流的使用场景 工作流flowable在项目中的应用实例

工作流flowable在项目中的应用实例

2024-03-06 23:39| 来源: 网络整理| 查看: 265

目前的项目主要有两个审批流程,在审批过程中需要发送邮件给申请人告知目前进展,此处记录下我在项目中是如何使用flowable工作流与业务相结合的。

1. 添加工作流依赖

org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.0 org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-starter-data-rest mysql mysql-connector-java runtime com.alibaba druid 1.0.9 org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-mail org.springframework.security spring-security-web com.alibaba fastjson 1.2.61 com.fasterxml.jackson.core jackson-annotations org.aspectj aspectjrt org.apache.shiro shiro-spring 1.4.1 org.slf4j slf4j-api org.slf4j slf4j-log4j12 commons-lang commons-lang 2.6 org.apache.commons commons-lang3 org.apache.poi poi 3.14 org.apache.poi poi-ooxml 3.14 com.jcraft jsch 0.1.55 commons-net commons-net 3.6 org.flowable flowable-spring-boot-starter-process 6.4.0

2. 在application.yml中增加配置项

flowable: check-process-definitions: false #设置需要手动部署工作流

3. 画流程图

设置审批候选人为固定的某个色的所有人

实际应用中,除了需要将流程完整的结束,我们通常需要跟踪业务状态,通常每个处理节点都会对应一个业务状态,此处指定方法负责更新状态和发送邮件

 

4. 由于每个业务系统都会有自己的用户角色权限管理,因此需要与flowable的用户组关系保持同步,一种方法是利用监听器,当业务系统编辑用户信息时就同步至flowable用户表中,另一种就是删除flowable的用户组关系表,利用视图将业务系统的用户组关系同步至flowable的用户组关系表中,并且视图名称与原flowable用户组关系表名称相同

5. 代码

###部署工作流### @Transactional(readOnly = false) public Object deploy (final String processName) { logger.info("---- FlowService deploy begin ----"); final Deployment deployment = processEngine.getRepositoryService() .createDeployment() .addClasspathResource("processes/" + processName + ".bpmn") .addClasspathResource("processes/" + processName + ".png") .name(processName) .key(processName) .deploy(); final Map map = new HashMap(); map.put("deploymentId", deployment.getId()); map.put("deploymentKey", deployment.getKey()); map.put("deploymentName", deployment.getName()); map.put("deploymentEngineVersion", deployment.getEngineVersion()); logger.info("---- FlowService deploy end ----"); return map; } ###查看已部署的工作流### public Object deployedProcessList() { logger.info("---- FlowService deployedProcess begin ----"); final List deploymentList = processEngine.getRepositoryService() .createDeploymentQuery() .orderByDeploymenTime() .asc() .list(); final List list = new ArrayList(); for (Deployment deployment : deploymentList) { final Map map = new HashMap(); map.put("deploymentId", deployment.getId()); map.put("deploymentKey", deployment.getKey()); map.put("deploymentName", deployment.getName()); map.put("deploymentEngineVersion", deployment.getEngineVersion()); list.add(map); } logger.info("---- FlowService deployedProcess end ----"); return list; } /** * 查询流程定义 * @return */ public Object processDefinitionList () { logger.info("---- FlowService getProcessDefinition begin ----"); final List definitionList = processEngine.getRepositoryService() .createProcessDefinitionQuery() .list(); final List list = new ArrayList(); for (ProcessDefinition processDefinition : definitionList) { final Map map = new HashMap(); map.put("definitionId", processDefinition.getId()); map.put("definitionKey", processDefinition.getKey()); map.put("definitionName", processDefinition.getName()); map.put("definitionDeploymentId", processDefinition.getDeploymentId()); map.put("definitionResourceName", processDefinition.getResourceName()); map.put("definitionVersion", processDefinition.getVersion()); map.put("definitionEngineVersion", processDefinition.getEngineVersion()); list.add(map); } logger.info("---- FlowService getProcessDefinition end ----"); return list; } /** * 启动一个工作流 * * @param processName 工作流模板 (启动最新的版本) * @param variables 参数表 * @param user 启动人 * @return */ @Transactional(readOnly=false) public String startProcess(String processName, String key, Map variables) { IdentityService identityService = processEngine.getIdentityService(); identityService.setAuthenticatedUserId(UserUtils.getCurrentUser().getUserName()); logger.info("设置启动人"); RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processName, key, variables); return processInstance.getId(); } /** * 获取当前角色待办任务列表 * @return */ public Object getRoleTaskList() { logger.info("---- FlowService getRoleTaskList begin ----"); List taskList = processEngine.getTaskService() .createTaskQuery() .taskCandidateGroup(UserUtils.getCurrentUser().getRoleName()) .orderByTaskCreateTime() .asc() .list(); final List list = new ArrayList(); for (Task task : taskList) { final Map map = new HashMap(); map.put("taskId", task.getId()); map.put("createTime", task.getCreateTime()); map.put("taskName", task.getName()); map.put("taskOwner", task.getOwner()); map.put("processDefinitionId", task.getProcessDefinitionId()); map.put("processInstanceId", task.getProcessInstanceId()); map.put("taskDefinitionId", task.getTaskDefinitionId()); map.put("taskDefinitiionKey", task.getTaskDefinitionKey()); list.add(map); } logger.info("---- FlowService getRoleTaskList end ----"); return list; } /** * 获取当前用户待办任务列表 * @return */ public Object getPersonalTaskList() { logger.info("---- FlowService getPersonalTaskList begin ----"); final List taskList = processEngine.getTaskService() .createTaskQuery() .taskAssignee(UserUtils.getCurrentUser().getUserName()) .orderByTaskCreateTime() .asc() .list(); final List list = new ArrayList(); for (Task task : taskList) { final Map map = new HashMap(); map.put("taskId", task.getId()); map.put("createTime", task.getCreateTime()); map.put("taskName", task.getName()); map.put("taskOwner", task.getOwner()); map.put("processDefinitionId", task.getProcessDefinitionId()); map.put("processInstanceId", task.getProcessInstanceId()); map.put("taskDefinitionId", task.getTaskDefinitionId()); map.put("taskDefinitiionKey", task.getTaskDefinitionKey()); list.add(map); } logger.info("---- FlowService getPersonalTaskList end ----"); return list; } /** * 判断所处理的任务是否是当前用户或当前用户角色的任务 * @param taskId * @return */ public boolean isPersonalTask (final String taskId) { final String currentUserName = UserUtils.getCurrentUser().getUserName(); final Task personalTask = processEngine.getTaskService() .createTaskQuery() .taskAssignee(currentUserName) .taskId(taskId) .singleResult(); logger.info("current user name: " + currentUserName); logger.info("taskId: " + taskId); if (personalTask == null) { logger.info("personalTask is null"); } else { logger.info("personal taskId: " + personalTask.getId() + "personal assignee: " + personalTask.getAssignee()); } if (personalTask != null && taskId.equals(personalTask.getId())) { return true; } final String currentRoleName = UserUtils.getCurrentUser().getRoleName(); final Task roleTask = processEngine.getTaskService() .createTaskQuery() .taskCandidateGroup(currentRoleName) .taskId(taskId) .singleResult(); logger.info("taskId: " + taskId); if (roleTask == null) { logger.info("roleTask is null"); } else { logger.info("role taskId: " + roleTask.getId() + "role assignee: " + roleTask.getAssignee()); } if (roleTask != null && taskId.equals(taskId)) { return true; } return false; } /** * 获取所有未处理的任务 * @return */ public Object getUnresolvedTaskList() { List taskList = processEngine.getTaskService() .createTaskQuery() .orderByTaskCreateTime() .asc() .list(); final List list = new ArrayList(); for (Task task : taskList) { final Map map = new HashMap(); map.put("taskId", task.getId()); map.put("createTime", task.getCreateTime()); map.put("taskName", task.getName()); map.put("taskOwner", task.getOwner()); map.put("processDefinitionId", task.getProcessDefinitionId()); map.put("processInstanceId", task.getProcessInstanceId()); map.put("taskDefinitionId", task.getTaskDefinitionId()); map.put("taskDefinitiionKey", task.getTaskDefinitionKey()); list.add(map); } return list; } /** * 签收任务 * @param taskId * @param username */ @Transactional(readOnly = false) public void claim(String taskId, String username) { logger.info("签收任务:"+ taskId + " 签收人:" + username + " begin"); processEngine.getTaskService().claim(taskId,username); logger.info("签收任务:"+ taskId + " 签收人:" + username + " end"); } /** * 执行某个流程节点 * @param taskId * @param variables */ @Transactional(readOnly=false) public void completeTask(String taskId, Map variables) { if (!isPersonalTask(taskId)) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("请任务处理人或处理角色操作")); } processEngine.getTaskService().complete(taskId, variables); logger.info("完成任务:" + taskId); } /** * 执行某个流程节点, 待审批意见和附件 * @param taskId * @param variables * @param comment * @param fileMap */ @Transactional(readOnly=false) public void completeTask(final String taskId, final Map variables, final String action, String opinion, final Map fileMap) { logger.info("task id: " + taskId + " ; action = " + action); if (!isPersonalTask(taskId)) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("请任务处理人或处理角色操作")); } //添加批注时候的审核人 Authentication.setAuthenticatedUserId(UserUtils.getCurrentUser().getUserName()); final TaskService taskService = processEngine.getTaskService(); final Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); if (StringUtils.isEmpty(opinion)) { opinion = action; } else { opinion = action + ": " + opinion; } taskService.addComment(taskId, task.getProcessInstanceId(), opinion); if (fileMap != null) { final Iterator it = fileMap.keySet().iterator(); while(it.hasNext()) { final String filePath = (String) it.next(); final String fileName = (String) fileMap.get(filePath); String suffix = ""; if (fileName.contains(".") && !fileName.endsWith(".")) { suffix = fileName.substring(fileName.lastIndexOf(".") + 1); } else { if (filePath.contains(".") && !filePath.endsWith(".")) { suffix = filePath.substring(filePath.lastIndexOf(".") + 1); } } taskService.createAttachment(suffix, taskId, task.getProcessInstanceId(), fileName, null, filePath); } } try { taskService.complete(taskId, variables); } catch (Exception e) { logger.error("处理任务失败", e); throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("任务处理失败")); } logger.info("完成任务:" + taskId); } /** * 获取审批历史记录 * @param processInstanceId 流程实例ID * @return */ public List getApprovalHistory (final String processInstanceId) { final List approvalHistoryList = new ArrayList(); //通过流程实例查询所有的(用户任务)历史活动 List historicActivityInstanceList = processEngine.getHistoryService() .createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .activityType("userTask") .orderByHistoricActivityInstanceStartTime() .asc() .list(); for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) { final String historyTaskId = historicActivityInstance.getTaskId(); //每个节点所产生的文档 final List attachments = processEngine.getTaskService().getTaskAttachments(historyTaskId); final List historyFileList = new ArrayList(); for (Attachment attachment : attachments) { final HistoryFile historyFile = new HistoryFile(); historyFile.setPath(attachment.getUrl()); historyFile.setName(attachment.getName()); historyFileList.add(historyFile); } //每个节点的评论 final List comments = processEngine.getTaskService().getTaskComments(historyTaskId); if (comments != null && comments.size() > 0) { for (Comment comment : comments) { final ApprovalHistory approvalHistory = new ApprovalHistory(); final User user = userDao.queryByUserName(comment.getUserId()); approvalHistory.setRoleName(user.getRoleName()); approvalHistory.setUserName(user.getName() + " (" + user.getUserName() + ")"); approvalHistory.setOperateTime(comment.getTime()); approvalHistory.setOpinion(comment.getFullMessage()); approvalHistory.setTaskId(historyTaskId); approvalHistory.setProcessInstanceId(processInstanceId); approvalHistory.setHistoryFileList(historyFileList); approvalHistoryList.add(approvalHistory); } } } return approvalHistoryList; } public List getProcessComments(String processInstanceId) { final List commentList = new ArrayList(); //通过流程实例查询所有的(用户任务)历史活动 List historicActivityInstanceList = processEngine.getHistoryService() .createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .activityType("userTask") .orderByHistoricActivityInstanceStartTime() .asc() .list(); for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) { final String historyTaskId = historicActivityInstance.getTaskId(); List comments = processEngine.getTaskService().getTaskComments(historyTaskId); if (comments != null && comments.size() > 0) { commentList.addAll(comments); } } return commentList; } /** * 生成流程进展图 * @param processKey * @param request * @return */ public void genProcessDiagram(final String processInstanceId, final HttpServletResponse response) { logger.info("---- FlowService genProcessDiagram begin ----"); final HistoryService historyService = processEngine.getHistoryService(); final RuntimeService runtimeService = processEngine.getRuntimeService(); //获得当前活动的节点 String processDefinitionId = ""; if (isFinished(processInstanceId)) { //如果流程已经结束,则得到结束节点 HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); if (hpi == null) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程定义不存在")); } processDefinitionId = hpi.getProcessDefinitionId(); } else { //如果流程没有结束,则取当前活动节点 //根据流程实例ID获得当前处于活动状态的activityId合集 final ProcessInstance instance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); if (instance == null) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程实例不存在")); } processDefinitionId = instance.getProcessDefinitionId(); } final List highLightedActivitis = new ArrayList(); //获得活动的节点 List highLightActivityList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() .asc() .list(); highLightActivityList = highLightActivityList.subList(highLightActivityList.size() - 1, highLightActivityList.size()); for (HistoricActivityInstance historicActivityInstance : highLightActivityList) { final String activityId = historicActivityInstance.getActivityId(); //判断节点是否在当前节点之前 highLightedActivitis.add(activityId); } //需要高亮显示的线 final List flows = new ArrayList(); final BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(processDefinitionId); final ProcessEngineConfiguration config = processEngine.getProcessEngineConfiguration(); final ProcessDiagramGenerator diagramGenerator = config.getProcessDiagramGenerator(); final InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivitis, flows, config.getActivityFontName(), config.getLabelFontName(), config.getAnnotationFontName(), config.getClassLoader(), 1.0, true); OutputStream outputStream = null; byte[] buf = new byte[1024]; int legth = 0; try { outputStream = response.getOutputStream(); while ((legth = inputStream.read(buf)) != -1) { outputStream.write(buf, 0, legth); } outputStream.flush(); } catch (IOException e) { logger.error("生成流程图片失败", e); throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCEPTION.setExceptionMsg("生成流程图片失败")); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { logger.error("输出流关闭失败", e); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { logger.error("输入流关闭失败", e); } } } logger.info("---- FlowService genProcessDiagram end ----"); } /** * 判断节点是否结束 * @param processInstanceId * @return */ public boolean isFinished(final String processInstanceId) { return processEngine.getHistoryService().createHistoricProcessInstanceQuery().finished().processInstanceId(processInstanceId).count() > 0; } /** * 查看流程定义图 * @param deploymentId * @param response */ public void viewDefinitionDiagram(final String deploymentId, final HttpServletResponse response) { final RepositoryService repositoryService = processEngine.getRepositoryService(); final ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); if (processDefinition == null) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程定义不存在")); } InputStream inputStream = processEngine.getRepositoryService().getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName()); OutputStream outputStream = null; byte[] buf = new byte[1024]; int legth = 0; try { outputStream = response.getOutputStream(); while ((legth = inputStream.read(buf)) != -1) { outputStream.write(buf, 0, legth); } outputStream.flush(); } catch (IOException e) { logger.error("获取流程定义图片失败", e); throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCEPTION.setExceptionMsg("获取流程定义图片失败")); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { logger.error("输出流关闭失败", e); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { logger.error("输入流关闭失败", e); } } } } /** * 根据 processInstanceId 获取当前的任务 * @param processInstanceId * @return */ public Task findTaskByProcessInstanceId(String processInstanceId) { final Task task = processEngine.getTaskService() .createTaskQuery() .processInstanceId(processInstanceId) .singleResult(); return task; } /** * 撤回,返回 taskID * @param processInstanceId * @return */ public Object withdraw(String processInstanceId) { // final ProcessInstance processInstance = processEngine.getRuntimeService() // .createProcessInstanceQuery() // .processInstanceId(processInstanceId) // .singleResult(); final TaskService taskService = processEngine.getTaskService(); final HistoryService historyService = processEngine.getHistoryService(); final RepositoryService repositoryService = processEngine.getRepositoryService(); final RuntimeService runtimeService = processEngine.getRuntimeService(); final String currentUserName = UserUtils.getCurrentUser().getUserName(); final Task task = taskService.createTaskQuery() .processInstanceId(processInstanceId) .singleResult(); if (task == null) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("流程未启动或已执行完成,无法撤回")); } List htiList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .orderByTaskCreateTime() .asc() .list(); HistoricTaskInstance myTask = null; for (HistoricTaskInstance historicTaskInstance : htiList) { if(currentUserName.equals(historicTaskInstance.getAssignee())) { myTask = historicTaskInstance; break; } } if(myTask.getId() == null) { throw new BusinessException(ExceptionEnum.EXECUTE_BASE_CHECK_EXCPTION.setExceptionMsg("该任务非当前用户提交,无法撤回")); } final String processDefinitionId = myTask.getProcessDefinitionId(); final ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) processEngine.getRepositoryService() .createProcessDefinitionQuery() .processDefinitionId(processDefinitionId) .singleResult(); final BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); //变量 Map variables = runtimeService.getVariableInstances(task.getExecutionId()); String myActivityId = null; final List haiList = historyService.createHistoricActivityInstanceQuery() .executionId(myTask.getExecutionId()).finished().list(); for(HistoricActivityInstance hai : haiList) { if(myTask.getId().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(); logger.warn("------->> activityId:" + activityId); FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId); //记录原活动方向 List oriSequenceFlows = new ArrayList(); oriSequenceFlows.addAll(flowNode.getOutgoingFlows()); //清理活动方向 flowNode.getOutgoingFlows().clear(); //建立新方向 List newSequenceFlowList = new ArrayList(); SequenceFlow newSequenceFlow = new SequenceFlow(); newSequenceFlow.setId("newSequenceFlowId"); newSequenceFlow.setSourceFlowElement(flowNode); newSequenceFlow.setTargetFlowElement(myFlowNode); newSequenceFlowList.add(newSequenceFlow); flowNode.setOutgoingFlows(newSequenceFlowList); Authentication.setAuthenticatedUserId(UserUtils.getCurrentUser().getUserName()); taskService.addComment(task.getId(), task.getProcessInstanceId(), "撤回"); Map currentVariables = new HashMap(); currentVariables.put("applier", currentUserName); //完成任务 taskService.complete(task.getId(),currentVariables); //恢复原方向 flowNode.setOutgoingFlows(oriSequenceFlows); return task.getId(); } ###更新流程节点状态和发送邮件### public void updateStatus (final DelegateExecution execution, final String status) { String businessKey = execution.getProcessInstanceBusinessKey(); //根据业务id自行处理业务表 System.out.println("业务表["+businessKey+"]状态更改成功,状态更改为:" + status + ", 流程实例ID:" + execution.getProcessInstanceId()); if (businessKey.contains(":")) { final Integer designId = Integer.valueOf(businessKey.split(":")[1]); final Design design = (Design) designDao.queryById(designId); design.setStatus(status); designDao.update(design); if (design.getCreateUserId().equals(UserUtils.getCurrentUser().getId())) { return; } //根据流程关键字和状态查找邮件模板 MailTemplate mailTemplate = mailTemplateDao.findByProcessKeyAndStatus(Constant.PROCESS_KEY_DESIGN , status); if (mailTemplate == null) { mailTemplate = new MailTemplate(); mailTemplate.setContent("邮件通知"); mailTemplate.setSubject("邮件通知"); } String content = mailTemplate.getContent(); if (!StringUtils.isEmpty(content)) { content = content.replaceAll("\\$\\{name\\}", design.getName()); } final User user = (User) userDao.queryById(design.getCreateUserId()); mailService.sendMail(user.getEmail(), mailTemplate.getSubject(), content, execution.getProcessInstanceId()); } }

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有