Activiti 學習筆記五:流程變數

衣舞晨風發表於2016-09-05

流程變數在整個工作流中扮演很重要的作用。例如:請假流程中有請假天數、請假原因等一些引數都為流程變數的範圍。流程變數的作用域範圍是只對應一個流程例項。也就是說各個流程例項的流程變數是不相互影響的。流程例項結束完成以後流程變數還儲存在資料庫中(存放到流程變數的歷史表中)。

一、部署流程定義

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /** 部署流程定義(從InputStream) */
    @Test
    public void deploymentProcessDefinition_inputStream() {
        InputStream inputStreambpmn = this.getClass().getResourceAsStream("/diagrams/processVariables.bpmn");
        InputStream inputStreampng = this.getClass().getResourceAsStream("/diagrams/processVariables.png");
        Deployment deployment = processEngine.getRepositoryService()// 與流程定義和部署物件相關的Service
                .createDeployment()// 建立一個部署物件
                .name("流程定義")// 新增部署的名稱
                .addInputStream("processVariables.bpmn", inputStreambpmn)// 使用資原始檔的名稱(要求:與資原始檔的名稱要一致),和輸入流完成部署
                .addInputStream("processVariables.png", inputStreampng)// 使用資原始檔的名稱(要求:與資原始檔的名稱要一致),和輸入流完成部署
                .deploy();// 完成部署
        System.out.println("部署ID:" + deployment.getId());//
        System.out.println("部署名稱:" + deployment.getName());//
    }

說明:
輸入流載入資原始檔的3種方式
這裡寫圖片描述
這裡寫圖片描述

二、啟動流程例項

/** 啟動流程例項 */
    @Test
    public void startProcessInstance() {
        // 流程定義的key
        String processDefinitionKey = "processVariables";
        ProcessInstance pi = processEngine.getRuntimeService()// 與正在執行的流程例項和執行物件相關的Service
                .startProcessInstanceByKey(processDefinitionKey);// 使用流程定義的key啟動流程例項,key對應helloworld.bpmn檔案中id的屬性值,使用key值啟動,預設是按照最新版本的流程定義啟動
        System.out.println("流程例項ID:" + pi.getId());// 流程例項ID
        System.out.println("流程定義ID:" + pi.getProcessDefinitionId());// 流程定義ID
    }

三、設定流程變數

/** 設定流程變數 */
    @Test
    public void setVariables() {
        /** 與任務(正在執行) */
        TaskService taskService = processEngine.getTaskService();
        // 任務ID
        String taskId = "2104";
        /** 一:設定流程變數,使用基本資料型別 */
        // taskService.setVariableLocal(taskId, "請假天數", 5);//與任務ID繫結
        // taskService.setVariable(taskId, "請假日期", new Date());
        // taskService.setVariable(taskId, "請假原因", "回家探親,一起吃個飯");
        /** 二:設定流程變數,使用javabean型別 */
        /**
         * 當一個javabean(實現序列號)放置到流程變數中,要求javabean的屬性不能再發生變化 * 如果發生變化,再獲取的時候,丟擲異常
         * 
         * 解決方案:在Person物件中新增: private static final long serialVersionUID =
         * 6757393795687480331L; 同時實現Serializable
         */
        Person p = new Person();
        p.setId(20);
        p.setName("翠花");
        taskService.setVariable(taskId, "人員資訊(新增固定版本)", p);

        System.out.println("設定流程變數成功!");
    }

說明:

  1. 流程變數的作用域就是流程例項,所以只要設定就行了,不用管在哪個階段設定
  2. 基本型別設定流程變數,在taskService中使用任務ID,定義流程變數的名稱,設定流程變數的值。
  3. Javabean型別設定流程變數,需要這個javabean實現了Serializable介面
  4. 設定流程變數的時候,向act_ru_variable這個表新增資料

四、獲取流程變數

