首页 > 代码库 > Activiti实战04_简单流程

Activiti实战04_简单流程

在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中,流程变量也是一样的,只要是同名的流程变量,便会采用顶替的原则,就好比你挑了好几条一样,每次只是替换,并不改变鱼这个种类,然后只有最后一次的有效,无论中间发生了多少次改变(前提是在你用这个流程变量之前的最后一次改变)。说完了流程变量,我们也开启了流程,接下来因为用户任务的存在,所以流程会阻塞在用户任务那里,直到有人接收并处理了任务,才会转到下一步(依照目前的流程图是这样的),存在一个用户拾取了任务,并完成了任务,就会继续往下走,由于是脚本任务,所以在执行完后流程就直接结束了,就只能从历史中查了。至此,一个简单的请假流程就算是完成了。

Activiti实战04_简单流程