flowable
简单介绍
本文通过申请发工资的业务场景来介绍使用工作流的全流程,包括画流程图,设置属性,以及代码编写
使用工作流大致分为四步
第一步:根据自己的业务画好流程图
第二步:设置流程图的属性和变量,保存模型
第三步:部署画好的流程图(发布)
第四步:根据业务和流程图写一些服务和监听器
这里主要介绍以下几个任务的使用
1.用户任务的分配和提交
2.服务任务的使用
3.中间信号捕捉事件的触发
4.排他网关的使用
5.通过设置流程变量,实现流程的不同流转
一、画流程图
申请发工资流程预览
二、设置流程信息
1.设置流程标识
设置流程的唯一标识为payrollApplication也就是模型KEY,后续部署和启动都会用到
2.设置流程变量
设置通过的流转条件为${approval==‘pass’}其中approval为变量名称,pass为变量值,工作流会自动解析表达式进行判断
设置不通过的流转条件为${approval==‘notPass’}
设置打款成功的流转条件为${payment == ‘success’}
设置打款失败的流转条件为${payment == ‘fail’}
3.设置信号定义和信号引用
主要用于接收银行打款处理通知,未通知会一直停留在中间信号接收事件节点上
设置信号引用为方才设置的信号定义
4.设置服务任务的实现类
设置事先写好的服务任务的实现类(下面有实现代码)
5.用户任务–通过变量设置审批人
设置审批人为${Assignee},通过设置变量Assignee,动态设置审批人
三、部署流程
四、使用流程
1.启动流程
启动流程实例并跟业务ID关联,并设置流程变量
1.processDefinitionKey 要启动的流程模型KEY (本次演示场景为payrollApplication)
2.businessKey 业务标识,跟流程进行关联,不需要可不填
3.variables 流程变量,启动流程时设置的变量,类型为Map
public string startProcessByBusinessKey(String processDefinitionKey, String businessKey , Map<String,Object> variables) { // 启动流程实例 ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables); logger.debug("流程实例ID:{},流程定义ID:{},业务标识:{}", instance.getId(), instance.getProcessDefinitionId(), businessKey); return instance.getId(); }
2.用户任务(财务审批)
businessKey为启动时设置的业务标识,不需要可不填
userId为启动流程时设置的流程变量Assignee的值
approval为审批结果值为pass或者notPass
public String completeTaskByUserIdAndBusinessKey(String businessKey, String userId, String approval) { // 获取流程实例ID String processInstanceId = null; // 需要处理的任务ID String taskId = null; // 查询该用户的所有任务 List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list(); if (null == taskList || taskList.isEmpty()) { return "该用户没有分配任务!"; } if (StringUtils.isBlank(businessKey)) { // 有可能存在多个任务,实际需要根据业务特殊处理 taskId = taskList.get(0).getId(); // 获取流程实例ID processInstanceId = taskList.get(0).getProcessInstanceId(); }else { // 根据业务ID查找任务ID for (Task task : taskList) { // 获取流程实例ID processInstanceId = task.getProcessInstanceId(); if (StringUtils.isNotBlank(processInstanceId)) { // 获取流程实例 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); // 流程实例 if (null == processInstance) { return "未查询到正在运行的流程实例!"; } // 流程实例关联的业务ID String processInstanceBusinessKey = processInstance.getBusinessKey(); // 流程实例关联的业务ID和该用户的业务ID if (StringUtils.isNotBlank(processInstanceBusinessKey) && StringUtils.equals(processInstanceBusinessKey, businessKey)) { taskId = task.getId(); break; } } } } if (StringUtils.isBlank(taskId)) { return "未查询到关联该业务的任务!"; } // 设置变量 设置流条件,告诉工作流下一步的流转节点 审批通过或未通过 JSONObject variables = new JSONObject(); variables.put("approval", approval); runtimeService.setVariables(processInstanceId, variables); // 提交任务 taskService.complete(taskId, null); return "提交任务成功"; }
3.服务任务(银行处理)
BankPaymentTask 实现类必须实现JavaDelegate接口,工作流才会识别到
public class BankPaymentTask implements JavaDelegate, Serializable { @Autowired public RuntimeService runtimeService; public static BankPaymentTask bankPaymentTask; @PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作 public void init() { bankPaymentTask= this; bankPaymentTask.runtimeService = this.runtimeService; } @Override public void execute(DelegateExecution execution) { // 获取流程实例变量 Map<String, Object> variables = runtimeService.getVariables(execution.getProcessInstanceId()); if (variables == null || variables.isEmpty()) { log.error("variables不能为空!"); return; } if (variables.get("businessKey") == null) { log.error("businessKey不能为空!"); return; } // 配合流程变量,使用http调用其他服务完成银行转账的操作 // JSONObject result = RestTemplateUtil.postForObject(paymentUrl, params, JSONObject.class); // 设置流程变量JSONObject variables = new JSONObject(); variables.put("xxx", "xxx"); runtimeService.setVariables(execution.getProcessInstanceId(), variables); }
4.中间信号捕获事件(等待银行处理结果回调)
工作流执行到当前节点会暂停,待银行打款操作结果回调之后,触发中间信号捕获事件信号,根据打款结果设置流程变量值,完成流程流转
public String callback(String businessKey, String signaler, String payment) { // 根据业务标识查询正在运行的流程实例 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult(); if (processInstance == null) { return "没有正在进行的任务!"; } // 流程实例ID String processInstanceId = processInstance.getId(); // 查找是否有等待触发的信号 // 流程执行流 流程执行流和流程实例的关系:流程执行流表示流程实例中具体地执行路径,流程实例是一次工作流业务的数据实体 Execution executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceId) .signalEventSubscriptionName(signaler).singleResult(); if (executions == null) { return "未查询到该信号事件!"; } logger.debug("executionsId:{},processInstanceId:{}", executions.getId(), processInstanceId); // 设置变量 设置流条件,告诉工作流下一步的流转节点JSONObject variables = new JSONObject();// payment为success或者fail variables.put("payment", payment); runtimeService.setVariables(processInstanceId, variables); // 发送触发信号 runtimeService.signalEventReceived(signaler, executions.getId()); return "触发信号接收成功"; }
来源地址:https://blog.csdn.net/weixin_43948460/article/details/128970508