Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

文章源碼託管:https://github.com/OUYANGSIHAI/Activiti-learninig
歡迎 star !!!

本來想着閒來無事,前面在項目中剛剛用到了工作流 Activiti 框架,寫寫博客的,但是,事情總是紛紛雜雜,一直拖延到現在,這一節原本想要寫一下關於 Activiti 的 API ,但是,想着太多這樣的博客了,而且顯得太生硬,難以理解,所以,這些 API 就在實際的 demo 中來講解。

一、建立流程圖

在開始做工作流之前,我們首先應該把具體的業務在工作流的部署流程圖體現出來,並且都測試通過,這樣就相當於成功了一半,後面的具體業務的開發就相對輕鬆一些了。

首先,我們先看一看在 idea 中有哪些控件,常用的控件進行了標註。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

下面我們講一下建立一個流程圖的具體過程。

首先,我們需要拉入一個開始節點bpmn 文件中,這是圖像化的界面,只需要拉入即可。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

然後,我們從控件中拉入一個 UserTask 用戶任務節點到 bpmn 文件中。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

這樣子就有了兩個審批節點了,如果還需要其他的一些業務需求,我們還可以加入一些網關,這裏就暫時不加了。

最後,我們只需要一個結束節點 EndEvent 就完成了這個工作流的部署圖的繪製。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

我們最後看一下完整的例子。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

看似已經完成了整個流程圖的繪製,但美中不足的是我們目前並沒有設置導師審批輔導員審批到底由誰來審批,所以,我們還是需要來瞅一瞅怎麼設置審批人員

首先,我們需要選中一個審批節點,例如,選中導師審批這個節點。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

其次,我們就顯而易見的可以在 idea 編輯器的左側看到一個名爲 BPMN editor 的屬性框,裏面包括一個用戶任務節點的可以設置的所有屬性

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

注意:候選用戶、候選組、任務監聽器,這三個屬性這裏暫時不講,後面再補充。

由於,這一步我們需要設置審批人,所以,我們需要在 Assignee 這個屬性中設置我們的審批人。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

如上圖,這裏設置導師審批這個節點的審批人爲 sihai 。設置審批人除了直接設置之外,還有兩種方式設置,後面再補充。

另外一個審批節點也通過這種方式設置就可以完成審批人的設置了。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

very good,這樣就基本完成了一個流程圖的創建。接下來,我們將通過實例來具體講解Activiti 的 API 的講解

二、實例講解 API

在上面這個流程圖的創建中,我們還沒有生成 png 圖片,所以,如果不知道如何生成的,可以參考之前的這篇文章:Activiti工作流從入門到入土:整合spring

既然是講解 API ,那麼還是先看一下主要有哪些 API 吧,這樣纔有一個整體把握。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

這些 API 具體怎麼用,接下來一一道來。

2.1 流程定義

既然是流程定義,那肯定少不了如何部署流程定義了。

2.1.1 部署流程定義方法1
 @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;

    /**
     * 部署流程定義(從classpath)
     */
    @Test
    public void deploymentProcessDefinition_classpath(){
        Deployment deployment = processEngine.getRepositoryService()//與流程定義和部署對象相關的Service
                .createDeployment()//創建一個部署對象
                .name("流程定義")//添加部署的名稱
                .addClasspathResource("bpmn/hello.bpmn")//從classpath的資源中加載,一次只能加載一個文件
                .addClasspathResource("bpmn/hello.png")//從classpath的資源中加載,一次只能加載一個文件
                .deploy();//完成部署
        System.out.println("部署ID:"+deployment.getId());
        System.out.println("部署名稱:"+deployment.getName());
    }

注意:這裏用的是整合 spring 之後的 junit 測試環境,如何整合 spring 請看這篇文章:Activiti工作流從入門到入土:整合spring

輸出結果:

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

這樣,我們就部署了這個流程。那麼具體是怎麼操作的呢,我們再來看看整個過程。

  • 獲取流程引擎對象:這個跟 spring 整合了。

  • 通過流程引擎獲取了一個 RepositoryService 對象(倉庫對象)

  • 由倉庫的服務對象產生一個部署對象配置對象,用來封裝部署操作的相關配置。

  • 這是一個鏈式編程,在部署配置對象中設置顯示名,上傳流程定義規則文件

  • 向數據庫表中存放流程定義的規則信息。