/** 獲取流程變數 */
    @Test
    public void getVariables() {
        /** 與任務(正在執行) */
        TaskService taskService = processEngine.getTaskService();
        // 任務ID
        String taskId = "2104";
        /** 一:獲取流程變數,使用基本資料型別 */
        // Integer days = (Integer) taskService.getVariable(taskId, "請假天數");
        // Date date = (Date) taskService.getVariable(taskId, "請假日期");
        // String resean = (String) taskService.getVariable(taskId, "請假原因");
        // System.out.println("請假天數:"+days);
        // System.out.println("請假日期:"+date);
        // System.out.println("請假原因:"+resean);
        /** 二:獲取流程變數,使用javabean型別 */
        Person p = (Person) taskService.getVariable(taskId, "人員資訊(新增固定版本)");
        System.out.println(p.getId() + "        " + p.getName());
    }

說明:

  1. 流程變數的獲取針對流程例項(即1個流程),每個流程例項獲取的流程變數時不同的
  2. 使用基本型別獲取流程變數,在taskService中使用任務ID,流程變數的名稱,獲取流程變數的值。
  3. Javabean型別設定獲取流程變數,除了需要這個javabean實現了Serializable介面外,還要求流程變數物件的屬性不能發生變化,否則丟擲異常。解決方案,固定序列化ID

五、模擬流程變數的設定和獲取的場景

/** 模擬設定和獲取流程變數的場景 */
    public void setAndGetVariables() {
        /** 與流程例項,執行物件(正在執行) */
        RuntimeService runtimeService = processEngine.getRuntimeService();
        /** 與任務(正在執行) */
        TaskService taskService = processEngine.getTaskService();

        /** 設定流程變數 */
        // runtimeService.setVariable(executionId, variableName,
        // value)//表示使用執行物件ID,和流程變數的名稱,設定流程變數的值(一次只能設定一個值)
        // runtimeService.setVariables(executionId,
        // variables)//表示使用執行物件ID,和Map集合設定流程變數,map集合的key就是流程變數的名稱,map集合的value就是流程變數的值(一次設定多個值)

        // taskService.setVariable(taskId, variableName,
        // value)//表示使用任務ID,和流程變數的名稱,設定流程變數的值(一次只能設定一個值)
        // taskService.setVariables(taskId,
        // variables)//表示使用任務ID,和Map集合設定流程變數,map集合的key就是流程變數的名稱,map集合的value就是流程變數的值(一次設定多個值)

        // runtimeService.startProcessInstanceByKey(processDefinitionKey,
        // variables);//啟動流程例項的同時,可以設定流程變數,用Map集合
        // taskService.complete(taskId, variables)//完成任務的同時,設定流程變數,用Map集合

        /** 獲取流程變數 */
        // runtimeService.getVariable(executionId,
        // variableName);//使用執行物件ID和流程變數的名稱,獲取流程變數的值
        // runtimeService.getVariables(executionId);//使用執行物件ID,獲取所有的流程變數,將流程變數放置到Map集合中,map集合的key就是流程變數的名稱,map集合的value就是流程變數的值
        // runtimeService.getVariables(executionId,
        // variableNames);//使用執行物件ID,獲取流程變數的值,通過設定流程變數的名稱存放到集合中,獲取指定流程變數名稱的流程變數的值,值存放到Map集合中

        // taskService.getVariable(taskId,
        // variableName);//使用任務ID和流程變數的名稱,獲取流程變數的值
        // taskService.getVariables(taskId);//使用任務ID,獲取所有的流程變數,將流程變數放置到Map集合中,map集合的key就是流程變數的名稱,map集合的value就是流程變數的值
        // taskService.getVariables(taskId,
        // variableNames);//使用任務ID,獲取流程變數的值,通過設定流程變數的名稱存放到集合中,獲取指定流程變數名稱的流程變數的值,值存放到Map集合中

    }

說明:

  1. RuntimeService物件可以設定流程變數和獲取流程變數
  2. TaskService物件可以設定流程變數和獲取流程變數
  3. 流程例項啟動的時候可以設定流程變數
  4. 任務辦理完成的時候可以設定流程變數
  5. 流程變數可以通過名稱/值的形式設定單個流程變數
  6. 流程變數可以通過Map集合,同時設定多個流程變數
    Map集合的key表示流程變數的名稱
    Map集合的value表示流程變數的值

