1. 程式人生 > >Activiti5工作流筆記一

Activiti5工作流筆記一

sys 名稱 find 筆記一 ftw name width rop 筆記

介紹工作流

  網上工作流的定義一大堆,這裏就不去復制了,通俗的理解,工作流就是類似OA系統中請假審批、報銷審批等一系列流程,下級提交的申請只有直系領導才能審批,其他人是沒有權限的,而只有直系領導審批通過後,直系領導的直系領導才可以看到申請,並進行審批,以此類推。。。

  而Activiti工作流就可以實現類似的功能,本筆記將以最簡單的方式讓你明白怎麽使用Activiti工作流,直接上代碼

準備環境

1) JDK1.6或者更高版本

2) 支持的數據庫有:h2, mysql, oracle, postgres, mssql, db2等。

3) 支持activiti5運行的jar包

4) 開發環境為

Eclipse3.7或者以上版本,myeclipse為8.6版本

安裝流程設計器(eclipse插件)

方案一:

有網絡的情況下,安裝流程設計器步驟如下:

1) 打開 Help -> Install New Software. 在如下面板中:

技術分享圖片

2) 在如下Install界面板中,點擊Add按鈕:

技術分享圖片

3) 然後填入下列字段

Name: Activiti BPMN 2.0 designer

Location: http://activiti.org/designer/update/

4) 回到Install界面,在面板正中列表中把所有展示出來的項目都勾上:

技術分享圖片

5) 點擊復選框

Detail部分記得選中 "Contact all updates sites.." , 因為它會檢查所有當前安裝所需要的插件並可以被Eclipse下載.

6) 安裝完以後,點擊新建工程new->Other…打開面板,如果看到下圖內容:

說明安裝成功了。

技術分享圖片

方案二

沒有網絡的情況下,安裝流程設計器步驟如下:

首先下載離線插件包:

https://files.cnblogs.com/files/lm970585581/activiti.zip

將壓縮包解壓後

技術分享圖片

這兩個文件夾復制到Eclipse根目錄下 ,重啟即可

註意:

打開菜單Windows->Preferences->Activiti->Save下流程流程圖片的生成方式:

技術分享圖片

雖然流程引擎在單獨部署bpmn文件時會自動生成圖片,但在實際開發過程中,自動生成的圖片會導致和BPMN

中的坐標有出入,在實際項目中展示流程當前位置圖會有問題。

所在完成以上配置後,會由我們自己來管理流程圖片。在發布流程時把流程規則文件和流程圖片一起上傳就行了。

準備Activiti5開發環境

activiti-5.13->wars目錄下是一些示例項目,解壓activiti-rest項目,導入activiti-rest目錄中WEB-INF\lib下所有包。添加到classpath中。

另外需要根據我們正在使用的數據庫添加相應的數據庫jar包

初始化數據庫

可以在activiti-rest\WEB-INF\classes下找到配置文件:如下

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://192.168.220.130:3306/activiti?useUnicode=true&amp;characterEncoding=utf8"></property>
        <property name="jdbcUsername" value="root"></property>
        <property name="jdbcPassword" value="root"></property>
        <!-- 
            創建表的策略
         -->
        <property name="databaseSchemaUpdate" value="true"></property>
    </bean>
</beans>

調用以下java代碼,即可把需要的表創建出來

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.junit.Test;

public class CreateTable {
    @Test
    public void testCreateTable(){
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
            .buildProcessEngine();
    }
}

HelloWorld程序

先畫請假流程圖

技術分享圖片

註意:

properties=>General中的ID和NAME可以設置每個步驟的名稱:

技術分享圖片

每個審批過程的properties=>Main config=>Assignee:設置能夠審批的對象,這裏部門經理審批設置為:張三,總經理審批設置為:李四

技術分享圖片

保存後,在根目錄下生成:技術分享圖片

JAVA程序如下:

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.task.Task;
import org.junit.Test;

/**
 * 1、部署流程圖
 * 2、啟動流程實例
 * 3、發起申請
 * 4、審批
 * @author zd
 *
 */
public class HelloWorld {
    /**
     * 部署流程圖
     */
    @Test
    public void testDeploy(){
        //產生流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //獲取倉庫流程的實例
        processEngine.getRepositoryService()
        .createDeployment()
        .addClasspathResource("qingjia.bpmn")
        .addClasspathResource("qingjia.png")
        .deploy();
        /**
         * 這裏使用RepositoryService部署流程定義
           addClasspathResource表示從類路徑下加載資源文件,一次只能加載一個文件
         */
    }
    