其實,這一步操作,用到了 Activiti 數據庫中的三張表,分別是:act_re_deployment(部署對象表),act_re_procdef(流程定義表),act_ge_bytearray(資源文件表)。

我們看看這三張表的變化:
1)act_re_deployment
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

可以看到,部署ID和部署名稱就存在這張表中。

2)act_re_procdef

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

這張表中,存放了部署的Deployment_ID部署流程的id、bpmn資源文件名稱、png圖片名稱等信息。

3)act_ge_bytearray

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

存儲流程定義相關的部署信息。即流程定義文檔的存放地。每部署一次就會增加兩條記錄,一條是關於 bpmn 規則文件的,一條是圖片的(如果部署時只指定了 bpmn 一個文件,activiti 會在部署時解析 bpmn 文件內容自動生成流程圖)。兩個文件不是很大,都是以二進制形式存儲在數據庫中。

2.1.2 部署流程定義方法2
 /**
     * 部署流程定義(從zip)
     */
    @Test
    public void deploymentProcessDefinition_zip(){
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("bpmn/hello.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        Deployment deployment = processEngine.getRepositoryService()//與流程定義和部署對象相關的Service
                .createDeployment()//創建一個部署對象
                .name("流程定義")//添加部署的名稱
                .addZipInputStream(zipInputStream)//指定zip格式的文件完成部署
                .deploy();//完成部署
        System.out.println("部署ID:"+deployment.getId());//
        System.out.println("部署名稱:"+deployment.getName());//
    }

項目結構如下:
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

輸出結果:
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

如此看來,也是沒有任何問題的,唯一的區別只是壓縮成zip格式的文件,使用zip的輸入流用作部署流程定義,其他使用並無區別。

部署了流程定義之後,我們應該想查看一下流程定義的一些信息。

2.1.3 查看流程定義
/**
     * 查詢流程定義
     */
    @Test
    public void findProcessDefinition(){
        List<ProcessDefinition> list = processEngine.getRepositoryService()//與流程定義和部署對象相關的Service
                .createProcessDefinitionQuery()//創建一個流程定義的查詢
                /**指定查詢條件,where條件*/
//                      .deploymentId(deploymentId)//使用部署對象ID查詢
//                      .processDefinitionId(processDefinitionId)//使用流程定義ID查詢
//                      .processDefinitionKey(processDefinitionKey)//使用流程定義的key查詢
//                      .processDefinitionNameLike(processDefinitionNameLike)//使用流程定義的名稱模糊查詢

                /**排序*/
                .orderByProcessDefinitionVersion().asc()//按照版本的升序排列
//                      .orderByProcessDefinitionName().desc()//按照流程定義的名稱降序排列

                /**返回的結果集*/
                .list();//返回一個集合列表,封裝流程定義
//                      .singleResult();//返回惟一結果集
//                      .count();//返回結果集數量
//                      .listPage(firstResult, maxResults);//分頁查詢
        if(list!=null && list.size()>0){
            for(ProcessDefinition pd:list){
                System.out.println("流程定義ID:"+pd.getId());//流程定義的key+版本+隨機生成數
                System.out.println("流程定義的名稱:"+pd.getName());//對應hello.bpmn文件中的name屬性值
                System.out.println("流程定義的key:"+pd.getKey());//對應hello.bpmn文件中的id屬性值
                System.out.println("流程定義的版本:"+pd.getVersion());//當流程定義的key值相同的相同下,版本升級,默認1
                System.out.println("資源名稱bpmn文件:"+pd.getResourceName());
                System.out.println("資源名稱png文件:"+pd.getDiagramResourceName());
                System.out.println("部署對象ID:"+pd.getDeploymentId());
                System.out.println("*********************************************");
            }
        }
    }

輸出結果:
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

查詢流程定義小結:

  • 流程定義和部署對象相關的Service都是 RepositoryService ,後面會發現關於流程定義的都是 RepositoryService

  • 通過這個 createProcessDefinitionQuery() 方法來設置一些查詢參數,比如通過條件、降序升序等。
2.1.4 刪除流程定義

通過刪除部署 ID 爲2501的信息。

/**
     * 刪除流程定義
     */
    @Test
    public void deleteProcessDefinition(){
        //使用部署ID,完成刪除,指定部署對象id爲2501刪除
        String deploymentId = "2501";
        /**
         * 不帶級聯的刪除
         *    只能刪除沒有啓動的流程,如果流程啓動,就會拋出異常
         */
//      processEngine.getRepositoryService()//
//                      .deleteDeployment(deploymentId);

        /**
         * 級聯刪除
         *    不管流程是否啓動,都能可以刪除
         */
        processEngine.getRepositoryService()//
                .deleteDeployment(deploymentId, true);
        System.out.println("刪除成功!");
    }

輸出結果:
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

到數據庫查看,發現 act_re_deployment 中的數據已經不存在了。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

  • 這裏還是通過 getRepositoryService() 方法獲取部署定義對象,然後指定 ID 刪除信息。
2.1.5 獲取流程定義文檔的資源

這裏的作用主要是查詢圖片,通過圖片可以在後面做流程展示用的。我們看看具體怎麼查看。

/**
     * 查看流程圖
     *
     * @throws IOException
     */
    @Test
    public void viewPic() throws IOException {
        /**將生成圖片放到文件夾下*/
        String deploymentId = "5001";
        //獲取圖片資源名稱
        List<String> list = processEngine.getRepositoryService()//
                .getDeploymentResourceNames(deploymentId);
        //定義圖片資源的名稱
        String resourceName = "";
        if (list != null && list.size() > 0) {
            for (String name : list) {
                if (name.indexOf(".png") >= 0) {
                    resourceName = name;
                }
            }
        }

        //獲取圖片的輸入流
        InputStream in = processEngine.getRepositoryService()//
                .getResourceAsStream(deploymentId, resourceName);

        //將圖片生成到F盤的目錄下
        File file = new File("F:/" + resourceName);

        //將輸入流的圖片寫到磁盤
        FileUtils.copyInputStreamToFile(in, file);
    }

在F盤下,可以找到圖片。
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

2.1.6 查詢最新版本的流程定義
 /**
     * 查詢最新版本的流程定義
     */
    @Test
    public void findLastVersionProcessDefinition() {
        List<ProcessDefinition> list = processEngine.getRepositoryService()//
                .createProcessDefinitionQuery()//
                .orderByProcessDefinitionVersion().asc()//使用流程定義的版本升序排列
                .list();
        /**
         map集合的特點:當map集合key值相同的情況下,後一次的值將替換前一次的值
         */
        Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
        if (list != null && list.size() > 0) {
            for (ProcessDefinition pd : list) {
                map.put(pd.getKey(), pd);
            }
        }
        List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());
        if (pdList != null && pdList.size() > 0) {
            for (ProcessDefinition pd : pdList) {
                System.out.println("流程定義ID:" + pd.getId());//流程定義的key+版本+隨機生成數
                System.out.println("流程定義的名稱:" + pd.getName());//對應hello.bpmn文件中的name屬性值
                System.out.println("流程定義的key:" + pd.getKey());//對應hello.bpmn文件中的id屬性值
                System.out.println("流程定義的版本:" + pd.getVersion());//當流程定義的key值相同的相同下,版本升級,默認1
                System.out.println("資源名稱bpmn文件:" + pd.getResourceName());
                System.out.println("資源名稱png文件:" + pd.getDiagramResourceName());
                System.out.println("部署對象ID:" + pd.getDeploymentId());
                System.out.println("*********************************************************************************");
            }
        }
    }

