Flowable 基本入門

flowable.7z官方版下載丨最新版下載丨綠色版下載丨APP下載-123云盤

1、Flowable介紹

????????Flowable是BPMN的一個基于java的軟件實現,不過Flowable不僅僅包括BPMN,還有DMN決策表和CMMN Case管理引擎,并且有自己的用戶管理、微服務API等一系列功能,是一個服務平臺。

2、Flowable 基礎

官方手冊:Flowable BPMN 用戶手冊 (v 6.3.0)

1.創建ProcessEngine

????????創建一個基本的maven工程,可以是Eclipse也可以是其他IDEA。然后添加兩個依賴

  • Flowable流程引擎。使我們可以創建一個ProcessEngine流程引擎對象,并訪問Flowable API。
  • 一個是MySQL的數據庫驅動

pom.xml文件中添加下列行:

<dependency><groupId>org.flowable</groupId><artifactId>flowable-engine</artifactId><version>6.3.0</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version>
</dependency>

????????然后創建一個普通的Java類,添加對應的main方法,首先要做的是初始化ProcessEngine流程引擎實例。這是一個線程安全的對象,因此通常只需要在一個應用中初始化一次。 ProcessEngineProcessEngineConfiguration實例創建。該實例可以配置與調整流程引擎的設置。 通常使用一個配置XML文件創建ProcessEngineConfiguration,但是(像在這里做的一樣)也可以編程方式創建它。 ProcessEngineConfiguration所需的最小配置,是數據庫JDBC連接:

public static void main(String[] args) {ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);ProcessEngine processEngine = cfg.buildProcessEngine();
}

????????注意在mysql8.0中執行可能出現如下的錯誤:

????????出現這種情況只需要在mysql的連接字符串中添加上nullCatalogMeansCurrent=true,設置為只查當前連接的schema庫即可。

    public static void main(String[] args) {ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn1?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);ProcessEngine processEngine = cfg.buildProcessEngine();}

????????然后應用運行沒有問題,但也沒有在控制臺提供有用的信息,只有一條消息提示日志沒有正確配置。Flowable使用SLF4J作為內部日志框架。在這個例子中,我們使用log4j作為SLF4J的實現。因此在pom.xml文件中添加下列依賴:

<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version>
</dependency>

????????Log4j需要一個配置文件。在src/main/resources文件夾下添加log4j.properties文件,并寫入下列內容:

log4j.rootLogger=DEBUG, CAlog4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

????????重新運行應用。應該可以看到關于引擎啟動與創建數據庫表結構的提示日志:

????????同時可以看到創建了相關的表結構在數據庫中:

????????這樣就得到了一個啟動可用的流程引擎。接下來為它提供一個流程!

2.部署流程定義

??接下來我們構建一個非常簡單的請假流程,Flowable引擎需要流程定義為BPMN 2.0格式,這是一個業界廣泛接受的XML標準。 在Flowable術語中,我們將其稱為一個流程定義(process definition)。一個流程定義可以啟動多個流程實例(process instance)流程定義可以看做是重復執行流程的藍圖。 在這個例子中,流程定義定義了請假的各個步驟,而一個流程實例對應某個雇員提出的一個請假申請。

??BPMN 2.0存儲為XML,并包含可視化的部分:使用標準方式定義了每個步驟類型(人工任務,自動服務調用,等等)如何呈現,以及如何互相連接。這樣BPMN 2.0標準使技術人員與業務人員能用雙方都能理解的方式交流業務流程。

??我們要使用的流程定義為:

流程定義說明:

  • 我們假定啟動流程需要提供一些信息,例如雇員名字、請假時長以及說明。當然,這些可以單獨建模為流程中的第一步。 但是如果將它們作為流程的“輸入信息”,就能保證只有在實際請求時才會建立一個流程實例。否則(將提交作為流程的第一步),用戶可能在提交之前改變主意并取消,但流程實例已經創建了。 在某些場景中,就可能影響重要的指標(例如啟動了多少申請,但還未完成),取決于業務目標。

  • 左側的圓圈叫做啟動事件(start event)。這是一個流程實例的起點。

  • 第一個矩形是一個用戶任務(user task)。這是流程中用戶操作的步驟。在這個例子中,經理需要批準或駁回申請

  • 取決于經理的決定,排他網關(exclusive gateway) (帶叉的菱形)會將流程實例路由至批準或駁回路徑

  • 如果批準,則需要將申請注冊至某個外部系統,并跟著另一個用戶任務,將經理的決定通知給申請人。當然也可以改為發送郵件。

  • 如果駁回,則為雇員發送一封郵件通知他。

????????一般來說,這樣的流程定義使用可視化建模工具建立,如Flowable Designer(Eclipse)或Flowable Web Modeler(Web應用)。但在這里我們直接撰寫XML,以熟悉BPMN 2.0及其概念。

??與上面展示的流程圖對應的BPMN 2.0 XML在下面顯示。請注意這只包含了“流程部分”。如果使用圖形化建模工具,實際的XML文件還將包含“可視化部分”,用于描述圖形信息,如流程定義中各個元素的坐標(所有的圖形化信息包含在XML的BPMNDiagram標簽中,作為definitions標簽的子元素)。

??將下面的XML保存在src/main/resources文件夾下名為holiday-request.bpmn20.xml的文件中。

<?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: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"xmlns:flowable="http://flowable.org/bpmn"typeLanguage="http://www.w3.org/2001/XMLSchema"expressionLanguage="http://www.w3.org/1999/XPath"targetNamespace="http://www.flowable.org/processdef"><process id="holidayRequest" name="Holiday Request" isExecutable="true"><startEvent id="startEvent"/><sequenceFlow sourceRef="startEvent" targetRef="approveTask"/><userTask id="approveTask" name="Approve or reject request"/><sequenceFlow sourceRef="approveTask" targetRef="decision"/><exclusiveGateway id="decision"/><sequenceFlow sourceRef="decision" targetRef="externalSystemCall"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${approved}]]></conditionExpression></sequenceFlow><sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${!approved}]]></conditionExpression></sequenceFlow><serviceTask id="externalSystemCall" name="Enter holidays in external system"flowable:class="org.flowable.CallExternalSystemDelegate"/><sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/><userTask id="holidayApprovedTask" name="Holiday approved"/><sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/><serviceTask id="sendRejectionMail" name="Send out rejection email"flowable:class="org.flowable.SendRejectionMail"/><sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/><endEvent id="approveEnd"/><endEvent id="rejectEnd"/></process></definitions>

????????現在我們已經有了流程BPMN 2.0 XML文件,下來需要將它部署(deploy)*到引擎中。部署*一個流程定義意味著:

  • 流程引擎會將XML文件存儲在數據庫中,這樣可以在需要的時候獲取它

  • 流程定義轉換為內部的、可執行的對象模型,這樣使用它就可以啟動流程實例

