1. 程式人生 > >activiti入門和流程的執行過程(附程式碼)

activiti入門和流程的執行過程(附程式碼)

1.定義bpmn檔案,這個檔案裡是用來定義流程的

2.釋出流程

 釋出流程,流程的key值相同的情況下每次釋出一次,這個流程在資料庫的版本會+1

3.檢視流程定義

列印的資訊

可以看到,我剛才定義的流程已經更新了,現在是版本2了

4.建立流程例項

這裡是使用key來建立一個流程

5.檢視任務

建立一個例項之後,開始執行流程。一個流程分為很多的節點,每個節點對於不同的人就是不同的任務,所以要執行流程就是從檢視自己的任務開始。

在流程定義時我們可以看到 ,start之後,第一個執行事件是提出申請,assignee設定的是 staff

所以查詢任務的時候,可以根據staff檢視任務

執行程式碼後,看到了任務相關資訊

在資料庫中我們可以看到相關資訊

6.辦理任務

這裡的taskId就是上一步查出來的任務id,將任務Id傳進taskService.complete的引數中,執行

執行完成後,資料庫表中的資訊也更新

因為此時流程例項已經走到下一步,此時這個例項的名字是請假審批而不是提出申請了。

然後執行taskId為25002的任務,走到最後一步任務,這個流程例項就完成了。

一定要注意在操作過程中,資料庫的變化,這樣才能更好更快的理解activiti框架

附程式碼:

pom.xml引入依賴

    <!--- Activiti依賴匯入 -->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>5.18.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.activiti</groupId>
          <artifactId>activiti-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>


    <!--- Activiti依賴匯入 -->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>5.18.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.activiti</groupId>
          <artifactId>activiti-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-engine</artifactId>
      <version>5.18.0</version>
      <exclusions>
        <exclusion>
          <artifactId>slf4j-api</artifactId>
          <groupId>org.slf4j</groupId>
        </exclusion>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>jcl-over-slf4j</artifactId>
        </exclusion>
        <exclusion>
          <artifactId>spring-beans</artifactId>
          <groupId>org.springframework</groupId>
        </exclusion>
        <exclusion>
          <artifactId>jackson-core-asl</artifactId>
          <groupId>org.codehaus.jackson</groupId>
        </exclusion>
        <exclusion>
          <artifactId>commons-lang3</artifactId>
          <groupId>org.apache.commons</groupId>
        </exclusion>
        <exclusion>
          <artifactId>mybatis</artifactId>
          <groupId>org.mybatis</groupId>
        </exclusion>

      </exclusions>

    </dependency>

注意這裡的<esclusion> 排除裡面相關的依賴

測試類的程式碼:


public class activitiTest {

    /**
     *  一條語句建立processEngine, 要求:
     * 1、配置檔案必須在classpath根目錄下
     * 2、配置檔名必須為activiti-context.xml或activiti.cfg.xml
     * 3、工廠物件的id必須為processEngine
     */
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    HistoryService historyService = processEngine.getHistoryService();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    TaskService taskService = processEngine.getTaskService();