輸出結果:
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

2.1.7 流程定義總結

1、部署流程定義用到了 Activiti 的下面的幾張表。

  • act_re_deployment:部署對象表
  • act_re_procdef:流程定義表
  • act_ge_bytearray:資源文件表
  • act_ge_property:主鍵生成策略表

2、我們發現部署流程定義的操作都是在 RepositoryService 這個類下進行操作的,我們只需要通過 getRepositoryService() 拿到對象,通過鏈式規則就可以進行部署流程定義的所有操作。

2.2 工作流完整實例的使用

這一節,我們通過一個完整的例子,來總結一下前面講過的一些基本的知識,這樣能夠更好的學習前面以及後面的知識點,這也算是一個過渡的章節。

回到第一節的建立流程圖,我們已經將基本的 bpmn 圖已經建立好了,但是,需要做一個完整的實例,我們還是需要補充一些內容的,這樣才能夠把這樣的一個實例做好,我們先把第一節的那個 bpmn 圖拿過來。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

首先,我們需要明確:這個圖到目前爲止,我們只是簡簡單單的把流程給畫出來了,比如,我們需要審覈的時候,是需要具體到某一個具體的人員去審覈的,所以,我們需要給每個節點設置審覈的具體人員。

注意:設置節點的審覈人員後面還會分一節細講,這裏只是做一個簡單的實例,所以,只需要這裏能夠看懂,做好就ok了。