????????將流程定義部署至Flowable引擎,需要使用RepositoryService,其可以從ProcessEngine對象獲取。使用RepositoryService,可以通過XML文件的路徑創建一個新的部署(Deployment),并調用deploy()方法實際執行:

    /*** 部署流程*/@Testpublic void testDeploy(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();// 部署流程 獲取RepositoryService對象RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deployment = repositoryService.createDeployment()// 創建Deployment對象.addClasspathResource("holiday-request.bpmn20.xml") // 添加流程部署文件.name("請求流程") // 設置部署流程的名稱.deploy(); // 執行部署操作System.out.println("deployment.getId() = " + deployment.getId());System.out.println("deployment.getName() = " + deployment.getName());}

????????然后執行該方法日志操作成功:

????????在后臺表結構也可以看到相關的信息,act_re_deployment: 流程定義部署表,每部署一次就增加一條記錄。

????????act_re_procdef :流程定義表,部署每個新的流程定義都會在這張表中增加一條記錄

????????act_ge_bytearray :流程資源表,流程部署的 bpmn文件和png圖片會保存在該表中

????????我們現在可以通過API查詢驗證流程定義已經部署在引擎中(并學習一些API)。通過RepositoryService創建的ProcessDefinitionQuery對象實現。

/*** 查看流程定義*/@Testpublic void testDeployQuery(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();// 部署流程 獲取RepositoryService對象RepositoryService repositoryService = processEngine.getRepositoryService();// 獲取流程定義對象ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId("2501").singleResult();System.out.println("processDefinition.getId() = " + processDefinition.getId());System.out.println("processDefinition.getName() = " + processDefinition.getName());System.out.println("processDefinition.getDeploymentId() = " + processDefinition.getDeploymentId());System.out.println("processDefinition.getDescription() = " + processDefinition.getDescription());}

輸出結果為:

processDefinition.getId() = holidayRequest:2:2503
processDefinition.getName() = Holiday Request
processDefinition.getDeploymentId() = 2501
processDefinition.getDescription() = null

3.啟動流程實例

??現在已經在流程引擎中部署了流程定義,因此可以使用這個流程定義作為“模板”啟動流程實例

????????要啟動流程實例,需要提供一些初始化流程變量。一般來說,可以通過呈現給用戶的表單,或者在流程由其他系統自動觸發時通過REST API,來獲取這些變量。在這個例子里,我們簡化直接在代碼中定義了,我們使用RuntimeService啟動一個流程實例

    /*** 啟動流程實例*/@Testpublic void testRunProcess(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();// 啟動流程實例通過 RuntimeService 對象RuntimeService runtimeService = processEngine.getRuntimeService();// 構建流程變量Map<String,Object> variables = new HashMap<>();variables.put("employee","張三") ;// 誰申請請假variables.put("nrOfHolidays",3); // 請幾天假variables.put("description","工作累了,想出去玩玩"); // 請假的原因// 啟動流程實例,第一個參數是流程定義的idProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables);// 啟動流程實例// 輸出相關的流程實例信息System.out.println("流程定義的ID:" + processInstance.getProcessDefinitionId());System.out.println("流程實例的ID:" + processInstance.getId());System.out.println("當前活動的ID:" + processInstance.getActivityId());}

啟動成功,輸出結果如下:

流程定義的ID:holidayRequest:2:2503
流程實例的ID:5001
當前活動的ID:null

對應的流程實例ID為:5001

啟動流程實例涉及到的表結構:

  • act_hi_actinst 流程實例執行歷史

  • act_hi_identitylink 流程的參與用戶的歷史信息

  • act_hi_procinst 流程實例歷史信息

  • act_hi_taskinst 流程任務歷史信息

  • act_ru_execution 流程執行信息

  • act_ru_identitylink 流程的參與用戶信息

  • act_ru_task 任務信息

4.查看任務

??上面員工發起了一個請假流程,接下來就會流轉到總經理這兒來處理,之前我們沒有指定經理這的處理人,我們可以加一個。

然后我們來查看下lisi的任務。

    /*** 查看任務*/@Testpublic void testQueryTask(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery().processDefinitionKey("holidayRequestNew").taskAssignee("lisi").list();for (Task task : list) {System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());System.out.println("task.getId() = " + task.getId());System.out.println("task.getAssignee() = " + task.getAssignee());System.out.println("task.getName() = " + task.getName());}}

輸出結果為:

task.getProcessDefinitionId() = holidayRequestNew:1:10003
task.getId() = 12508
task.getAssignee() = lisi
task.getName() = Approve or reject request

5.完成任務

??現在李四這個角色可以來完成當前的任務了

????????在此處我們直接解決掉這個請假,然后會走發送拒絕郵件的流程,這塊我們需要用到JavaDelegate來觸發。

public class SendRejectionMail implements JavaDelegate {/*** 觸發發送郵件的操作* @param delegateExecution*/@Overridepublic void execute(DelegateExecution delegateExecution) {System.out.println("請假被拒絕,,,安心工作吧");}
}

然后來完成任務

    /*** 完成任務*/@Testpublic void testCompleteTask(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionKey("holidayRequestNew").taskAssignee("lisi").singleResult();// 添加流程變量Map<String,Object> variables = new HashMap<>();variables.put("approved",false); // 拒絕請假// 完成任務taskService.complete(task.getId(),variables);}

????????然后可以看到JavaDelegate觸發了:

6.流程的刪除

??有些流程已經沒有用了,我們需要刪除掉,其實也非常簡單。

    /*** 刪除流程*/@Testpublic void testDeleteProcess(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();// 刪除流程定義,如果該流程定義已經有了流程實例啟動則刪除時報錯// repositoryService.deleteDeployment("1");// 設置為TRUE 級聯刪除流程定義,及時流程有實例啟動,也可以刪除,設置為false 非級聯刪除操作。repositoryService.deleteDeployment("2501",true);}

7.查看歷史信息

??選擇使用Flowable這樣的流程引擎的原因之一,是它可以自動存儲所有流程實例的審計數據歷史數據。這些數據可以用于創建報告,深入展現組織運行的情況,瓶頸在哪里,等等。

??例如,如果希望顯示流程實例已經執行的時間,就可以從ProcessEngine獲取HistoryService,并創建歷史活動(historical activities)的查詢。在下面的代碼片段中,可以看到我們添加了一些額外的過濾條件:

  • 只選擇一個特定流程實例的活動

  • 只選擇已完成的活動

??結果按照結束時間排序,代表其執行順序。

/*** 查看歷史*/@Testpublic void testQueryHistory(){// 配置數據庫相關信息 獲取 ProcessEngineConfigurationProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);// 獲取流程引擎對象ProcessEngine processEngine = cfg.buildProcessEngine();HistoryService historyService = processEngine.getHistoryService();List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processDefinitionId("holidayRequestNew:1:10003").finished().orderByHistoricActivityInstanceEndTime().asc().list();for (HistoricActivityInstance historicActivityInstance : list) {System.out.println(historicActivityInstance.getActivityId() + " took "+ historicActivityInstance.getDurationInMillis() + " milliseconds");}}

輸出結果:

startEvent took 1 milliseconds
approveTask took 837735 milliseconds
decision took 13 milliseconds
sendRejectionMail took 2 milliseconds
rejectEnd took 1 milliseconds

3、Flowable流程設計器

1.Eclipse Designer

??Flowable提供了名為Flowable Eclipse Designer的Eclipse插件,可以用于圖形化地建模、測試與部署BPMN 2.0流程。

1.1 下載安裝Eclipse

??去Eclipse官網下載即可:Eclipse Packaging Project (EPP) Releases | Eclipse Packages 注意2020-09后的版本不再支持jdk8

????????解壓縮就可以了,然后進入解壓縮的目錄:

直接啟動即可:

1.2 安裝Flowable插件

??然后我們再安裝下Flowable的插件,選擇Help → Install New Software。在下圖面板中,點擊Add按鈕,并填寫下列字段

  • Name: Flowable BPMN 2.0 designer

  • Location: http://www.flowable.org/designer/update/

????????這種在線更新的方式已經被官網移除了,操作不了。

????????這時我們就只能通過離線安裝的方式來實現了,下載對應的離線文件。

然后繼續:選擇Help → Install New Software

1.3 創建項目

??然后我們就可以創建一個Flowable Project了.

????????然后我們可以在src/mian/resources/ 的目錄下創建對應的流程圖了。

????????看到如下的界面說明插件安裝成功了。

1.4 創建流程圖

????????使用滑板來繪制流程,通過從右側把圖標拖拽到左側的面板,最終的效果

????????指定流程的主鍵:

????????指定任務的負責人,在Properties視圖中指定每個任務節點的負責人。

創建請假單:zhangsan

審批請假單:lisi

????????當我們設置完成后保存文件,會同時生成png圖片:

注意:生成圖片需要如下配置。

1.5 部署流程

??首先在Eclipse中生成bar文件,選中項目然后鼠標右擊。

????????然后會發現在項目的根目錄下多了一個deployment文件夾,里面多了一個MyProcess.bar文件。

????????然后我們就可以把這個bar文件拷貝到IDEA中,繼續部署的流程。

????????而部署的代碼和前面沒啥區別。

    @Testpublic void testDeploy(){// 1.獲取 ProcessEngine 對象ProcessEngine processEngine = configuration.buildProcessEngine();// 2.獲取RepositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();InputStream in = this.getClass().getClassLoader().getResourceAsStream("MyHoliday.bar");ZipInputStream zipInputStream = new ZipInputStream(in);// 3.完成流程的部署操作 ZIP 或者 Bar文件Deployment deploy = repositoryService.createDeployment()// .addClasspathResource("MyHoliday.bar")// 關聯要部署的流程文件.addZipInputStream(zipInputStream).name("XXX公司請求流程").deploy() ;// 部署流程System.out.println("deploy.getId() = " + deploy.getId());System.out.println("deploy.getName() = " + deploy.getName());}

執行后查看表結構,相關的信息就進去了

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;public class Test02 {ProcessEngineConfiguration configuration = null;@Beforepublic void before(){// 獲取  ProcessEngineConfiguration 對象configuration = new StandaloneProcessEngineConfiguration();// 配置 相關的數據庫的連接信息configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");configuration.setJdbcUsername("root");configuration.setJdbcPassword("123456");configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");// 如果數據庫中的表結構不存在就新建configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);}/*** 部署流程**/@Testpublic void testDeploy(){// 1.獲取 ProcessEngine 對象ProcessEngine processEngine = configuration.buildProcessEngine();// 2.獲取RepositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();InputStream in = this.getClass().getClassLoader().getResourceAsStream("MyHoliday.bar");ZipInputStream zipInputStream = new ZipInputStream(in);// 3.完成流程的部署操作 ZIP 或者 Bar文件Deployment deploy = repositoryService.createDeployment()// .addClasspathResource("MyHoliday.bar")// 關聯要部署的流程文件.addZipInputStream(zipInputStream).name("XXX公司請求流程").deploy() ;// 部署流程System.out.println("deploy.getId() = " + deploy.getId());System.out.println("deploy.getName() = " + deploy.getName());}/*** 啟動流程實例*/@Testpublic void testRunProcess(){ProcessEngine processEngine = configuration.buildProcessEngine();// 我們需要通過RuntimeService來啟動流程實例RuntimeService runtimeService = processEngine.getRuntimeService();// 啟動流程實例ProcessInstance holidayRequest = runtimeService.startProcessInstanceById("myProcess:1:25004");System.out.println("holidayRequest.getProcessDefinitionId() = " + holidayRequest.getProcessDefinitionId());System.out.println("holidayRequest.getActivityId() = " + holidayRequest.getActivityId());System.out.println("holidayRequest.getId() = " + holidayRequest.getId());}/*** 測試任務查詢*/@Testpublic void testQueryTask(){ProcessEngine processEngine = configuration.buildProcessEngine();TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery().processDefinitionKey("myProcess") // 指定查詢的流程編程.taskAssignee("zhangsan") // 查詢這個任務的處理人.list();for (Task task : list) {System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());System.out.println("task.getName() = " + task.getName());System.out.println("task.getAssignee() = " + task.getAssignee());System.out.println("task.getDescription() = " + task.getDescription());System.out.println("task.getId() = " + task.getId());}}/*** 完成當前任務*/@Testpublic void testCompleteTask(){ProcessEngine processEngine = configuration.buildProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionKey("myProcess").taskAssignee("lisi").singleResult();// 創建流程變量if(task != null){// 完成任務taskService.complete(task.getId());}}/*** 獲取流程任務的歷史數據*/@Testpublic void testHistory(){ProcessEngine processEngine = configuration.buildProcessEngine();HistoryService historyService = processEngine.getHistoryService();List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processDefinitionId("myProcess:1:25004").finished() // 查詢的歷史記錄的狀態是已經完成.orderByHistoricActivityInstanceEndTime().asc() // 指定排序的字段和順序.list();for (HistoricActivityInstance history : list) {System.out.println(history.getActivityName()+":"+history.getAssignee()+"--"+history.getActivityId()+":" + history.getDurationInMillis()+"毫秒");}}
}

2.Flowable UI應用

??Flowable提供了幾個web應用,用于演示及介紹Flowable項目提供的功能:

  • Flowable IDM: 身份管理應用。為所有Flowable UI應用提供單點登錄認證功能,并且為擁有IDM管理員權限的用戶提供了管理用戶、組與權限的功能。

  • Flowable Modeler: 讓具有建模權限的用戶可以創建流程模型、表單、選擇表與應用定義。

  • Flowable Task: 運行時任務應用。提供了啟動流程實例、編輯任務表單、完成任務,以及查詢流程實例與任務的功能。

  • Flowable Admin: 管理應用。讓具有管理員權限的用戶可以查詢BPMN、DMN、Form及Content引擎,并提供了許多選項用于修改流程實例、任務、作業等。管理應用通過REST API連接至引擎,并與Flowable Task應用及Flowable REST應用一同部署。

??所有其他的應用都需要Flowable IDM提供認證。每個應用的WAR文件可以部署在相同的servlet容器(如Apache Tomcat)中,也可以部署在不同的容器中。由于每個應用使用相同的cookie進行認證,因此應用需要運行在相同的域名下。

2.1 安裝部署

????????下載Tomcat:Apache Download Mirrors 官網下載后解壓縮到非中文目錄即可,然后是下載FlowableUI的文件,在Flowable6.6之后把FlowableUI中提供的四個功能合并到了一起。

????????然后把解壓縮后的兩個war包拷貝到Tomcat的解壓縮的webapps目錄下。

2.2 啟動服務

??啟動Tomcat服務,執行startup.bat文件

????????如果啟動中出現亂碼修改Tomcat的conf目錄下的 logging.properties 文件中的編碼。

????????如果一閃而過則檢查jdk的環境變量配置。啟動成功后,在瀏覽器中訪問 http://localhost:8080/flowable-ui, 默認的賬號密碼是 admin/test

2.3 用戶管理

??我們先在 身份管理應用程序 中創建用戶并授權。

2.4 繪制流程

????????創建新的流程:

創建流程,分配處理人:

繼續完成流程圖的創建:

2.5 部署流程

??繪制好的流程圖,我們只需要一鍵導出即可

????????下載下來后拷貝到項目的resource目錄下即可:

2.6 FlowableUI 演示

2.6.1 部署流程

??在FlowableUI中提供了演示程序:

????????創建一個新的應用程序,并指定相關的信息:

????????創建應用后需要指定對應的流程圖:

2.6.2 啟動流程

??發布了應用程序后我們就可以來啟動流程了

????????也就是可以看到當前是user1來處理,user1登錄后可以看到要處理的流程,user2登錄是看不到的。

????????點擊完成后流程就向下一步流轉了。

????????這時再通過user2登錄,就可以看到對應的代辦的信息。

4、Flowable基礎表結構

1.表結構講解

??工作流程的相關操作都是操作存儲在對應的表結構中,為了能更好的弄清楚Flowable的實現原理和細節,我們有必要先弄清楚Flowable的相關表結構及其作用。在Flowable中的表結構在初始化的時候會創建五類表結構,具體如下:

  • ACT_RE :'RE'表示 repository。 這個前綴的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。

  • ACT_RU:'RU'表示 runtime。 這些運行時的表,包含流程實例,任務,變量,異步任務,等運行中的數據。 Flowable只在流程實例執行過程中保存這些數據, 在流程結束時就會刪除這些記錄。 這樣運行時表可以一直很小速度很快。

  • ACT_HI:'HI'表示 history。 這些表包含歷史數據,比如歷史流程實例, 變量,任務等等。

  • ACT_GE: GE 表示 general。 通用數據, 用于不同場景下

  • ACT_ID: ’ID’表示identity(組織機構)。這些表包含標識的信息,如用戶,用戶組,等等。

具體的表結構的含義:

表分類表名解釋
一般數據
[ACT_GE_BYTEARRAY]通用的流程定義和流程資源
[ACT_GE_PROPERTY]系統相關屬性
流程歷史記錄
[ACT_HI_ACTINST]歷史的流程實例
[ACT_HI_ATTACHMENT]歷史的流程附件
[ACT_HI_COMMENT]歷史的說明性信息
[ACT_HI_DETAIL]歷史的流程運行中的細節信息
[ACT_HI_IDENTITYLINK]歷史的流程運行過程中用戶關系
[ACT_HI_PROCINST]歷史的流程實例
[ACT_HI_TASKINST]歷史的任務實例
[ACT_HI_VARINST]歷史的流程運行中的變量信息
流程定義表
[ACT_RE_DEPLOYMENT]部署單元信息
[ACT_RE_MODEL]模型信息
[ACT_RE_PROCDEF]已部署的流程定義
運行實例表
[ACT_RU_EVENT_SUBSCR]運行時事件
[ACT_RU_EXECUTION]運行時流程執行實例
[ACT_RU_IDENTITYLINK]運行時用戶關系信息,存儲任務節點與參與者的相關信息
[ACT_RU_JOB]運行時作業
[ACT_RU_TASK]運行時任務
[ACT_RU_VARIABLE]運行時變量表
用戶用戶組表
[ACT_ID_BYTEARRAY]二進制數據表
[ACT_ID_GROUP]用戶組信息表
[ACT_ID_INFO]用戶信息詳情表
[ACT_ID_MEMBERSHIP]人與組關系表
[ACT_ID_PRIV]權限表
[ACT_ID_PRIV_MAPPING]用戶或組權限關系表
[ACT_ID_PROPERTY]屬性表
[ACT_ID_TOKEN]記錄用戶的token信息
[ACT_ID_USER]用戶表

2.ProcessEngine講解

2.1 硬編碼的方式

??我們前面講解案例的時候是通過ProcessEngineConfiguration這個配置類來加載的。

// 配置數據庫相關信息 獲取 ProcessEngineConfiguration
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration().setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn2?serverTimezone=UTC&nullCatalogMeansCurrent=true").setJdbcUsername("root").setJdbcPassword("123456").setJdbcDriver("com.mysql.cj.jdbc.Driver").setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 獲取流程引擎對象
ProcessEngine processEngine = cfg.buildProcessEngine();

2.2 配置文件

??除了上面的硬編碼的方式外,我們還可以在resources目錄下創建一個flowable.cfg.xml文件,注意這個名稱是固定的哦。內容如下:

<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.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration"><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/flow1?allowMultiQueries=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false&amp;serverTimezone=UTC&amp;nullCatalogMeansCurrent=true" /><property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" /><property name="jdbcUsername" value="root" /><property name="jdbcPassword" value="123456" /><property name="databaseSchemaUpdate" value="true" /><property name="asyncExecutorActivate" value="false" /></bean>
</beans>

????????在上面的配置文件中配置相關的信息。我們在Java代碼中就可以簡化為:

    @Testpublic void test01(){// 獲取流程引擎對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();System.out.println("processEngine = " + processEngine);}

????????可以看下getDefaultProcessEngine的源碼,在里面最終還是執行了和硬編碼一樣的代碼:

    public static ProcessEngine getProcessEngine(String processEngineName) {if (!isInitialized()) {init(); // 完成初始化操作}return processEngines.get(processEngineName);}public static synchronized void init() {if (!isInitialized()) {if (processEngines == null) {// Create new map to store process-engines if current map is nullprocessEngines = new HashMap<>();}ClassLoader classLoader = ReflectUtil.getClassLoader();Enumeration<URL> resources = null;try {resources = classLoader.getResources("flowable.cfg.xml"); // 加載flowable.cfg.xml配置文件} catch (IOException e) {throw new FlowableIllegalArgumentException("problem retrieving flowable.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), e);}// Remove duplicated configuration URL's using set. Some// classloaders may return identical URL's twice, causing duplicate// startupsSet<URL> configUrls = new HashSet<>();while (resources.hasMoreElements()) {configUrls.add(resources.nextElement());}for (Iterator<URL> iterator = configUrls.iterator(); iterator.hasNext();) {URL resource = iterator.next();LOGGER.info("Initializing process engine using configuration '{}'", resource.toString());initProcessEngineFromResource(resource); // 初始化ProcessEngine}try {resources = classLoader.getResources("flowable-context.xml"); // 在整合Spring的情況下加載該文件} catch (IOException e) {throw new FlowableIllegalArgumentException("problem retrieving flowable-context.xml resources on the classpath: " + System.getProperty("java.class.path"), e);}while (resources.hasMoreElements()) {URL resource = resources.nextElement();LOGGER.info("Initializing process engine using Spring configuration '{}'", resource.toString());initProcessEngineFromSpringResource(resource); // 從Spring的資源文件中完成ProcessEngine的初始化}setInitialized(true);} else {LOGGER.info("Process engines already initialized");}}

????????在源碼中提供了單獨使用好整合Spring的配置加載方式。再進入到initProcessEngineFromResource(resource)方法中:

????????而且我們也可以看到ProcessEngine最終的實現是 ProcessEngineImpl對象。

2.3 自定義配置文件

??最后我們如果要加載自定義名稱的配置文件可以通過ProcessEngineConfiguration中的對應構造方法來實現。

    @Testpublic void test2() throws Exception{ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("flowable.cfg.xml");ProcessEngine processEngine = configuration.buildProcessEngine();System.out.println("processEngine = " + processEngine);}

3. Servcie服務接口

????????Service是工作流引擎提供用于進行工作流部署、執行、管理的服務接口,我們使用這些接口可以就是操作服務對應的數據表。

3.1 Service創建方式

????????通過ProcessEngine創建Service,方式如下:

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
// ...

3.2 Service總覽

service名稱service作用
RepositoryServiceFlowable的資源管理類
RuntimeServiceFlowable的流程運行管理類
TaskServiceFlowable的任務管理類
HistoryServiceFlowable的歷史管理類
ManagerServiceFlowable的引擎管理類

簡單介紹:

RepositoryService

????????是activiti的資源管理類,提供了管理和控制流程發布包和流程定義的操作。使用工作流建模工具設計的業務流程圖需要使用此service將流程定義文件的內容部署到計算機。

????????除了部署流程定義以外還可以:查詢引擎中的發布包和流程定義。

????????暫停或激活發布包,對應全部和特定流程定義。 暫停意味著它們不能再執行任何操作了,激活是對應的反向操作。獲得多種資源,像是包含在發布包里的文件, 或引擎自動生成的流程圖。獲得流程定義的pojo版本, 可以用來通過java解析流程,而不必通過xml。

RuntimeService

????????Activiti的流程運行管理類。可以從這個服務類中獲取很多關于流程執行相關的信息

TaskService

????????Activiti的任務管理類。可以從這個類中獲取任務的信息。

HistoryService

????????Flowable的歷史管理類,可以查詢歷史信息,執行流程時,引擎會保存很多數據(根據配置),比如流程實例啟動時間,任務的參與者, 完成任務的時間,每個流程實例的執行路徑,等等。 這個服務主要通過查詢功能來獲得這些數據。

ManagementService

????????Activiti的引擎管理類,提供了對Flowable 流程引擎的管理和維護功能,這些功能不在工作流驅動的應用程序中使用,主要用于 Flowable 系統的日常維護。

4.圖標介紹

??BPMN 2.0是業務流程建模符號2.0的縮寫。它由Business Process Management Initiative這個非營利協會創建并不斷發展。作為一種標識,BPMN 2.0是使用一些符號來明確業務流程設計流程圖的一整套符號規范,它能增進業務建模時的溝通效率。目前BPMN2.0是最新的版本,它用于在BPM上下文中進行布局和可視化的溝通。接下來我們先來了解在流程設計中常見的 符號。

BPMN2.0的基本符合主要包含:

4.1 事件圖標

??在Flowable中的事件圖標啟動事件,邊界事件,中間事件和結束事件.

4.2 活動(任務)圖標

??活動是工作或任務的一個通用術語。一個活動可以是一個任務,還可以是一個當前流程的子處理流程; 其次,你還可以為活動指定不同的類型。常見活動如下:

4.3 結構圖標

??結構圖標可以看做是整個流程活動的結構,一個流程中可以包括子流程。常見的結構有:

4.4 網關圖標

??網關用來處理決策,有幾種常用網關需要了解:

5.流程部署詳解

5.1 部署實現

??我們先來看下流程部署的具體過程。代碼實現

/*** 部署流程*/@Testpublic void test3(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();Deployment deploy = repositoryService.createDeployment().addClasspathResource("holiday-request-new.bpmn20.xml").name("請假流程...").category("請假") // 分類.tenantId("dpb") // 租戶id.deploy();System.out.println("deploy.getId() = " + deploy.getId());System.out.println("deploy.getName() = " + deploy.getName());System.out.println("deploy.getCategory() = " + deploy.getCategory());}

5.2 部署涉及表結構

涉及到的三張表:

部署資源表:act_ge_bytearray

字段名稱備注
ID_主鍵
REV_版本號
NAME_名稱部署的文件名稱,如:holiday-request-new.bpmn20.xml、holiday-request-new.bpmn20.png
DEPLOYMENT_ID_部署ID
BYTES_字節(二進制數據)
GENERATED_是否系統生成0為用戶上傳, 1為系統自動生成, 比如系統會 自動根據xml生 成png

部署ID表:act_re_deployment

字段名稱備注
ID_主鍵
NAME_名稱
CATEGORY_分類
TENANT_ID_租戶ID
DEPLOY_TIME_部署時間
DERIVED_FROM_來源于
DERIVED_FROM_ROOT_來源于
ENGINE_VERSION_流程引擎的版本

流程表:act_re_procdef

字段名稱備注
ID_主鍵
REV_版本號
CATEGORY_分類流程定義的Namespace就是類別
NAME_名稱
KEY_標識
VERSION_版本
DEPLOYMENT_ID_部署ID
RESOURCE_NAME_資源名稱流程bpmn文件名稱
DGRM_RESOURCE_NAME_圖片資源名稱
DESCRIPTION_描述
HAS_START_FORM_KEY_擁有開始表單標識start節點是否存在formKey 0否 1是
HAS_GRAPHICAL_NOTATION_擁有圖形信息
SUSPENSION_STATE_掛起狀態暫停狀態 1激活 2暫停
TENANT_ID_租戶ID

注意:

????????業務流程定義數據表,此表和ACT_RE_DEPLOYMENT是多對一的關系。即,一個部署的bar包里可能包含多個流程定義文件,每個流程定義文件都會有一條記錄在ACT_REPROCDEF表內,每個流程定義的數據,都會對于ACT_GE_BYTEARRAY表內的一個資源文件和PNG圖片文件。和ACT_GE_BYTEARRAY的關聯是通過程序用ACT_GE_BYTEARRAY.NAME與ACT_RE_PROCDEF.NAME_完成的。

5.3 掛起和激活

??部署的流程默認的狀態為激活,如果我們暫時不想使用該定義的流程,那么可以掛起該流程。當然該流程定義下邊所有的流程實例全部暫停。

????????流程定義為掛起狀態,該流程定義將不允許啟動新的流程實例,同時該流程定義下的所有的流程實例都將全部掛起暫停執行。

/*** 掛起流程*/@Testpublic void test05(){// 獲取流程引擎對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId("holiday:1:4").singleResult();// 獲取流程定義的狀態boolean suspended = processDefinition.isSuspended();System.out.println("suspended = " + suspended);if(suspended){// 表示被掛起System.out.println("激活流程定義");repositoryService.activateProcessDefinitionById("holiday:1:4",true,null);}else{// 表示激活狀態System.out.println("掛起流程");repositoryService.suspendProcessDefinitionById("holiday:1:4",true,null);}}

????????具體的實現其實就是更新了流程定義表中的字段:

????????而且通過REV_字段來控制數據安全,也是一種樂觀鎖的體現了,如果要啟動一個已經掛起的流程就會出現如下的錯誤:

6.啟動流程實例

??然后我們來看看啟動流程實例的過程。實現代碼如下:

/*** 啟動流程實例*/@Testpublic void testRunProcess(){// 獲取流程引擎對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 啟動流程實例通過 RuntimeService 對象RuntimeService runtimeService = processEngine.getRuntimeService();// 構建流程變量Map<String,Object> variables = new HashMap<>();variables.put("employee","張三") ;// 誰申請請假variables.put("nrOfHolidays",3); // 請幾天假variables.put("description","工作累了,想出去玩玩"); // 請假的原因// 啟動流程實例,第一個參數是流程定義的idProcessInstance processInstance = runtimeService.startProcessInstanceById("holiday:1:4", variables);// 啟動流程實例// 輸出相關的流程實例信息System.out.println("流程定義的ID:" + processInstance.getProcessDefinitionId());System.out.println("流程實例的ID:" + processInstance.getId());System.out.println("當前活動的ID:" + processInstance.getActivityId());}

????????當我們啟動了一個流程實例后,會在ACT_RU_*對應的表結構中操作,運行時實例涉及的表結構共10張:

  • ACT_RU_DEADLETTER_JOB 正在運行的任務表

  • ACT_RU_EVENT_SUBSCR 運行時事件

  • ACT_RU_EXECUTION 運行時流程執行實例

  • ACT_RU_HISTORY_JOB 歷史作業表

  • ACT_RU_IDENTITYLINK 運行時用戶關系信息

  • ACT_RU_JOB 運行時作業表

  • ACT_RU_SUSPENDED_JOB 暫停作業表

  • ACT_RU_TASK 運行時任務表

  • ACT_RU_TIMER_JOB 定時作業表

  • ACT_RU_VARIABLE 運行時變量表

????????啟動一個流程實例的時候涉及到的表有

  • ACT_RU_EXECUTION 運行時流程執行實例

  • ACT_RU_IDENTITYLINK 運行時用戶關系信息

  • ACT_RU_TASK 運行時任務表

  • ACT_RU_VARIABLE 運行時變量表

ACT_RU_EXECUTION表結構

字段名稱備注
ID_主鍵
REV_版本號
PROC_INST_ID_流程實例ID
BUSINESS_KEY_業務主鍵ID
PARENT_ID_父執行流的ID
PROC_DEF_ID_流程定義的數據ID
SUPER_EXEC_
ROOT_PROC_INST_ID_流程實例的root流程id
ACT_ID_節點實例ID
IS_ACTIVE_是否存活
IS_CONCURRENT_執行流是否正在并行
IS_SCOPE_
IS_EVENT_SCOPE_
IS_MI_ROOT_
SUSPENSION_STATE_流程終端狀態
CACHED_ENT_STATE_
TENANT_ID_租戶編號
NAME_
START_TIME_開始時間
START_USER_ID_開始的用戶編號
LOCK_TIME_鎖定時間
IS_COUNT_ENABLED_
EVT_SUBSCR_COUNT_
TASK_COUNT_
JOB_COUNT_
TIMER_JOB_COUNT_
SUSP_JOB_COUNT_
DEADLETTER_JOB_COUNT_
VAR_COUNT_
ID_LINK_COUNT_

????????創建流程實例后對應的表結構的數據:

ACT_RU_TASK 運行時任務表

字段名稱備注
ID_主鍵
REV_版本號
EXECUTION_ID_任務所在的執行流ID
PROC_INST_ID_流程實例ID
PROC_DEF_ID_流程定義數據ID
NAME_任務名稱
PARENT_TASK_ID_父任務ID
DESCRIPTION_說明
TASK_DEF_KEY_任務定義的ID值
OWNER_任務擁有人
ASSIGNEE_被指派執行該任務的人
DELEGATION_委托人
PRIORITY_優先級
CREATE_TIME_創建時間
DUE_DATE_耗時
CATEGORY_類別
SUSPENSION_STATE_是否掛起1代表激活 2代表掛起
TENANT_ID_租戶編號
FORM_KEY_
CLAIM_TIME_拾取時間

????????創建流程實例后對應的表結構的數據:

ACT_RU_VARIABLE 運行時變量表

字段名稱備注
ID_主鍵
REV_版本號
TYPE_參數類型可以是基本的類型,也可以用戶自行擴展
NAME_參數名稱
EXECUTION_ID_參數執行ID
PROC_INST_ID_流程實例ID
TASK_ID_任務ID
BYTEARRAY_ID_資源ID
DOUBLE_參數為double,則保存在該字段中
LONG_參數為long,則保存在該字段中
TEXT_用戶保存文本類型的參數值
TEXT2_用戶保存文本類型的參數值

????????創建流程實例后對應的表結構的數據:

ACT_RU_IDENTITYLINK 運行時用戶關系信息

字段名稱備注
ID_主鍵
REV_版本號
GROUP_ID_用戶組ID
TYPE_關系數據類型assignee支配人(組)、candidate候選人(組)、owner擁有人,participant參與者
USER_ID_用戶ID
TASK_ID_任務ID
PROC_INST_ID_流程定義ID
PROC_DEF_ID_屬性ID

????????創建流程實例后對應的表結構的數據:

7.處理流程

??上面的流程已經流轉到了zhangsan這個用戶這里,然后可以開始審批了

        // 獲取流程引擎對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processDefinitionId("holiday:1:4").taskAssignee("zhangsan").singleResult();// 添加流程變量Map<String,Object> variables = new HashMap<>();variables.put("approved",false); // 拒絕請假// 完成任務taskService.complete(task.getId(),variables);

在正常處理流程中涉及到的表結構

  • ACT_RU_EXECUTION 運行時流程執行實例

  • ACT_RU_IDENTITYLINK 運行時用戶關系信息

  • ACT_RU_TASK 運行時任務表

  • ACT_RU_VARIABLE 運行時變量表

ACT_RU_TASK 運行時任務表 :會新生成一條記錄

ACT_RU_VARIABLE 運行時變量表:會記錄新的流程變量

????????當然流程實例也可以掛起:

// 1.獲取ProcessEngine對象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 2.獲取RuntimeService
RuntimeService runtimeService = engine.getRuntimeService();
// 3.獲取流程實例對象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("25001").singleResult();
// 4.獲取相關的狀態操作
boolean suspended = processInstance.isSuspended();
String id = processInstance.getId();
if(suspended){// 掛起--》激活runtimeService.activateProcessInstanceById(id);System.out.println("流程定義:" + id + ",已激活");
}else{// 激活--》掛起runtimeService.suspendProcessInstanceById(id);System.out.println("流程定義:" + id + ",已掛起");
}

????????啟動第二個流程實例后再查看相關的表結構時,對他們的關系理解會更加的清楚一些;啟動一個新的流程實例對應的就會產生兩條記錄。

IDENTITYLINK中會記錄每次流程操作的信息:

????????流程變量數據,及時key 相同,但是屬于不同的流程實例相互間也是隔離的。

8.完成一個流程

??然后我們把第一個流程處理完成。

ProcessEngine processEngine = cfg.buildProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionId("holiday:1:4").taskAssignee("lisi").singleResult();
// 添加流程變量
Map<String,Object> variables = new HashMap<>();
variables.put("approved",false); // 拒絕請假
// 完成任務
taskService.complete(task.getId(),variables);

????????處理完了一個工作流程后,我們來看看相關的表結構信息,首先我們會發現

  • ACT_RU_EXECUTION 運行時流程執行實例

  • ACT_RU_IDENTITYLINK 運行時用戶關系信息

  • ACT_RU_TASK 運行時任務表

  • ACT_RU_VARIABLE 運行時變量表

????????這四張表中對應的數據都沒有了,也就是這個流程已經不是運行中的流程了。然后在對應的歷史表中我們可以看到相關的信息

  • ACT_HI_ACTINST 歷史的流程實例

  • ACT_HI_ATTACHMENT 歷史的流程附件

  • ACT_HI_COMMENT 歷史的說明性信息

  • ACT_HI_DETAIL 歷史的流程運行中的細節信息

  • ACT_HI_IDENTITYLINK 歷史的流程運行過程中用戶關系

  • ACT_HI_PROCINST 歷史的流程實例

  • ACT_HI_TASKINST 歷史的任務實例

  • ACT_HI_VARINST 歷史的流程運行中的變量信息

在我們上面的處理流程的過程中設計到的歷史表有

ACT_HI_ACTINST 歷史的流程實例

字段名稱備注
ID_主鍵
PROC_DEF_ID_流程定義ID
PROC_INST_ID_流程實例ID
EXECUTION_ID_執行ID
ACT_ID_節點實例ID
TASK_ID_任務ID
CALL_PROC_INST_ID_調用外部的流程實例ID
ACT_NAME_節點名稱
ACT_TYPE_節點類型
ASSIGNEE_處理人
START_TIME_開始時間
END_TIME_結束時間
DURATION_耗時
DELETE_REASON_刪除原因
TENANT_ID_租戶編號

ACT_HI_IDENTITYLINK 歷史的流程運行過程中用戶關系

字段名稱備注
ID_主鍵
GROUP_ID_組編號
TYPE_類型
USER_ID_用戶編號
TASK_ID_任務編號
CREATE_TIME_創建時間
PROC_INST_ID_流程實例編號
SCOPE_ID_
SCOPE_TYPE_
SCOPE_DEFINITION_ID_

ACT_HI_PROCINST 歷史的流程實例

字段名稱備注
ID_主鍵
PROC_INST_ID_流程實例ID
BUSINESS_KEY_業務主鍵
PROC_DEF_ID_屬性ID
START_TIME_開始時間
END_TIME_結束時間
DURATION_耗時
START_USER_ID_起始人
START_ACT_ID_起始節點
END_ACT_ID_結束節點
SUPER_PROCESS_INSTANCE_ID_父流程實例ID
DELETE_REASON_刪除原因
TENANT_ID_租戶編號
NAME_名稱

ACT_HI_TASKINST 歷史的任務實例

字段名稱備注
ID_主鍵
PROC_DEF_ID_流程定義ID
TASK_DEF_KEY_任務定義的ID值
PROC_INST_ID_流程實例ID
EXECUTION_ID_執行ID
PARENT_TASK_ID_父任務ID
NAME_名稱
DESCRIPTION_說明
OWNER_實際簽收人 任務的擁有者簽收人(默認為空,只有在委托時才有值)
ASSIGNEE_被指派執行該任務的人
START_TIME_開始時間
CLAIM_TIME_任務拾取時間
END_TIME_結束時間
DURATION_耗時
DELETE_REASON_刪除原因
PRIORITY_優先級別
DUE_DATE_過期時間
FORM_KEY_節點定義的formkey
CATEGORY_類別
TENANT_ID_租戶

????????ACT_HI_VARINST 歷史的流程運行中的變量信息:流程變量雖然在任務完成后在流程實例表中會刪除,但是在歷史表中還是會記錄的

字段名稱備注
ID_主鍵
PROC_INST_ID_流程實例ID
EXECUTION_ID_指定ID
TASK_ID_任務ID
NAME_名稱
VAR_TYPE_參數類型
REV_數據版本
BYTEARRAY_ID_字節表ID
DOUBLE_存儲double類型數據
LONG_存儲long類型數據
.....

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72649.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72649.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72649.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

完全背包-一維數組

52. 攜帶研究材料&#xff08;第七期模擬筆試&#xff09; 題目描述 小明是一位科學家&#xff0c;他需要參加一場重要的國際科學大會&#xff0c;以展示自己的最新研究成果。他需要帶一些研究材料&#xff0c;但是他的行李箱空間有限。這些研究材料包括實驗設備、文獻資料和…

景聯文科技:以專業標注賦能AI未來,驅動智能時代的精準躍遷

在人工智能技術重塑全球產業格局的今天&#xff0c;高質量訓練數據已成為驅動算法進化的核心燃料。作為數據智能服務領域的領軍者&#xff0c;景聯文科技深耕數據標注行業多年&#xff0c;以全棧式數據解決方案為核心&#xff0c;構建起覆蓋數據采集、清洗、標注、質檢及算法調…

洛谷B2074 計算星期幾

B2074 計算星期幾 - 洛谷 代碼區&#xff1a; #include<algorithm> #include<iostream> #include<unordered_map> #include<string> using namespace std; int main() {unordered_map<int, string> m { { 1,"Monday" },{2,"Tue…

協同過濾推薦算法+微信小程序的農產品團購推薦平臺(程序+論文+講解+安裝+調試+售后)

感興趣的可以先收藏起來&#xff0c;還有大家在畢設選題&#xff0c;項目以及論文編寫等相關問題都可以給我留言咨詢&#xff0c;我會一一回復&#xff0c;希望幫助更多的人。 系統介紹 在當今時代&#xff0c;科學技術正以令人矚目的速度迅猛進步&#xff0c;經濟社會也隨之…

十大經典排序算法簡介

一 概述 本文對十大經典排序算法做簡要的總結(按常用分類方式排列),包含核心思想、時間/空間復雜度及特點。 二、比較類排序 1. 冒泡排序 (BUBBLE SORT) 思想:重復交換相鄰逆序元素,像氣泡上浮 復雜度: 時間:O(n^2)(最好情況O(n)) 空間:O(1) 特點:簡單但效率低,穩…

[自然語言處理]pytorch概述--什么是張量(Tensor)和基本操作

pytorch概述 PyTorch 是?個開源的深度學習框架&#xff0c;由 Facebook 的??智能研究團隊開發和維護&#xff0c;于2017年在GitHub上開源&#xff0c;在學術界和?業界都得到了?泛應? pytorch能做什么 GPU加速自動求導常用網絡層 pytorch基礎 量的概念 標量&#xf…

Spring統一格式返回

目錄 一&#xff1a;統一結果返回 1&#xff1a;統一結果返回寫法 2&#xff1a;String類型報錯問題 解決方法 二&#xff1a;統一異常返回 統一異常返回寫法 三&#xff1a;總結 同志們&#xff0c;今天咱來講一講統一格式返回啊&#xff0c;也是好久沒有講過統一格式返…

【無標題】四色拓撲模型與宇宙歷史重構的猜想框架

### 四色拓撲模型與宇宙歷史重構的猜想框架 --- #### **一、理論基礎&#xff1a;四色拓撲與時空全息原理的融合** 1. **宇宙背景信息的拓撲編碼** - **大尺度結構網絡**&#xff1a;將星系團映射為四色頂點&#xff0c;纖維狀暗物質結構作為邊&#xff0c;構建宇宙尺度…

藍橋杯 封閉圖形個數

藍橋杯 封閉圖形個數 題目 鏈接 解答 # 數字個數 n int(input()) # 數字 ls input().split() # 統計數字的圈數 o_nums {} for i, x in enumerate(ls):o_num 0for c in x:if int(c) in [0, 4, 6, 9]:o_num 1elif c 8:o_num 2o_nums[i] o_num # 字典根據圓圈數排序 …

基于javaweb的SpringBoot學生在線考試管理系統設計和實現(源碼+文檔+部署講解)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論…

國產編輯器EverEdit - 超多樣式設置

1 設置-編輯-樣式 1.1 設置說明 1.1.1 折疊樣式 默認為箭頭&#xff0c;折疊樣式選項如下&#xff1a; 箭頭&#xff1a; 矩形和線條 五邊形 圓形圖標 1.1.2 光標樣式 光標用于指示當前用戶輸入位置&#xff0c;光標樣式選項如下&#xff1a; 默認 纖細 字寬 …

Linux - 線程控制

一、線程概念 1&#xff09;線程地址空間 線程與進程共享相同的虛擬地址空間&#xff0c;因此線程在訪問內存時與進程沒有本質的區別。但線程共享和獨占的內存區域有不同的特點&#xff0c;理解這些特性對于正確使用線程至關重要。 1. 線程地址空間的組成 線程的地址空間是…

通過多線程分別獲取高分辨率和低分辨率的H264碼流

目錄 一.RV1126 VI采集攝像頭數據并同時獲取高分辨率碼流和低分辨率碼流流程 ?編輯 1.1初始化VI模塊&#xff1a; 1.2初始化RGA模塊&#xff1a; 1.3初始化高分辨率VENC編碼器、 低分辨率VENC編碼器&#xff1a; 1.4 VI綁定高分辨率VENC編碼器&#xff0c;VI綁定RGA模塊…

部署RabbitMQ集群詳細教程

部署RabbitMQ集群詳細教程 下面是一份在 Ubuntu 環境下部署 RabbitMQ 集群的詳細步驟說明&#xff0c;涉及主機名設置、Erlang & RabbitMQ 安裝、管理插件啟用、集群通信 Cookie 配置、節點加入集群、鏡像隊列策略設置以及集群驗證等。為了演示方便&#xff0c;以下示例假…

【Linux】之【Bug】VMware 虛擬機開機 一直卡在黑屏左上角下劃線閃爍界面

解決 參考&#xff1a; 解決Ubuntu20.04 開機黑屏光標閃爍進不去系統 Centos根目錄100%解決思路 當前界面 ctrlaltf3-f6 暫時進入終端界面 df -h 查看發現根目錄 磁盤空間已滿 執行命令 查看當前目錄占用內存明細 sudo du -h -x --max-depth1清理無用的大內存文件 或者安裝…

webflux集成langchain4j基礎版

伴隨著大模型應用的興起&#xff0c;webflux逐漸引起關注。為了以java的方式運行AI應用&#xff0c;讓我們一起學習webflux集成langchain4j吧。 1. 項目依賴 首先&#xff0c;你需要在 pom.xml 中添加必要的依賴&#xff1a; <dependencies><!-- Spring WebFlux --…

使用GitLink個人建站服務部署Allure在線測試報告

更多技術文章&#xff0c;訪問軟件測試社區 文章目錄 &#x1f680;前言&#x1f511;開通GitLink個人建站服務1. 前提條件2. 登錄GitLink平臺&#xff08;https://www.gitlink.org.cn/login&#xff09;3. 進入設置>個人建站>我的站點4. 新建站點5. 去倉部進行部署6. 安…

go數組的聲明和初始化

1.數組簡介 數組是可以存放多個同一類型的數據。數組也是一種數據類型&#xff0c;在go中&#xff0c;數組是值類型。數組的長度也是數組類型的一部分&#xff0c;所以[2]int和[3]int屬于不同的數據類型。 2.數組的長度也是類型的一部分 var arr1 [2]intvar arr2 [3]intfmt.P…

四款GIS工具箱軟件解析:滿足企業多樣化空間數據需求

概述 隨著地理信息系統&#xff08;GIS&#xff09;在城市規劃、環境監測、資源管理等領域的廣泛應用&#xff0c;各種GIS工具箱軟件不斷涌現&#xff0c;為用戶提供了強大的數據處理、空間分析和地圖制圖功能。本文將為大家介紹4款GIS工具箱軟件&#xff0c;這些軟件各具特色…

VirtualBox虛擬機安裝Mac OS啟動后的系統設置

VirtualBox虛擬機安裝Mac OS一直沒裝成功&#xff0c;本來想要放棄的&#xff0c;后來想著再試一次&#xff0c;于是在關機的情況&#xff0c;執行那幾句設置&#xff1a; cd "E:\Program Files\Oracle\VirtualBox\" VBoxManage.exe modifyvm "MacOS" --c…