Activiti入門學習demo

jopen 9年前發布 | 137K 次閱讀 Activiti 工作流引擎

本文提供activiti入門學習的demo,包括流程文件和調用代碼。

一、新建工程,導入相應的jar包,建議用maven做jar包的依賴管理。maven依賴部分代碼如下:

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--activiti的核心jar包,其相關依賴jar包會一并導入-->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-engine</artifactId>
      <version>5.18.0</version>
    </dependency>
    <!--h2內存數據庫的jar包,本文的例子用的是h2數據庫,基于內存模式,方便測試-->
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.3.176</version>
    </dependency>
  </dependencies>

二、流程文件,測試中用到的兩個流程文件,放到合適的目錄下,一般是resources目錄下,至于如何生成流程文件,請參照相關資料:

  1. MyProcess.bpmn20.xml

    </li> </ol>

     <?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:xsd="http://www.w3.org/2001/XMLSchema" 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="usertask1" name="User Task"></userTask>
        <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
        <endEvent id="endevent1" name="End"></endEvent>
        <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
      </process>
    </definitions>

    這是一個最簡單的流程,流程圖如下:

    Activiti入門學習demo

    2. pool.bpmn

    <?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:xsd="http://www.w3.org/2001/XMLSchema" 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">
      <collaboration id="Collaboration">
        <participant id="pool1" name="請假流程" processRef="process_pool1"></participant>
      </collaboration>
      <process id="process_pool1" name="process_pool1" isExecutable="true">
        <laneSet id="laneSet_process_pool1">
          <lane id="lane1" name="員工">
            <flowNodeRef>startevent1</flowNodeRef>
            <flowNodeRef>usertask1</flowNodeRef>
            <flowNodeRef>usertask4</flowNodeRef>
            <flowNodeRef>endevent1</flowNodeRef>
            <flowNodeRef>exclusivegateway3</flowNodeRef>
          </lane>
          <lane id="lane2" name="領導">
            <flowNodeRef>usertask2</flowNodeRef>
            <flowNodeRef>exclusivegateway1</flowNodeRef>
          </lane>
          <lane id="lane3" name="人事">
            <flowNodeRef>usertask3</flowNodeRef>
            <flowNodeRef>exclusivegateway2</flowNodeRef>
          </lane>
        </laneSet>
        <startEvent id="startevent1" name="Start" activiti:initiator="applyUserId">
          <extensionElements>
            <activiti:formProperty id="startDate" name="請假開始日期" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
            <activiti:formProperty id="endDate" name="請假結束日期" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
            <activiti:formProperty id="reason" name="請假原因" type="string" required="true"></activiti:formProperty>
          </extensionElements>
        </startEvent>
        <userTask id="usertask1" name="調整申請" activiti:assignee="${applyUserId}">
          <extensionElements>
            <activiti:formProperty id="startDate" name="請假開始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
            <activiti:formProperty id="endDate" name="請假結束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
            <activiti:formProperty id="reason" name="請假原因" type="string" value="${reason}" required="true"></activiti:formProperty>
            <activiti:formProperty id="reApply" name="重新申請" type="enum" required="true">
              <activiti:value id="true" name="重新申請"></activiti:value>
              <activiti:value id="false" name="取消申請"></activiti:value>
            </activiti:formProperty>
          </extensionElements>
        </userTask>
        <sequenceFlow id="flow2" name="提交申請" sourceRef="startevent1" targetRef="usertask2"></sequenceFlow>
        <userTask id="usertask2" name="領導審批" activiti:candidateGroups="deptLeader">
          <extensionElements>
            <activiti:formProperty id="startDate" name="請假開始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
            <activiti:formProperty id="endDate" name="請假結束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
            <activiti:formProperty id="reason" name="請假原因" type="string" value="${reason}" writable="false"></activiti:formProperty>
            <activiti:formProperty id="deptLeaderApprove" name="審批意見" type="enum" required="true">
              <activiti:value id="true" name="同意"></activiti:value>
              <activiti:value id="false" name="拒絕"></activiti:value>
            </activiti:formProperty>
          </extensionElements>
        </userTask>
        <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
        <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="exclusivegateway1"></sequenceFlow>
        <sequenceFlow id="flow4" name="同意" sourceRef="exclusivegateway1" targetRef="usertask3">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApprove=='true'}]]></conditionExpression>
        </sequenceFlow>
        <userTask id="usertask3" name="人事審批" activiti:candidateGroups="hr">
          <extensionElements>
            <activiti:formProperty id="startDate" name="請假開始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
            <activiti:formProperty id="endDate" name="請假結束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
            <activiti:formProperty id="reason" name="請假原因" type="string" value="${reason}" writable="false"></activiti:formProperty>
            <activiti:formProperty id="hrApprove" name="審批意見" type="enum" required="true">
              <activiti:value id="true" name="同意"></activiti:value>
              <activiti:value id="false" name="拒絕"></activiti:value>
            </activiti:formProperty>
          </extensionElements>
        </userTask>
        <sequenceFlow id="flow6" name="不同意" sourceRef="exclusivegateway1" targetRef="usertask1">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApprove=='false'}]]></conditionExpression>
        </sequenceFlow>
        <exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
        <sequenceFlow id="flow7" sourceRef="usertask3" targetRef="exclusivegateway2"></sequenceFlow>
        <sequenceFlow id="flow8" name="同意" sourceRef="exclusivegateway2" targetRef="usertask4">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrApprove=='true'}]]></conditionExpression>
        </sequenceFlow>
        <userTask id="usertask4" name="銷假" activiti:assignee="${applyUserId}">
          <extensionElements>
            <activiti:formProperty id="startDate" name="請假開始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
            <activiti:formProperty id="endDate" name="請假結束日期" type="date" value="${endDate}" datePattern="yyyy-MM-dd" writable="false"></activiti:formProperty>
            <activiti:formProperty id="reason" name="請假原因" type="string" value="${reason}" writable="false"></activiti:formProperty>
            <activiti:formProperty id="reportBackDate" name="銷假日期" type="date" default="${endDate}" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
          </extensionElements>
        </userTask>
        <sequenceFlow id="flow9" name="不同意" sourceRef="exclusivegateway2" targetRef="usertask1">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrApprove=='false'}]]></conditionExpression>
        </sequenceFlow>
        <endEvent id="endevent1" name="End"></endEvent>
        <sequenceFlow id="flow10" sourceRef="usertask4" targetRef="endevent1">
          <extensionElements>
            <activiti:executionListener event="take" expression="${execution.setVariable('result','OK')}"></activiti:executionListener>
          </extensionElements>
        </sequenceFlow>
        <sequenceFlow id="flow11" name="繼續提交申請" sourceRef="exclusivegateway3" targetRef="usertask2">
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${reApply=='true'}]]></conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow12" name="取消申請" sourceRef="exclusivegateway3" targetRef="endevent1">
          <extensionElements>
            <activiti:executionListener event="take" expression="${execution.setVariable('result','canceled')}"></activiti:executionListener>
          </extensionElements>
          <conditionExpression xsi:type="tFormalExpression"><![CDATA[${reApply=='false'}]]></conditionExpression>
        </sequenceFlow>
        <exclusiveGateway id="exclusivegateway3" name="Exclusive Gateway"></exclusiveGateway>
        <sequenceFlow id="flow13" sourceRef="usertask1" targetRef="exclusivegateway3"></sequenceFlow>
      </process>
    </definitions>

    這是一個請假流程,流程圖如下:

    Activiti入門學習demo

    三、用于測試的java代碼,采用junit方式運行:

     package com.wangtl.activiti;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import org.activiti.engine.FormService;
    import org.activiti.engine.HistoryService;
    import org.activiti.engine.IdentityService;
    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngineConfiguration;
    import org.activiti.engine.RepositoryService;
    import org.activiti.engine.RuntimeService;
    import org.activiti.engine.TaskService;
    import org.activiti.engine.history.HistoricDetail;
    import org.activiti.engine.history.HistoricFormProperty;
    import org.activiti.engine.history.HistoricProcessInstance;
    import org.activiti.engine.history.HistoricVariableInstance;
    import org.activiti.engine.history.HistoricVariableUpdate;
    import org.activiti.engine.repository.Deployment;
    import org.activiti.engine.repository.ProcessDefinition;
    import org.activiti.engine.runtime.ProcessInstance;
    import org.activiti.engine.task.Task;
    import org.junit.Test;
    public class VerySimpleLeaveProcessTest {
     
     @Test
     public  void testProcessDefinition() throws Exception{
      // 創建 Activiti流程引擎
      ProcessEngine processEngine=
          ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
          .buildProcessEngine();
        // 取得 Activiti 服務 
      RepositoryService repositoryService=processEngine.getRepositoryService();
      // 部署流程定義
      Deployment deploy=repositoryService.createDeployment().addClasspathResource("MyProcess.bpmn20.xml").deploy();
      
      ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId())
        .singleResult();
      System.out.println(processDefinition.getKey());
      // 啟動流程實例
      RuntimeService runtimeService=processEngine.getRuntimeService();
      ProcessInstance processInstance=runtimeService.startProcessInstanceByKey(processDefinition.getKey());
      System.out.println("pid="+processInstance.getId()+",pdid="+
        processInstance.getProcessDefinitionId());
     }
     
     @Test
     public void testStartProcess() throws Exception{
      // 1.創建 Activiti流程引擎(此處使用的是h2數據庫,并啟用的是內存模式,即數據保存在內存中,程序運行完數據就丟失)
      ProcessEngine processEngine=
          ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
          .buildProcessEngine();
      
      // 2.部署流程定義
      //取得 Activiti 服務 
      RepositoryService repositoryService=processEngine.getRepositoryService();
      //獲得流程定義的相關數據
      String fileName="E:/workspace/activiti-demo/src/main/resources/MyProcess.bpmn20.xml";
      File f =new File(fileName);
      InputStream fileInputStream = new FileInputStream(f);
      //創建Deployment,同時部署流程定義
      repositoryService.createDeployment()
       .addInputStream(fileName, fileInputStream)
       .deploy();
      //查看定義的流程(非必須,只是驗證流程定義是否部署成功)
      ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery()
        .singleResult();
      System.out.println("流程定義文件的key為:"+processDefinition.getKey());
      // 3.啟動流程實例
      RuntimeService runtimeService=processEngine.getRuntimeService();
      ProcessInstance processInstance=runtimeService.startProcessInstanceByKey(processDefinition.getKey());
      System.out.println("流程實例的id="+processInstance.getId()+",流程實例的definitionId="+
        processInstance.getProcessDefinitionId());
      
      //4.取得當前任務
      //獲得任務服務
      TaskService taskService=processEngine.getTaskService();
      //取得當前任務(由于流程定義中沒有指明任務指派給誰,所以這里不用申明任務由誰獲得)
      Task task=taskService.createTaskQuery().singleResult();
      System.out.println("當前任務的名稱是:"+task.getName());
      //5.認領任務(由于流程定義中沒有指明任務指派給誰,任何人都可以認領該任務,如這里的“leaderUser”)
      taskService.claim(task.getId(), "leaderUser");
      //查看"leaderUser"現在是否能夠獲取到該任務(非必須)
      task=taskService.createTaskQuery().taskAssignee("leaderUser").singleResult();
      System.out.println("認領任務的人是:"+task.getAssignee());
      //6.完成任務
      taskService.complete(task.getId());
      
      //以下是驗證任務是否完成,通過重新查找任務(為空),查詢歷史記錄(有),說明之前的任務完成了(非必須)
      task=taskService.createTaskQuery().singleResult();
      System.out.println("當前的任務是:"+task);
      HistoryService historyService=processEngine.getHistoryService();
      long count=historyService.createHistoricProcessInstanceQuery().finished().count();
      System.out.println("已完成的任務數是:"+count);
     }
     
     
     
     @Test
     public void testStartProcess2() throws Exception{
      // 1.創建 Activiti流程引擎(此處使用的是h2數據庫,并啟用的是內存模式,即數據保存在內存中,程序運行完數據就丟失)
      ProcessEngine processEngine=
          ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
    //      .setHistory("full")
          .buildProcessEngine();
      
      // 2.部署流程定義
      //取得 Activiti 服務 
      RepositoryService repositoryService=processEngine.getRepositoryService();
      //獲得流程定義的相關數據
      String fileName="E:/workspace/activiti-demo/src/main/resources/pool.bpmn";
      File f =new File(fileName);
      InputStream fileInputStream = new FileInputStream(f);
      //創建Deployment,同時部署流程定義
      repositoryService.createDeployment()
       .addInputStream(fileName, fileInputStream)
       .deploy();
      //查看定義的流程(非必須,只是驗證流程定義是否部署成功)
      ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey("process_pool1")
        .singleResult();
      System.out.println("流程定義文件的key為:"+processDefinition.getKey());
      
      //設置當前用戶
      String currentUserId="hen";
      IdentityService identityService=processEngine.getIdentityService();
      identityService.setAuthenticatedUserId(currentUserId);
      
      //設置表單變量
      SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
      Map<String,String> variables =new HashMap<String,String>();
      Calendar ca=Calendar.getInstance();
      String startDate = sdf.format(ca.getTime());
      ca.add(Calendar.DAY_OF_MONTH, 2);
      String endDate=sdf.format(ca.getTime());
      variables.put("startDate", startDate);
      variables.put("endDate", endDate);
      variables.put("reason", "年假");
      
      // 3.當前用戶啟動流程實例(類似RuntimeService,只是這里帶上了表單數據)
      FormService formService=processEngine.getFormService();
      ProcessInstance processInstance=
        formService.submitStartFormData(processDefinition.getId(), variables);
      System.out.println("流程實例的id="+processInstance.getId()+",流程實例的definitionId="+
        processInstance.getProcessDefinitionId());
      
      //取得deptLeader的任務
      TaskService taskService=processEngine.getTaskService();
      Task leaderTask=taskService.createTaskQuery().taskCandidateGroup("deptLeader").singleResult();
      System.out.println("當前任務的名稱是:"+leaderTask.getName());
      //審批當前任務(類似于TaskService的complete)
      variables=new HashMap<String,String>();
      variables.put("deptLeaderApprove", "true");
      formService.submitTaskFormData(leaderTask.getId(), variables);
      
      //取得hr的任務
      Task hrTask=taskService.createTaskQuery().taskCandidateGroup("hr").singleResult();
      System.out.println("當前任務的名稱是:"+hrTask.getName());
      //審批當前任務(類似于TaskService的complete)
      variables=new HashMap<String,String>();
      variables.put("hrApprove", "true");
      formService.submitTaskFormData(hrTask.getId(), variables);
      
      //取得用戶的銷假任務
      Task reportBackTask=taskService.createTaskQuery().taskAssignee(currentUserId).singleResult();
      //提交任務
      variables=new HashMap<String,String>();
      variables.put("reportBackDate", endDate);
      formService.submitTaskFormData(reportBackTask.getId(),variables);
      
      //以下是驗證流程是否結束(非必須)
      HistoryService historyService=processEngine.getHistoryService();
      HistoricProcessInstance historicProcessInstance=historyService
        .createHistoricProcessInstanceQuery().finished().singleResult();
      System.out.println("已執行的流程id:"+historicProcessInstance.getId());
      Map<String,Object> historyVariables=packageVariables(historyService,processInstance);
      System.out.println(historyVariables.get("result"));
      
     }
     
     private Map<String,Object> packageVariables(HistoryService historyService,ProcessInstance processInstance){
      
      Map<String,Object> historyVariables=new HashMap<String,Object>();
      
      //在保存表單字段的同時會復制一份經過類型轉換的值,并以字段的ID為變量名保存到數據庫中,當然前提是要設置引擎的“history”屬性為“full”級別
      /List<HistoricDetail> list=
      historyService.createHistoricDetailQuery().processInstanceId(processInstance.getId()).list();
      System.out.println("歷史記錄數"+list.size());
      for(HistoricDetail historicDetail:list){
       if(historicDetail instanceof HistoricFormProperty){
        HistoricFormProperty field=(HistoricFormProperty) historicDetail;
        historyVariables.put(field.getPropertyId(), field.getPropertyValue());
        System.out.println("form field: taskId="+field.getTaskId()+", "
          +field.getPropertyId()+"="+field.getPropertyValue());
       }else if(historicDetail instanceof HistoricVariableUpdate){
        HistoricVariableUpdate variable=(HistoricVariableUpdate) historicDetail;
        historyVariables.put(variable.getVariableName(),variable.getValue());
        System.out.println("variable: "+variable.getVariableName()+"="+variable.getValue());
       }
      }/
      
      
      / 查詢所有保存的變量:5.11版本之后,從表act_hi_varinst/
      List<HistoricVariableInstance> list = 
        historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId()).list();
      for (HistoricVariableInstance variable : list) 
      { 
       historyVariables.put(variable.getVariableName(),variable.getValue());
       System.out.println("variable: " + variable.getVariableName() + " = " + variable.getValue());
      
      }
      
      
      / 只讀取表單變量:從表act_hi_detail/
      /List<HistoricDetail> formProperties = 
        historyService.createHistoricDetailQuery().processInstanceId(processInstance.getId())
        .formProperties().list();
      for (HistoricDetail historicDetail : formProperties) {  
       HistoricFormProperty field = (HistoricFormProperty) historicDetail;  
       historyVariables.put(field.getPropertyId(), field.getPropertyValue());
       System.out.println("field id: " + field.getPropertyId() + ", value: " + field.getPropertyValue());
      } /

      return historyVariables;  } }</pre>來自:http://my.oschina.net/wangrikui/blog/506338

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!