設置審覈人員步驟

首先,我們需要選中一個節點,例如,下圖中的“導師審批”節點。
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

接下來,在左邊的工具欄,我們會看到好多選項,有一項爲 Assignee ,我們需要在這個選項中設置我們這個節點需要設置的審批人。

Assignee設置格式:直接使用英文或者中文都可以,例如,sihai,更復雜的設置後面再講。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

下面的節點設置也是跟上面一模一樣。

輔導員審批的審批人員是:歐陽思海。
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

perfect,這樣流程圖的任務就完成了,下面我們就可以進行這個實例的測試階段了。

1)部署流程定義
部署流程定義,在前面的章節已經講過了,有兩種方式進行處理,一種是加載 bpmn 文件和 png 文件,還有一種是將這兩個文件壓縮成 zip 格式的壓縮文件,然後加載。這裏我們使用第一種方式進行處理。

/**
     * 部署流程定義(從classpath)
     */
    @Test
    public void deploymentProcessDefinition_classpath() {
        Deployment deployment = processEngine.getRepositoryService()//與流程定義和部署對象相關的Service
                .createDeployment()//創建一個部署對象
                .name("hello")//添加部署的名稱
                .addClasspathResource("bpmn/hello.bpmn")//從classpath的資源中加載,一次只能加載一個文件
                .addClasspathResource("bpmn/hello.png")//從classpath的資源中加載,一次只能加載一個文件
                .deploy();//完成部署
        log.info("部署ID:" + deployment.getId());
        log.info("部署名稱:" + deployment.getName());
    }

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

現在流程定義已經有了,下面我們就需要啓動這個流程實例。

關於關於這一步做了什麼事情,可以在前面的章節查看。

2)啓動流程實例

 /**
     * 啓動流程實例
     */
    @Test
    public void startProcessInstance(){
        //1、流程定義的key,通過這個key來啓動流程實例
        String processDefinitionKey = "hello";
        //2、與正在執行的流程實例和執行對象相關的Service
        // startProcessInstanceByKey方法還可以設置其他的參數,比如流程變量。
        ProcessInstance pi = processEngine.getRuntimeService()
                .startProcessInstanceByKey(processDefinitionKey);//使用流程定義的key啓動流程實例,key對應helloworld.bpmn文件中id的屬性值,使用key值啓動,默認是按照最新版本的流程定義啓動
        log.info("流程實例ID:"+pi.getId());//流程實例ID
        log.info("流程定義ID:"+pi.getProcessDefinitionId());//流程定義ID
    }

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API
注意: processDefinitionKey 是 bpmn 文件的名稱。

步驟
1 獲取到 runtimeService 實例。
2 通過 bpmn 文件的名稱,也就是 processDefinitionKey 來啓動流程實例。
3 啓動流程後,流程的任務就走到了導師審批節點。

下面就是查詢個人任務了,我們可以查詢導師審批節點的任務。

3)查詢個人任務

