摘要:本文通过一个工作流 Activiti 框架的具体使用示例,具体详尽的介绍了工作流 Activiti 框架的使用方式。
本文分享自华为云社区《一个使用示例,五个操作步骤!从此轻松掌握项目中工作流的开发》,作者:攻城狮 Chova。
本文通过一个工作流 Activiti 框架的具体使用示例,具体详尽的介绍了工作流 Activiti 框架的使用方式。包括创建流程,发布流程,启动一个流程实例,完成一个流程实例以及挂起和激活一个流程实例。通过对工作流 Activiti 的具体使用步骤的掌握,基本上就能够学会了工作流 Activiti 的工作流程和具体使用。
创建流程
任何与“静态”资源有关的数据(比如流程定义)都可以通过 RepositoryService 访问,从概念上讲,所有静态数据都是 Activiti 的资源内容
在 src/test/resources/org/activiti/test 目录下创建一个新的 xml 文件 VacationRequest.bpmn20.xml:
<?xml version="1.0" encoding="UTF-8" ?><definitions id="definitions" targetNamespace="http://activiti.org/bpmn20" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn">
<process id="vacationRequest" name="Vacation request">
<startEvent id="request" activiti:initiator="employeeName"> <extensionElements> <activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/> <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" /> <activiti:formProperty id="vacationMotivation" name="Motivation" type="string" /> </extensionElements> </startEvent> <sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" />
<userTask id="handleRequest" name="Handle vacation request" > <documentation> ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}). </documentation> <extensionElements> <activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true"> <activiti:value id="true" name="Approve" /> <activiti:value id="false" name="Reject" /> </activiti:formProperty> <activiti:formProperty id="managerMotivation" name="Motivation" type="string" /> </extensionElements> <potentialOwner> <resourceAssignmentExpression> <formalExpression>management</formalExpression> </resourceAssignmentExpression> </potentialOwner> </userTask> <sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" />
<exclusiveGateway id="requestApprovedDecision" name="Request approved?" /> <sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail"> <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression> </sequenceFlow>
<task id="sendApprovalMail" name="Send confirmation e-mail" /> <sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" /> <endEvent id="theEnd1" />
<sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask"> <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression> </sequenceFlow>
<userTask id="adjustVacationRequestTask" name="Adjust vacation request"> <documentation> Your manager has disapproved your vacation request for ${numberOfDays} days. Reason: ${managerMotivation} </documentation> <extensionElements> <activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/> <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" /> <activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" /> <activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true"> <activiti:value id="true" name="Yes" /> <activiti:value id="false" name="No" /> </activiti:formProperty> </extensionElements> <humanPerformer> <resourceAssignmentExpression> <formalExpression>${employeeName}</formalExpression> </resourceAssignmentExpression> </humanPerformer> </userTask> <sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />
<exclusiveGateway id="resendRequestDecision" name="Resend request?" /> <sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest"> <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression> </sequenceFlow>
<sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2"> <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression> </sequenceFlow> <endEvent id="theEnd2" />
</process>
</definitions>
复制代码
为了让 Activiti 引擎知道这个流程,我们必须先进行[发布],发布意味着引擎会把 BPMN 2.0 xml 解析成可以执行的东西,发布包中的所有流程定义都会添加到数据库中.这样,当引擎重启时,它依然可以获得[已发布]的流程:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();repositoryService.createDeployment() .addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml") .deploy();
Log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());
复制代码
启动一个流程实例
把流程定义发布到 Activiti 引擎后,可以基于它发起新流程实例.
对每个流程定义,都可以有很多流程实例.流程定义是"蓝图",流程实例是它的一个运行的执行
所有与流程运行状态相关的东西都可以通过 RuntimeService 获得.有很多方法可以启动一个新流程实例.
可以在流程实例启动时添加一些流程变量, 因为第一个用户任务的表达式需要这些变量.流程变量经常会被用到,因为它们赋予来自同一个流程定义的不同流程实例的特别含义
流程变量是区分流程实例的关键
下面使用定义在流程定义 xml 中的 key 来启动流程实例:
Map<String, Object> variables = new HashMap<String, Object>();variables.put("employeeName", "Kermit");variables.put("numberOfDays", new Integer(4));variables.put("vacationMotivation", "I'm really tired!");
RuntimeService runtimeService = processEngine.getRuntimeService();ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);
// Verify that we started a new process instanceLog.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());
复制代码
完成任务
流程启动后,第一步就是用户任务.这是必须由系统用户处理的一个环节.
用户会有一个"任务列表",展示了所有必须由整个用户处理的任务.下面是对应的查询:
// Fetch all tasks for the management groupTaskService taskService = processEngine.getTaskService();List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();for (Task task : tasks) { Log.info("Task available: " + task.getName());}
复制代码
Task task = tasks.get(0);
Map<String, Object> taskVariables = new HashMap<String, Object>();taskVariables.put("vacationApproved", "false");taskVariables.put("managerMotivation", "We have a tight deadline!");taskService.complete(task.getId(), taskVariables);
复制代码
挂起或激活一个流程
repositoryService.suspendProcessDefinitionByKey("vacationRequest");try { runtimeService.startProcessInstanceByKey("vacationRequest");} catch (ActivitiException e) { e.printStackTrace();}
复制代码
挂起时,流程不能继续执行:比如,完成任务会抛出异常,异步操作(比如定时器)也不会执行.挂起流程实例可以调用 runtimeService.suspendProcessInstance 方法
激活流程实例可以调用 runtimeService.activateProcessInstanceXXX 方法
点击关注,第一时间了解华为云新鲜技术~
评论