    /**
     * 啟動流程實例  pi=process instance
     */
    @Test
    public void testStartPI(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRuntimeService()
        .startProcessInstanceById("qingjia:1:4");//ID在act_re_procdef這個表中可以看到
        //這裏使用RuntimeService啟動流程實例
    }
    
    /**
     * 完成任務
     */
    @Test
    public void testFinishTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getTaskService()
        .complete("104");//act_ru_task表中獲取
    }
    
    /**
     * 根據張三查詢任務
     */
    @Test
    public void testQueryTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //查詢任務列表
        List<Task> tasks = processEngine.getTaskService()
        .createTaskQuery()
        .taskAssignee("張三")
        .list();
        for (Task task : tasks) {
            System.out.println(task.getName());
        }
    }
}

流程定義

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipInputStream;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.junit.Test;
import org.springframework.transaction.annotation.Transactional;

/**
 * pd=process definition
 * @author zd
 *   1、把流程圖部署到activiti的引擎中   重點
 *       classpath
 *       inputstream
 *       zipinputstream
 *   2、對流程圖進行刪除   重點
 *   3、獲取到流程圖和bpmn文件  重點
 *   4、查詢  了解
 *      查詢部署
 *      查詢流程定義
 */
public class PDTest {
    /**
     * 涉及到的表
     *     act_ge_bytearray
     *         1、說明
     *             該表存儲了bpmn文件和png圖片
     *             從字段可以看出,根據deploymentID可以查詢bpmn文件和png圖片
     *         2、字段
     *             name_:存儲該文件的路徑名稱
     *             deploymentid_id_:部署表的ID
     *             byte_:存放值(bpmn和png)
     *     act_re_deployment
     *         1、說明
     *             該表存儲了部署的動作
     *         2、字段
     *            ID_:部署ID 主鍵
     *     act_re_procdef
     *         1、說明
     *             流程定義表
     *         2、字段
     *                id: 是由${name}:${version}:隨機數   確定唯一的流程
     *             name_: 流程定義名稱
     *             key_:  流程定義名稱
     *             version_:  某一個流程定義的版本
     *             deployment_id_:部署表的ID
     *             
     *  說明:
     *      1、根據deploymentID-->查詢圖片和bpmn文件
     *      2、根據deploymentID-->查詢流程定義
     *      3、只要流程名稱不變,部署一次,版本號加1,id就發生變化,生成了一個新的deploymentID
     *      4、所以deploymentID和pdid是一一對應的關系
     */
    @Test
    public void testDeployFromClasspath(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
        .createDeployment()
        .addClasspathResource("qingjia.bpmn")
        .addClasspathResource("qingjia.png")
        .deploy();
    }
    
    /**
     * 通過inputStream的方式部署
     */
    @Test
    public void testDeployFromInputStream(){
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("qingjia.bpmn");
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
        .createDeployment()
        .addInputStream("qingjia.bpmn", inputStream)
        .deploy();
    }
    