/**
     * 查詢當前人的個人任務
     */
    @Test
    public void findPersonalTask(){
        String assignee = "sihai";
        List<Task> list = processEngine.getTaskService()//與正在執行的任務管理相關的Service
                .createTaskQuery()//創建任務查詢對象
                /**查詢條件(where部分)*/
                .taskAssignee(assignee)//指定個人任務查詢,指定辦理人
//                      .taskCandidateUser(candidateUser)//組任務的辦理人查詢
//                      .processDefinitionId(processDefinitionId)//使用流程定義ID查詢
//                      .processInstanceId(processInstanceId)//使用流程實例ID查詢
//                      .executionId(executionId)//使用執行對象ID查詢
                /**排序*/
                .orderByTaskCreateTime().asc()//使用創建時間的升序排列
                /**返回結果集*/
//                      .singleResult()//返回惟一結果集
//                      .count()//返回結果集的數量
//                      .listPage(firstResult, maxResults);//分頁查詢
                .list();//返回列表
        if(list!=null && list.size()>0){
            for(Task task:list){
                log.info("任務ID:"+task.getId());
                log.info("任務名稱:"+task.getName());
                log.info("任務的創建時間:"+task.getCreateTime());
                log.info("任務的辦理人:"+task.getAssignee());
                log.info("流程實例ID:"+task.getProcessInstanceId());
                log.info("執行對象ID:"+task.getExecutionId());
                log.info("流程定義ID:"+task.getProcessDefinitionId());
                log.info("********************************************");
            }
        }
    }

通過 sihai 這個審批人,查詢到了下面的信息。
Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

分析步驟
1 首先通過 getTaskService 方法,獲取到 TaskService 對象。
2 通過 createTaskQuery 方法創建查詢對象。
3 通過 taskAssignee 方法設置審覈人。
4 對於結果的返回,我們可以通過 orderByTaskCreateTime().asc() 設置排序等其他信息。

這裏需要注意一點,查詢到的一個重要的信息是:任務 id(taskId),下一步,我們需要通過這個任務 id ,來完成任務。

4)辦理個人任務

/**
     * 完成我的任務
     */
    @Test
    public void completePersonalTask() {
        //任務ID,上一步查詢得到的。
        String taskId = "7504";
        processEngine.getTaskService()//與正在執行的任務管理相關的Service
                .complete(taskId);
        log.info("完成任務:任務ID:" + taskId);
    }

通過上一步的任務 id :7504,完成任務。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

步驟
1 首先,通過 getTaskService 方法拿到 TaskService 對象。
2 調用 complete 方法,給定具體的任務 id 完成任務。

5)查詢流程狀態(判斷流程走到哪一個節點)
這個接口還是十分需要的,當我們在具體的業務中,我們需要判斷我們的流程的狀態是什麼狀態,或者說我們的流程走到了哪一個節點的時候,這一個接口就讓我們實現業務省了非常多的事情。

/**
     * 查詢流程狀態(判斷流程走到哪一個節點)
     */
    @Test
    public void isProcessActive() {
        String processInstanceId = "7501";
        ProcessInstance pi = processEngine.getRuntimeService()//表示正在執行的流程實例和執行對象
                .createProcessInstanceQuery()//創建流程實例查詢
                .processInstanceId(processInstanceId)//使用流程實例ID查詢
                .singleResult();
        if (pi == null) {
            log.info("流程已經結束");
        } else {
            log.info("流程沒有結束");
            //獲取任務狀態
            log.info("節點id:" + pi.getActivityId());
        }
    }

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

步驟:
1 獲取到流程實例 ProcessInstance 對象。
2 通過 getActivityId 方法獲取到實例 Id(節點 id )。

那麼拿到了節點 Id 有什麼作用呢?
其實,有了這個 Id 之後,我們就可以判斷流程走到哪一步了。例如,上面的輸出的節點 id 是 _4,這個 _4 就是對應 輔導員審批節點的 id,所以,我們就可以判讀流程其實是已經走到這個節點了,後期需要在頁面顯示流程狀態的時候就發揮作用了。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

6)查詢流程執行的歷史信息
通過查看 activiti 5 的官方 API 接口,發現查看歷史信息有下面的查詢接口。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

下面我們通過上面的實例對下面的方法一一進行測試。

歷史活動實例查詢接口

/**
     * 歷史活動查詢接口
     */
    @Test
    public void findHistoryActivity() {
        String processInstanceId = "7501";
        List<HistoricActivityInstance> hais = processEngine.getHistoryService()//
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        for (HistoricActivityInstance hai : hais) {
            log.info("活動id:" + hai.getActivityId()
                    + "   審批人:" + hai.getAssignee()
                    + "   任務id:" + hai.getTaskId());
            log.info("************************************");
        }
    }

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