六、查詢歷史的流程變數

/** 查詢流程變數的歷史表 */
    @Test
    public void findHistoryProcessVariables() {
        List<HistoricVariableInstance> list = processEngine.getHistoryService()//
                .createHistoricVariableInstanceQuery()// 建立一個歷史的流程變數查詢物件
                .variableName("請假天數").list();
        if (list != null && list.size() > 0) {
            for (HistoricVariableInstance hvi : list) {
                System.out.println(hvi.getId() + "   " + hvi.getProcessInstanceId() + "   " + hvi.getVariableName()
                        + "   " + hvi.getVariableTypeName() + "    " + hvi.getValue());
                System.out.println("###############################################");
            }
        }
    }

說明:
歷史的流程變數查詢,指定流程變數的名稱,查詢act_hi_varinst表(也可以針對,流程例項ID,執行物件ID,任務ID查詢)

七、流程變數的支援的型別

Type name Description
string Value is threaded as a java.lang.String. Raw JSON-text value is used when writing a variable.
integer Value is threaded as a java.lang.Integer. When writing, JSON number value is used as base for conversion, falls back to JSON text.
short Value is threaded as a java.lang.Short. When writing, JSON number value is used as base for conversion, falls back to JSON text.
long Value is threaded as a java.lang.Long. When writing, JSON number value is used as base for conversion, falls back to JSON text.
double Value is threaded as a java.lang.Double. When writing, JSON number value is used as base for conversion, falls back to JSON text.
boolean Value is threaded as a java.lang.Boolean. When writing, JSON boolean value is used for conversion.
date Value is treated as a java.util.Date. When writing, the JSON text will be converted using ISO-8601 date format.
binary Binary variable, treated as an array of bytes. The value attribute is null, the valueUrl contains an URL pointing to the raw binary stream.
serializable Serialized representation of a Serializable Java-object. As with the binary type, the value attribute is null, the valueUrl contains an URL pointing to the raw binary stream. All serializable variables (which are not of any of the above types) will be exposed as a variable of this type.

從圖中可以看出包括了大部分封裝型別和Date、String和實現了Serializable介面的類的型別。

八、總結

  1. 流程變數
    在流程執行或者任務執行的過程中,用於設定和獲取變數,使用流程變數在流程傳遞的過程中傳遞業務引數。
    對應的表:
    act_ru_variable:正在執行的流程變數表
    act_hi_varinst:流程變數歷史表
  2. 擴充套件知識:setVariable和setVariableLocal的區別
    setVariable:設定流程變數的時候,流程變數名稱相同的時候,後一次的值替換前一次的值,而且可以看到TASK_ID的欄位不會存放任務ID的值
    setVariableLocal:
    1:設定流程變數的時候,針對當前活動的節點設定流程變數,如果一個流程中存在2個活動節點,對每個活動節點都設定流程變數,即使流程變數的名稱相同,後一次的版本的值也不會替換前一次版本的值,它會使用不同的任務ID作為標識,存放2個流程變數值,而且可以看到TASK_ID的欄位會存放任務ID的值
    例如act_hi_varinst 表的資料:不同的任務節點,即使流程變數名稱相同,存放的值也是不同的。
    如圖:
    這裡寫圖片描述
    2:還有,使用setVariableLocal說明流程變數繫結了當前的任務,當流程繼續執行時,下個任務獲取不到這個流程變數(因為正在執行的流程變數中沒有這個資料),所有查詢正在執行的任務時不能查詢到我們需要的資料,此時需要查詢歷史的流程變數。

    原始碼demo下載:http://download.csdn.net/detail/xunzaosiyecao/9622475

本文部分內容整理自itcast講義,在此表示感謝。
作者:jiankunking 出處:http://blog.csdn.net/jiankunking

相關文章