    /**
     * 通過zip的方式部署
     */
    @Test
    public void testDeployFromZip(){
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("qingjia.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
        .createDeployment()
        .addZipInputStream(zipInputStream)
        .deploy();
    }
    
    /**
     * 把查詢出來的圖片放到E盤的根目錄下
     */
    @Test
    public void testShowImage() throws Exception{
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        InputStream inputStream = processEngine.getRepositoryService()
        /**
         * 參數為pdid
         */
        .getProcessDiagram("qingjia:1:4");
        /**
         * 得到一個圖片
         */
        //    OutputStream outputStream = new FileOutputStream("e:/processimg.png");
        //    for(int b=-1;(b=inputStream.read())!=-1;){
        //        outputStream.write(b);
        //    }
        //    inputStream.close();
        //    outputStream.close();
        /***************************************************************************************/
        /**
         *   第一個參數為deploymentId
         *   第二個參數為resourceName
         */
        /********************************************************************************/
        /**
         * 得到的是一個圖片
         */
            //        InputStream inputStream2 = processEngine.getRepositoryService()
            //        .getResourceAsStream("101", "qingjia.png");
            //        
            //        OutputStream outputStream2 = new FileOutputStream("e:/processimg2.png");
            //        for(int b=-1;(b=inputStream2.read())!=-1;){
            //            outputStream2.write(b);
            //        }
            //        inputStream2.close();
            //        outputStream2.close();
            /**********************************************************************************/
        /**
         * 得到的是bpmn文件 
         */
        InputStream inputStream3 = processEngine.getRepositoryService()
        .getProcessModel("qingjia:1:4");
        OutputStream outputStream3 = new FileOutputStream("e:/processimg3.bpmn");
        for(int b=-1;(b=inputStream3.read())!=-1;){
            outputStream3.write(b);
        }
        inputStream3.close();
        outputStream3.close();
        /*************************************************************************************/

    }
    
    /**
     * 查詢流程部署
     */
    @Test
    public void testQueryDeploy(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Deployment> deployments = processEngine.getRepositoryService()
        .createDeploymentQuery()
        .list();
        for (Deployment deployment : deployments) {
            System.out.println(deployment.getId());
        }
    }
    
    /**
     * 根據部署ID查詢部署  一個結果
     */
    @Test
    public void testQueryDeployById(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        Deployment deployment = processEngine.getRepositoryService()
        .createDeploymentQuery()
        .deploymentId("1")
        .singleResult();
        
            System.out.println(deployment.getId());
        
    }
    
    /**
     * 查詢所有的流程定義
     */
    @Test
    public void testQueryPD(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<ProcessDefinition> processDefinitions = processEngine.getRepositoryService()
        .createProcessDefinitionQuery()
        .list();
        for (ProcessDefinition processDefinition : processDefinitions) {
            System.out.println(processDefinition.getKey());
            System.out.println(processDefinition.getId());
            System.out.println(processDefinition.getVersion());
        }
    }
    
    /**
     * 按照版本的從高到低進行排序
     */
    @Test
    public void testQueryPDByVersion(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<ProcessDefinition> processDefinitions = processEngine.getRepositoryService()
        .createProcessDefinitionQuery()
        .orderByProcessDefinitionVersion()
        .desc()
        .list();
        for (ProcessDefinition processDefinition : processDefinitions) {
            System.out.println(processDefinition.getKey());
            System.out.println(processDefinition.getId());
            System.out.println(processDefinition.getVersion());
        }
    }
    
    /**
     * 根據pdid查詢流程定義
     * 根據 pdkey查詢流程定義
     */
    //略。。
    
    /**
     * 刪除
     */
    @Test
    public void testDelete(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRepositoryService()
        //.deleteDeployment("");//該方法只能刪除流程定義,一般不會使用
        .deleteDeployment("1", true);//該方法不僅能夠刪除流程定義,而且能夠刪除正在運行的流程實例
    }
}

流程實例、任務的執行

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.bpmn.parser.handler.ProcessParseHandler;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

/**
 * pi=process instance
 * @author zd
 * 1、啟動流程實例
 * 2、完成任務
 * 3、任務的查詢
 *         1、根據任務的執行人查詢任務
 *         2、可以根據任務查詢任務的執行人
 *         3、查看歷史任務
 * 4、怎麽樣查看流程實例是否結束
 */
public class PITest {
    /**
     * 啟動流程實例
     *    涉及到的表
     *       act_hi_actinst   hi:history   actinst:action instance
     *          1、概念
     *               所有的正在執行的或者已經完成的節點
     *          2、字段
     *              act_type_:為節點的類型
     *              end_time_: 如果有值,說明該節點已經結束了
     *       act_hi_procinst   procinst:process instance
     *          1、概念
     *               所有的正在執行的或者已經完成的流程實例
     *          2、字段
     *               end_time_:如果該字段有值,說明這個流程實例已經結束了
     *               end_act_id_:說明該流程實例是在哪個節點結束的
     *       act_hi_taskinst   taskinst:task instance
     *          1、概念
     *              所有的正在執行的或者已經完成的任務節點
     *          2、字段
     *              end_time_:如果該字段有值,說明任務已經完成了
     *              delete_reason:如果該值為completed,說明該任務處於完成的狀態
     *       act_ru_execution  ru:runtime   
     *          1、概念
     *              代表正在執行的流程實例 
     *          2、字段
     *              id_:主鍵  executionid
     *              proc_inst_id_:  process instanceid
     *              proc_def_id_:pdid
     *              act_id_:當前的流程實例正在執行的節點的ID的值
     *       act_ru_task
     *          1、概念
     *              代表正在執行的任務
     *          2、字段
     *             id_:主鍵   任務ID
     *             execution_id_:piid,executionid
     *             name_:任務名稱
     *          3、說明
     *               該表是一個臨時表,該表中的任務完成以後,這一行會被刪除掉   
     *              
     */
    @Test
    public void testStartPI(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        ProcessInstance pi = processEngine.getRuntimeService()
        .startProcessInstanceById("qingjia:1:304");
        System.out.println(pi.getId());
    }
    