通過這個接口不僅僅查到這些信息,還有其他的方法,可以獲取更多的關於歷史活動的其他信息。

歷史流程實例查詢接口

/**
     * 查詢歷史流程實例
     */
    @Test
    public void findHistoryProcessInstance() {
        String processInstanceId = "7501";
        HistoricProcessInstance hpi = processEngine.getHistoryService()// 與歷史數據(歷史表)相關的Service
                .createHistoricProcessInstanceQuery()// 創建歷史流程實例查詢
                .processInstanceId(processInstanceId)// 使用流程實例ID查詢
                .orderByProcessInstanceStartTime().asc().singleResult();
        log.info(hpi.getId() + "    " + hpi.getProcessDefinitionId() + "    " + hpi.getStartTime() + "    "
                + hpi.getEndTime() + "     " + hpi.getDurationInMillis());
    }

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

這個接口可以查詢到關於歷史流程實例的所有信息。

歷史任務實例查詢接口

 /**
     * 查詢歷史任務
     */
    @Test
    public void findHistoryTask() {
        String processInstanceId = "7501";
        List<HistoricTaskInstance> list = processEngine.getHistoryService()// 與歷史數據(歷史表)相關的Service
                .createHistoricTaskInstanceQuery()// 創建歷史任務實例查詢
                .processInstanceId(processInstanceId)//
                .orderByHistoricTaskInstanceStartTime().asc().list();
        if (list != null && list.size() > 0) {
            for (HistoricTaskInstance hti : list) {
                log.info("\n 任務Id:" + hti.getId() + "    任務名稱:" + hti.getName() + "    流程實例Id:" + hti.getProcessInstanceId() + "\n 開始時間:"
                        + hti.getStartTime() + "   結束時間:" + hti.getEndTime() + "   持續時間:" + hti.getDurationInMillis());
            }
        }
    }

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

這個查詢接口可以查詢到歷史任務信息

歷史流程變量查詢接口

/**
     * 查詢歷史流程變量
     */
    @Test
    public void findHistoryProcessVariables() {
        String processInstanceId = "7501";
        List<HistoricVariableInstance> list = processEngine.getHistoryService()//
                .createHistoricVariableInstanceQuery()// 創建一個歷史的流程變量查詢對象
                .processInstanceId(processInstanceId)//
                .list();
        if (list != null && list.size() > 0) {
            for (HistoricVariableInstance hvi : list) {
                log.info("\n" + hvi.getId() + "   " + hvi.getProcessInstanceId() + "\n" + hvi.getVariableName()
                        + "   " + hvi.getVariableTypeName() + "    " + hvi.getValue());
            }
        }
    }

在這個實例中沒有設置流程變量,所以,這裏是查詢不到任何歷史信息的。

這個接口主要是關於歷史流程變量的設置的一些信息。

歷史本地接口查詢接口

/**
     * 通過執行sql來查詢歷史數據,由於activiti底層就是數據庫表。
     */
    @Test
    public void findHistoryByNative() {
        HistoricProcessInstance hpi = processEngine.getHistoryService()
                .createNativeHistoricProcessInstanceQuery()
                .sql("查詢底層數據庫表的sql語句")
                .singleResult();
        log.info("\n" + hpi.getId() + "    " + hpi.getProcessDefinitionId() + "    " + hpi.getStartTime()
                + "\n" + hpi.getEndTime() + "     " + hpi.getDurationInMillis());
    }

這個接口是提供直接通過 sql 語句來查詢歷史信息的,我們只需要在 sql() 方法中寫原生的 sql 語句就可以進行數據查詢。

寫到這裏,我想應該通過這樣的一個完整的實例將 Activiti 工作流的 API 都介紹的差不多了,這一節到這裏也就要說拜拜了。再回看一下文章開頭的 API 接口,這也算是這一節的總結。

Activiti工作流從入門到入土:完整Hello World大比拼(Activiti工作流 API

文章有不當之處,歡迎指正,如果喜歡微信閱讀,你也可以關注我的微信公衆號好好學java,獲取優質學習資源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章