在Activiti实战03_Hello World中我们介绍了一个中间没有任何任务的流程,实现了流程的部署与查阅,而在本章中,将会为流程添加任务节点,是流程能够像个流程,变得更加丰满起来。
在上一节的基础上,我门将会为流程添加实际业务使其能够正常工作起来,先模拟一个很简单的请假流程。
首先,在上一节的流程图中为流程添加一个用户任务(userTask)来处理申请,根据申请内容来决定运行申请还是驳回申请。流程图如下:
代码清单,由于篇幅的原因,这里就不在列出任务的坐标位置等信息
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> <process id="myProcess" name="My process" isExecutable="true"> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="deptLeaderAudit" name="领导审批" activiti:candidateGroups="deptLeader"></userTask> <sequenceFlow id="flow1" name="to User Task" sourceRef="startevent1" targetRef="deptLeaderAudit"></sequenceFlow> <scriptTask id="outputAuditResult" name="输出审批结果" scriptFormat="groovy" activiti:autoStoreVariables="false"> <script>out:println "applyUser:" + applyUser +" ,days:"+ days +",approval:" + approved;</script> </scriptTask> <sequenceFlow id="flow2" name="to Script Task" sourceRef="deptLeaderAudit" targetRef="outputAuditResult"></sequenceFlow> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow3" name="to End" sourceRef="outputAuditResult" targetRef="endevent1"></sequenceFlow> </process> </definitions>
简单说一下这个代码清单里值得注意的地方,首先增加了两个任务节点,即<userTask></userTask>标签和<scriptTask></scriptTask>标签中所包含的内容,因为有四个节点,自然会产生三条连线,即<sequenceFlow></sequenceFlow>之间的内容,id分别为flow1,flow2,fow3,,对于scriptTask而言,因为采用了groovy的语法,所以需要导入相关jar包或添加相关依赖。
<dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.7</version> </dependency>
测试:
代码清单
public class SimpleLeaveProcessTest { @Test public void testStartProcess(){ // 创建流程引擎,使用内存数据库 ProcessEngine processEngine = ProcessEngineConfiguration .createStandaloneInMemProcessEngineConfiguration() .buildProcessEngine(); // 部署流程定义文件 RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() .addClasspathResource("diagrams/SimpleLeave.bpmn") .deploy(); // 验证已部署的流程定义 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .singleResult(); assertEquals("myProcess",processDefinition.getKey()); // 启动流程并返回流程实例 RuntimeService runtimeService = processEngine.getRuntimeService(); //设置流程变量 Map<String, Object> variables = new HashMap<String,Object>(); variables.put("applyUser", "employee1"); variables.put("days", 3); //带着流程变量开启流程 ProcessInstance instance = runtimeService.startProcessInstanceByKey("myProcess",variables); assertNotNull(instance); System.out.println("pid = " +instance.getId() +", pdid = " + instance.getProcessDefinitionId() ); //获取任务服务 TaskService taskService = processEngine.getTaskService(); //获取领导审批任务 Task taskOfDeptLeader = taskService.createTaskQuery() .taskCandidateGroup("deptLeader") .singleResult(); assertNotNull(taskOfDeptLeader); //验证任务是否为领导审批任务 assertEquals("领导审批", taskOfDeptLeader.getName()); //作为有权处理的组角色,拾取任务,此时相同角色的其他人便看不到该任务了 taskService.claim(taskOfDeptLeader.getId(), "leaderUser"); variables = new HashMap<String,Object>(); // 再次设置流程变量 variables.put("approved", true); // 带着流程变量完成任务 taskService.complete(taskOfDeptLeader.getId(),variables); // 由于任务已经完成,所以不再是改组角色拥有的任务,此时就查不到任务了 taskOfDeptLeader = taskService.createTaskQuery() .taskCandidateGroup("deptLeader") .singleResult(); assertNull(taskOfDeptLeader); // 任务已经走完就会归到历史里面,所以这里从历史中查数据 HistoryService historyService = processEngine.getHistoryService(); long count = historyService.createHistoricProcessInstanceQuery() .finished() .count(); //判断是否有一个任务已完成,并处于历史状态 assertEquals(1, count); } }
代码解释:
在上一章中,我们是直接开启了流程,然后就直接走向了结束。在这章中,因为存在任务节点的关系,一旦开启流程,便会走到任务节点处,此处就是【领导审批】任务节点,而这次开启流程的方式也和上一章有所不同,这章是带着流程变量开启的流程,上一章则是直接开启流程,至于流程变量是什么,你可以这样理解,就好比你去菜市场买鱼,走了好几家,挑了好几条,终于挑到了一条让自己满意的鱼了,然后就高高兴兴的带着鱼回家了,在Activiti中,流程变量也是一样的,只要是同名的流程变量,便会采用顶替的原则,就好比你挑了好几条一样,每次只是替换,并不改变鱼这个种类,然后只有最后一次的有效,无论中间发生了多少次改变(前提是在你用这个流程变量之前的最后一次改变)。说完了流程变量,我们也开启了流程,接下来因为用户任务的存在,所以流程会阻塞在用户任务那里,直到有人接收并处理了任务,才会转到下一步(依照目前的流程图是这样的),存在一个用户拾取了任务,并完成了任务,就会继续往下走,由于是脚本任务,所以在执行完后流程就直接结束了,就只能从历史中查了。至此,一个简单的请假流程就算是完成了。
原文:http://www.cnblogs.com/homeword/p/7113404.html