    /**
     * 查詢所有的正在執行的流程實例
     */
    @Test
    public void testQueryPI(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<ProcessInstance> processInstances = processEngine.getRuntimeService()
        .createProcessInstanceQuery()
        .list();
        for (ProcessInstance processInstance : processInstances) {
            System.out.println(processInstance.getActivityId());
            System.out.println(processInstance.getId());
        }
    }
    
    /**
     * 查詢當前正在執行的節點
     */
    @Test
    public void testQueryActivity(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<String> strings = processEngine.getRuntimeService()
        .getActiveActivityIds("401");
        for (String string : strings) {
            System.out.println(string);
        }
    }
    
    /**
     *獲取當前的流程實例正在運行的節點的坐標
     */
    @Test
    public void getPix(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        /**
         * processDefinitionEntity代表流程圖對象的實體
         * 
         * 根據pdid獲取到流程定義實體
         */
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
                .getProcessDefinition("qingjia:1:304");
        List<String> strings = processEngine.getRuntimeService()
                .getActiveActivityIds("401");  //piid
        for (String string : strings) {
            /**
             * ActivityImpl代表流程圖上的每一個節點
             */
            ActivityImpl activityImpl = processDefinitionEntity.findActivity(string);
            /**
             * 獲取到正在執行的流程節點的坐標
             */
            System.out.println(activityImpl.getHeight());
            System.out.println(activityImpl.getWidth());
            System.out.println(activityImpl.getX());
            System.out.println(activityImpl.getY());
        }
    }
    
    /**
     * 查詢所有的任務
     */
    @Test
    public void testQueryAllTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Task> tasks = processEngine.getTaskService()
        .createTaskQuery()
        .list();
        for (Task task : tasks) {
            System.out.println(task.getId());
            System.out.println(task.getName());
        }
    }
    
    /**
     * 完成任務
     *    需要一個參數:taskId
     */
    @Test
    public void testFinishTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getTaskService()
        .complete("602");
    }
    
    /**
     * 根據任務的執行人查看任務
     */
    @Test
    public void testQueryTaskByAssignee(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Task> tasks = processEngine.getTaskService()
        .createTaskQuery()
        .taskAssignee("張三")
        .list();
        for (Task task : tasks) {
            System.out.println(task.getId());
            System.out.println(task.getName());
        }
    }
    
    /**
     * 根據任務的執行人查看任務,並且按照時間的倒敘排序
     */
    @Test
    public void testQueryTaskByAssigneeByTime_DESC(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Task> tasks = processEngine.getTaskService()
        .createTaskQuery()
        .taskAssignee("張三")
        .orderByTaskCreateTime()
        .desc()
        .list();
        for (Task task : tasks) {
            System.out.println(task.getId());
            System.out.println(task.getName());
        }
    }
    
    /**
     * 根據piid判斷流程實例是否結束
     */
    @Test
    public void testQueryPIByPIID(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        ProcessInstance pi = processEngine.getRuntimeService()
        .createProcessInstanceQuery()
        .processInstanceId("401")
        .singleResult();
        if(pi==null){
            System.out.println("該流程實例已經結束了");
        }else{
            System.out.println("該流程實例正在執行中");
        }
    }
    
    
    /**
     * 查詢已經完成的任務
     */
    @Test
    public void testQueryHistoryTask(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<HistoricTaskInstance> historicTaskInstances = processEngine.getHistoryService()
        .createHistoricTaskInstanceQuery()
        .finished()
        .list();
        for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
            System.out.println(historicTaskInstance.getAssignee());
            System.out.println(historicTaskInstance.getName());
            System.out.println(historicTaskInstance.getId());
        }
    }
    
    /**
     * 查詢已經完成的activityimpl
     */
    @Test
    public void testQueryHistoryActivityImpl(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<HistoricActivityInstance> historicActivityInstances = processEngine.getHistoryService()
        .createHistoricActivityInstanceQuery()
        .list();
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
            System.out.println(historicActivityInstance.getActivityName());
        }
    }
}

Activiti5工作流筆記一