     /** 通過zipinputstream完成部署
     * 注意:這個的話,需要將bpmn和png檔案進行壓縮成zip檔案,然後放在專案src目錄下即可(當然其他目錄也可以)
     */
    @Test
    public void testDeployFromZipinputStream(){
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("shenqing.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
                .createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
    }

    /**
     * 建立ActivitiEngine 生成資料庫表
     */
    @Test
    public void createActivitiEngine(){

        //取得ProcessEngineConfiguration物件
        ProcessEngineConfiguration engineConfiguration=ProcessEngineConfiguration.
                createStandaloneProcessEngineConfiguration();

        /**2. 通過載入 activiti.cfg.xml 獲取 流程引擎 和自動建立資料庫及表*/

        // 設定建立表的策略 (當沒有表時,自動建立表)
        // = "false";//不會自動建立表,沒有表,則拋異常
        // = "create-drop";//先刪除,再建立表
        // = "true";//假如沒有表,則自動建立
        engineConfiguration.setDatabaseSchemaUpdate("true");
        //通過ProcessEngineConfiguration物件建立 ProcessEngine 物件
        ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
        System.out.println("流程引擎建立成功!");

    }


    /**
     * 檢視流程圖
     * 根據deploymentId和name(在act_ge_bytearray資料表中)
     */
    @Test
    public void testShowImage() throws Exception{
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        InputStream inputStream = processEngine.getRepositoryService()
                /**
                 * deploymentID
                 * 檔案的名稱和路徑
                 */
                .getResourceAsStream("110003","activiti/weekReport.bpmn");
        OutputStream outputStream3 = new FileOutputStream("e:/weekReport.png");
        int b = -1 ;
        while ((b=inputStream.read())!=-1){
            outputStream3.write(b);
        }
        inputStream.close();
        outputStream3.close();
    }

    /**
     * 根據pdid檢視圖片(在act_re_procdef資料表中)
     * @throws Exception
     */
    @Test
    public void testShowImage2() throws Exception{
        InputStream inputStream = processEngine.getRepositoryService()
                .getProcessDiagram("leaveProcess:13:120004");
        OutputStream outputStream = new FileOutputStream("e:/leaveProcess.png");
        int b = -1 ;
        while ((b=inputStream.read())!=-1){
            outputStream.write(b);
        }
        inputStream.close();
        outputStream.close();
    }

    /**
     * 部署流程定義
     */
    @Test
    public void deploy() {

        //獲取倉庫服務 :管理流程定義
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()//建立一個部署的構建器
                .addClasspathResource("activiti/weekReport.bpmn")//從類路徑中新增資源,一次只能新增一個資源
                .name("週報審批流程")//設定部署的名稱
                .category("直銷部")//設定部署的類別
                .deploy();

        System.out.println("部署的id"+deploy.getId());
        System.out.println("部署的名稱"+deploy.getName());
    }

    /**
     * 建立流程例項
     */
    @Test
    public void startProcessInstance(){
        String leaveId = "007";
        String staffId = "04643";
        HashMap<String,Object> map=new HashMap<>();
        map.put("staffId",staffId);
        // 啟動流程
        String processInstanceKey = "weekReportProcess";
//        三個引數分別為(String processDefinitionKey, String businessKey, HashMap<String, Object> variables)
        ProcessInstance pi = processEngine.getRuntimeService()
                .startProcessInstanceByKey(processInstanceKey,leaveId,map);
        System.out.println("建立流程例項成功,流程例項id:"+pi.getId()
                + "  流程定義id:" + pi.getProcessDefinitionId());
        //預設完成第一步申請人的申請步驟
        Task task = processEngine.getTaskService()
                .createTaskQuery()
                .processInstanceId(pi.getId())
                .singleResult();
        String nextStaffId = "04646";
        map.put("staffId",nextStaffId);
        processEngine.getTaskService()
                .complete(task.getId(),map);
    }

    /**
     * 查詢所有的正在執行的任務
     */
    @Test
    public void testQueryTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Task> tasks = processEngine.getTaskService()
                .createTaskQuery()
                .list();
        for (Task task : tasks) {
            System.out.println(task.getName());
        }
    }

    /**
     * 根據piid得到當前正在執行的流程例項的正在活動的節點
     */
    @Test
    public void testActivity(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        /**
         * 根據piid得到流程例項
         */
        ProcessInstance pi = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processInstanceId("127501")
                .singleResult();
        String activityId = pi.getActivityId();//當前流程例項正在執行的activityId
        System.out.println(activityId);
    }

    /**
     * 查找個人任務
     */
    @Test
    public void getMyTaskInfo() {
        String staffId = "007";
        List<Task> listTask = processEngine.getTaskService()
                .createTaskQuery()
                .taskAssignee(staffId)
                .list();

        if (listTask != null && listTask.size() > 0) {
            for (Task task : listTask) {
                System.out.println("任務ID:"+task.getId());
                System.out.println("任務名稱:"+task.getName());
                System.out.println("任務時間:"+task.getCreateTime());
                System.out.println("任務的辦理人:"+task.getAssignee());
                System.out.println("任務的例項ID:"+task.getProcessDefinitionId());
                System.out.println("#########################################");
            }
        }
    }

    /**
     *  執行任務
     * @return
     */
    @Test
    public void completeMyPersonTask() {
        String taskId = "170002";
        String nextStaffId = "02222";
        HashMap<String,Object> map=new HashMap<>();
        map.put("staffId",nextStaffId);
        processEngine.getTaskService()
                .complete(taskId,map);
        System.out.println("檢視當前任務成功"+"完成任務,任務ID:" + taskId);
    }

    /**
     *  終止流程例項
     * @return
     */
    @Test
    public void deleteProcessInstance() {
        String taskId = "135002";
        String reason = "太少了,100個新增!";
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId()).singleResult();
        processEngine.getRuntimeService()
                .deleteProcessInstance(processInstance.getId(),reason);
        System.out.println("停止taskId為:" + taskId+"的任務");
    }

    /**
     * 查詢執行物件表,使用流程例項ID和當前活動的名稱(receivetask1)
     */
    @Test
    public void queryExecution(){
        ProcessInstance pi = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processDefinitionKey("weekReportProcess")
                .singleResult();
        //3.查詢執行物件表,使用流程例項ID和當前活動的名稱(receivetask1)
        String processInstanceId = pi.getId();//得到流程例項ID
        Execution execution1 = processEngine.getRuntimeService()
                .createExecutionQuery()
                .processInstanceId(processInstanceId)//流程例項ID
//                .activityId("receivetask1")//當前活動的名稱
                .singleResult();
        //5.向後執行一步
        processEngine.getRuntimeService()
                .signal(execution1.getId());

    }

    /**
     *  直接跳過某一個執行步驟
     * @return
     */
    @Test
    public void passTask() {
        String executionId =  "127501";
        processEngine.getRuntimeService().signal(executionId);
        System.out.println("直接執行下一步");
    }

    /**
     * 直接完成執行者為空的步驟,直到有執行者的那一步並設定執行者id
     */
    @Test
    public void passNull(){
        TaskService taskService = processEngine.getTaskService();
        //上一個任務的執行者
        String assignee =  "04646";
        //當前流程例項Id
        String processInstanceId = "165001";

        //整個流程中,所有節點涉及的執行人全部加入到一個數組中
        ArrayList<String>  assignees= new ArrayList<>();
        assignees.add("04643");
        assignees.add("04646");
        assignees.add("");
        assignees.add("007");

        //獲得上一個執行者後面的陣列
        List<String> subAssigneeList = assignees.subList(assignees.indexOf(assignee)+1, assignees.size());
        //遍歷陣列 查詢下一個執行者是否為空
        //如果為空就預設完成進入下一步,直到第一個不為空的執行者 跳出foreach
        for (String l:subAssigneeList
             ) {
            System.out.println("subList的位置"+subAssigneeList.indexOf(l)+"元素是:"+l);

            //如果 下一個任務的執行人為空,直接預設完成這一步,並根據陣列將下一個執行人加入下一個任務中
            if (l.equals(null) || l.length() == 0){
                Task task = taskService.createTaskQuery()
                        .processInstanceId(processInstanceId)
                        .singleResult();
                HashMap<String, Object> var = new HashMap<>();
                var.put("staffId",subAssigneeList.get( subAssigneeList.indexOf(l) + 1));
                taskService.complete(task.getId(),var);
                System.out.println("這個位置的執行者是空,直接預設完成這一步");
            }else {
                System.out.println("存在執行者,跳出此迴圈");
                break;
            }
        }
        System.out.println(subAssigneeList);
    }

    @Test
    public void queryProcessInstanceHistory(){
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .orderByHistoricActivityInstanceEndTime()
                .desc()
                .processInstanceId("132501")
                .list();
        for (HistoricActivityInstance h:list){
            System.out.println(h.getId());
            System.out.println(h.getActivityId());
            System.out.println(h.getAssignee());
            System.out.println(h.getExecutionId());
            System.out.println(h.getProcessInstanceId());
            System.out.println("##############################");

        }
    }

}

activiti.cfg.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:sqlserver://xxxDatabaseName=activititest" />
        <property name="jdbcDriver" value="" />
        <property name="jdbcUsername" value="" />
        <property name="jdbcPassword" value="" />
        <!-- 建表策略 -->
        <!--
            "false";不能自動建立表,需要表存在
            "create-drop";先刪除表再建立表
            "true";如果表不存在,自動建立表
            -->
        <property name="databaseSchemaUpdate" value="true" />
    </bean>

</beans>

spring配置檔案裡可以這麼配置

 <!-- 配置activiti -->
        <context:component-scan base-package="com.wolwo.activiti">
                <context:exclude-filter type="annotation"
                                        expression="org.springframework.stereotype.Controller" />
                <context:exclude-filter type="annotation"
                                        expression="org.springframework.web.bind.annotation.ControllerAdvice" />
        </context:component-scan>


        <!-- 配置流程引擎檔案 -->
        <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
                <property name="dataSource" ref="dataSource" />
                <property name="transactionManager" ref="transactionManager" />
                <property name="labelFontName" value="宋體"/>
                <property name="activityFontName" value="宋體" />
                <!-- 是否自動建立23張表 -->
                <property name="databaseSchemaUpdate" value="true" />

                <property name="jobExecutorActivate" value="false" />
                <property name="deploymentResources" value="activiti/**/*.bpmn"/>
        </bean>

        <!-- 配置建立流程引擎物件 -->
        <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
        </bean>

        <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
        <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
        <bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
        <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
        <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
        <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
        <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />