一萬字帶你入門 Activiti 工作流,通俗易懂!
來源:blog.csdn.net/Mr_97xu/article/details/112899079
概念
工作流。通過計算機對業務流程自動化執行管理,主要解決的是 “使在多個參與者之間按照某種預定義的規則自動進行傳遞文檔、信息或任務的過程,從而實現某個預期的業務目標,或者促使此目標的實現”。
Activiti7
介紹
Activiti 是一個工作流引擎,Activiti 可以將業務系統中複雜的業務流程抽取出來,使用專門的建模語言 BPMN2.0 進行定義,業務流程按照預先定義的流程進行執行,實現了系統的流程由 Activiti 進行管理,減少業務系統由於流程變更進行系統升級改造的工作量,從而提高系統的健壯性,同時也減少了系統開發維護成本。
在使用 activiti 之前,首先需要編寫activiti.cfg.xml
配置文件。並且引入相關依賴。
<dependencies>
<!--activiti的核心包-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>7-201710-EA</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
</dependencies>
activiti.cfg.xml
activiti 的引擎配置文件,包括:ProcessEngineConfiguration
的定義、數據源定義、事務管理器等。其實就是一個 Spring 配置文件。
<?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">
<!--dbcp連接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property />
<property />
<property />
<property />
<property />
<property />
</bean>
<!--在默認方式下,bean的id固定爲processEngineConfiguration-->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--配置數據庫相關信息-->
<property />
<!--
activiti數據庫表處理策略
false(默認值):檢查數據庫的版本和依賴庫的版本,如果不匹配就拋出異常
true:構建流程引擎時,執行檢查,如果需要就執行更新。如果表不存在,就創建。
create-drop:構建流程引擎時創建數據庫報表,關閉流程引擎時就刪除這些表。
drop-create:先刪除表再創建表。
create:構建流程引擎時創建數據庫表,關閉流程引擎時不刪除這些表
-->
<property />
<property />
<property />
<property />
</bean>
</beans>
Activiti 流程框架,在前期主要需要了解的就是數據庫表的創建、流程的部署、流程的啓動和各個階段任務的完成。
流程引擎配置類
流程引擎配置類(ProcessEngineConfiguration
),通過 ProcessEngineConfiguration
可以創建工作流引擎 ProceccEngine。
工作流引擎的創建
工作流引擎的創建主要有兩種方式:默認創建方式和一般創建方式
默認創建方式
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
一般創建方式
//使用自定義方式創建
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
//獲取流程引擎對象:通過 ProcessEngineConfiguration 創建 ProcessEngine,此時會創建數據庫
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
當創建好工作流引擎後,對應的數據庫中會自動生成 25 張數據庫表。
ACT_GE_PROPERTY
中會先展示下一次流程的 ID(next.dbid
),並且在下一次流程部署的時候,對下一次流程的 ID 進行賦值。
Activiti 表說明
這裏以表名的前綴進行說明:
Service 服務接口
Activiti 中還有許多的 Service 服務接口。這些 Service 是工作流引擎提供用於進行工作流部署、執行、管理的服務接口,我們可以使用這些接口操作服務對應的數據表。
Service 創建方式
通過ProcessEngine
創建 Service 方式:
Runtimeservice runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
Service 總覽
- RepositoryService
Activiti 的資源管理類,提供了管理和控制流程發佈包和流程定義的操作。使用工作流建模工具設計的業務流程圖需要使用此 service 將流程定義文件的內容部署到計算機。除了部署流程定義以外,還可以查詢引擎中的發佈包和流程定義。
暫停或激活發佈包,對應全部和特定流程定義。暫停意味着它們不能再執行任何操作了,激活是對應的反向操作。獲得多種資源,像是包含在發佈包裏的文件,或引擎自動生成的流程圖。獲得流程定義的 pojo 版本,可以用來通過 java 解析流程,而不必通過 xml。
- Runtimeservice
Activiti 的流程運行管理類。可以從這個服務類中獲取很多關於流程執行相關的信息
- Taskservice
Activiti 的任務管理類。可以從這個類中獲取任務的信息。
- Historyservice
Activiti 的歷史管理類,可以查詢歷史信息,執行流程時,引擎會保存很多數據(根據配置),比如流程實例啓動時間,任務的參與者,完成任務的時間,每個流程實例的執行路徑,等等。這個服務主要通過查詢功能來獲得這些數據。
- ManagementService
Activiti 的引擎管理類,提供了對 Activiti 流程引擎的管理和維護功能,這些功能不在工作流驅動的應用程序中使用,主要用於 Activiti 系統的日常維護。
流程圖符號說明
BPMN 插件
使用 IDEA 進行開發,建議下載一個插件。actiBPM 插件,直接搜索下載。
流程符號、畫流程圖
流程符號:事件 Event,活動 Activity,網關 Gateway,流向
使用流程設計器畫出流程圖
-
創建 bpmn 文件,在流程設計器使用流程符號來表達流程,指定流程的 key,指定任務負責人
-
生成 png 文件
-
創建的 bpmn 文件要放在 resourse 下的 bpmn 文件夾下。
注意:當前任務流程的 ID 不能是數字開頭。
找到本地的文件,選擇 notepad 打開
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" 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:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1611283406582" >
<process id="myEvection" isClosed="false" isExecutable="true" >
<startEvent id="_2" />
<userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" />
<userTask activiti:assignee="jerry" activiti:exclusive="true" id="_4" />
<userTask activiti:assignee="jack" activiti:exclusive="true" id="_5" />
<userTask activiti:assignee="rose" activiti:exclusive="true" id="_6" />
<endEvent id="_7" />
<sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
<sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
<sequenceFlow id="_10" sourceRef="_4" targetRef="_5"/>
<sequenceFlow id="_11" sourceRef="_5" targetRef="_6"/>
<sequenceFlow id="_12" sourceRef="_6" targetRef="_7"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" >
<bpmndi:BPMNPlane bpmnElement="myEvection">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="185.0" y="0.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<omgdc:Bounds height="55.0" width="85.0" x="160.0" y="85.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
<omgdc:Bounds height="55.0" width="85.0" x="160.0" y="185.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<omgdc:Bounds height="55.0" width="85.0" x="160.0" y="285.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
<omgdc:Bounds height="55.0" width="85.0" x="160.0" y="390.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
<omgdc:Bounds height="32.0" width="32.0" x="185.0" y="475.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_7">
<omgdi:waypoint x="201.0" y="445.0"/>
<omgdi:waypoint x="201.0" y="475.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_2" targetElement="_3">
<omgdi:waypoint x="201.0" y="32.0"/>
<omgdi:waypoint x="201.0" y="85.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_4">
<omgdi:waypoint x="202.5" y="140.0"/>
<omgdi:waypoint x="202.5" y="185.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_5" targetElement="_6">
<omgdi:waypoint x="202.5" y="340.0"/>
<omgdi:waypoint x="202.5" y="390.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5">
<omgdi:waypoint x="202.5" y="240.0"/>
<omgdi:waypoint x="202.5" y="285.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
流程的操作
部署流程
使用 Activiti 提供的 API 把流程圖的內容寫入到數據庫中
屬於資源操作類,使用 RepositoryService
-
單文件部署:把 bpmn 文件和 png 文件逐個處理
-
壓縮包部署:把 bpmn 文件和 png 文件打成壓縮包來處理
-
部署操作表:
act_re_deployment
、act_re_procdef
、act_ge_bytearray
/**
* 流程部署
*/
public void deployment() {
// 創建 ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 使用 service 進行流程的部署,定義一個流程的名字,把bpmn和png部署到數據中
Deployment deployment = repositoryService.createDeployment()
.name("出差申請流程") //流程圖標的名字
.addClasspathResource("bpmn/evection.bpmn") //bpmn文件
.addClasspathResource("bpmn/evection.png") //bpmn文件生成的圖片
.deploy();
// 輸出部署信息
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署名字:" + deployment.getName());
}
有時候我們會有多個流程,需要創建多個 bpmn 流程文件,這個時候想要同時部署,我們可以對 bpmn 文件進行打包壓縮,使用 Zip 包進行批量的部署
/**
* 使用Zip包進行批量的部署
*/
@Test
public void deployProcessByZip() {
// 獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 流程部署
// 讀取資源包文件,構造成 InputStream
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
// 使用 InputStream 構造 ZipInputStream
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 使用壓縮包的流,進行流程的部署
Deployment deploy = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
// 輸出
System.out.println("流程部署的ID:" + deploy.getId());
System.out.println("流程部署的名稱:" + deploy.getName());
}
操作的數據庫表:
-
act_ge_bytearray
-
act_ge_property
-
act_re_deployment
-
act_re_procdef
啓動流程實例
流程部署完成以後,需要啓動流程實例。使用 RuntimeService
根據流程定義的 key 進行啓動。
核心代碼:
/**
* 啓動流程
*/
public void starProcess() {
// 創建 ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取 RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根據流程定義的ID啓動流程
ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
// 輸出內容
System.out.println("流程定義ID:" + instance.getProcessDefinitionId());
System.out.println("流程實例的ID:" + instance.getId());
System.out.println("當前活動的ID:" + instance.getActivityId());
}
任務查詢
使用 TaskService
,根據流程定義的 key ,任務負責人來進行查詢
核心代碼:
/**
* 查詢個人待執行的任務
*/
@Test
public void findPersonalTaskList() {
// 獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取TaskService
TaskService taskService = processEngine.getTaskService();
// 根據流程的key和任務的負責人去查詢任務
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("myEvection") // 流程的key
.includeProcessVariables()
.taskAssignee("zhangsan") // 要查詢的負責人
.list();
// 輸出
for (Task task : taskList) {
System.out.println("流程實例的ID:" + task.getProcessInstanceId());
System.out.println("任務的ID:" + task.getId());
System.out.println("任務的負責人:" + task.getAssignee());
System.out.println("任務的名稱:" + task.getName());
}
}
任務完成
使用 TaskService
,用任務 ID 直接完成任務。
核心代碼:
/**
* 完成個人任務
*/
@Test
public void completTask() {
String key = "testCandidiate";
String assignee = "張三1"; //任務的負責人
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assignee)
.singleResult();
if (task != null) {
taskService.complete(task.getId());
}
}
關於流程實例的掛起和激活
全部流程實例的掛起和激活
/**
* 全部流程實例的掛起和激活
*/
@Test
public void suspendAllProcessInstance() {
// 1.獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.獲取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.查詢流程定義
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("myEvection")
.singleResult();
// 4.獲取當前流程定義的實例是否都是掛起狀態
boolean flag = processDefinition.isSuspended();
// 5.獲取流程定義的ID
String id = processDefinition.getId();
// 6.判斷是否掛起狀態。是:改爲激活;否:改爲掛起
if (flag) {
// 改爲激活. 參數1:流程定義的ID,參數2:是否激活,參數3:激活時間
repositoryService.activateProcessDefinitionById(id, true, null);
System.out.println("流程定義ID:" + id + "已激活");
} else {
// 改爲掛起. 參數1:流程定義的ID;參數2:是否掛起;參數3:掛起時間
repositoryService.suspendProcessDefinitionById(id, true, null);
System.out.println("流程定義ID:" + id + "已掛起");
}
}
單個流程實例的掛起和激活
/**
* 單個流程實例的掛起和激活
*/
@Test
public void suspendSingleProcessInstance() {
// 1.獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.獲取 RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3.通過 RuntimeService 獲取流程實例對象
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId("17501")
.singleResult();
// 4.得到當前流程實例的暫停狀態
boolean flag = instance.isSuspended();
// 5.獲取流程實例的ID
String instanceId = instance.getId();
// 6.判斷是否暫停。是:改爲激活;否:改爲暫停
if (flag) {
runtimeService.activateProcessInstanceById(instanceId);
System.out.println("流程實例ID:" + instanceId + "已激活");
} else {
runtimeService.suspendProcessInstanceById(instanceId);
System.out.println("流程實例ID:" + instanceId + "已暫停");
}
}
注意:流程實例在掛起的狀態下是無法進行下一步操作的。
流程變量
我們在使用流程變量的時候。如果我們將一個對象存儲到一個流程變量中,那麼這個對象需要實現 Serializable 接口。
/**
* 出差申請中的流程變量對象
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Evection implements Serializable {
private Long id; //主鍵ID
private Integer days; //出差天數
private String evectionName; //出差單名字
private Date startTime; //出差開始時間
private Date endTime; //出差結束時間
private String address; //目的地
private String reason; //出差原因
}
流程變量的作用域
-
整個流程實例、任務、執行實例。
-
默認:整個流程實例。
使用方法
在屬性上使用 UEL 表達式 ${assignee}
,assignee
就是一個流程變量的名稱。
在連線上使用 UEL 表達式 ${days<=3}
,days 就是一個流程變量名稱,返回結果爲 true 或者 false。
Activiti 有很多種方式設置流程變量,這裏簡單介紹兩種:
啓動流程時設置流程變量
/**
* 啓動流程
*/
@Test
public void startProcess() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 流程變量map
Map<String, Object> map = new HashMap<>();
// 設置流程變量
Evection evection = new Evection();
evection.setDays(2);
// 把流程變量的pojo放入map
map.put("evection", evection);
map.put("assignee0", "張三");
map.put("assignee1", "李經理");
map.put("assignee2", "王財務");
map.put("assignee3", "趙總經理");
runtimeService.startProcessInstanceByKey("myProcess_1", map);
}
任務辦理時設置
/**
* 完成任務
*/
@Test
public void completTask() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection();
evection.setDays(2);
Map<String, Object> map = new HashMap<>();
map.put("evection", evection);
Task task = taskService.createTaskQuery()
.processDefinitionKey("myProcess_2")
.taskAssignee("王財務0")
.singleResult();
if (task != null) {
String taskId = task.getId();
// 完成任務
taskService.complete(taskId, map);
}
}
網關
用來控制流程的走向
排他網關——ExclusiveGateway
用來在流程中實現決策,當流程執行到這個網關,所有的分支都會判斷條件是否爲 true,如果爲 true,則執行該分支。
注意:排他網關只會選擇一個作爲 true 的分支執行,如果有兩個分支都爲 true,排他網關會選擇 ID 值比較小的一條分支去執行。
如果從排他網關出去的流程所有的條件都不滿足,則會拋出異常。
並行網關——ParallelGateway
並行網關,允許流程分成多條分支,也可以把多分支匯聚到一起,並行網關的功能是基於進入和外出順序流的:
-
fork 分支:並行後的所有外出順序流,爲每個順序流都創建一個併發分支
-
join 匯聚:所有到達並行網關,在此等待的分支,直到所有進入順序流的分支都到達以後,流程就會通過匯聚網關。
注意:如果同一個並行網關有多個進入和多個外出順序流,它就同時具有分支和匯聚功能,這時,網關會先匯聚所有進入的順序流,然後再切分成多個並行分支。
與其他網關的主要區別是:並行網關不會解析條件,即使順序流中定義了條件,也會被忽略。
並行網關需要所有分支的全部運行完了,纔會匯聚,繼續向下執行。
包含網關——InclusiveGateway
包含網關可以看成是排他網關和並行網關的結合體,和排他網關一樣,可以在外出順序流上定義條件,包含網關會解析它們,但是主要的區別是:包含網關可以選擇多於一條順序流,這和並行網關一樣。
包含網關的功能是基於進入和外出順序流的。
-
分支:所有外出順序流的條件都會被解析,結果爲 true 的順序流會以並行方式繼續執行,會爲每一個順序流創建一個分支。
-
匯聚:所有並行分支到達包含網關,會進入等待狀態,直到每個包含流程 token 的進入順序流的分支都到達。這是和並行網關最大的不同。
事件網關——EventGateway
Activiti 和 Spring 的整合開發
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--工作流引擎配置對象-->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!--數據源-->
<property />
<!--使用Spring的事務管理器-->
<property />
<!--
數據庫策略:
false:默認值。activiti在啓動時,會對比數據庫表中保存的版本。如果沒有表或者版本不匹配,將拋出 異常。
true:activiti會對數據庫中所有表進行更新操作,如果表不存在,則會自動創建。
create_drop:在activiti啓動時創建表,在關閉時刪除表(必須手動關閉引擎,才能刪除表)。
drop-create:在activiti啓動時刪除原來的舊錶,然後再創建新表(不需要手動關閉引擎)。
-->
<property />
</bean>
<!--配置數據源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property />
<property />
<property />
<property />
<property />
<property />
</bean>
<!-- 流程引擎對象 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property />
</bean>
<!--資源服務-->
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
<!--流程管理-->
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
<!--任務管理-->
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
<!--歷史管理-->
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
<!--事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property />
</bean>
<!--通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--傳播行爲-->
<tx:method />
<tx:method />
<tx:method />
<tx:method />
<tx:method />
<tx:method />
</tx:attributes>
</tx:advice>
</beans>
Activiti 和 SpringBoot 的整合開發
配置文件:
spring:
application:
name: actspringboot
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/actspring?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
username: root
password: root
activiti:
# false:默認值。activiti在啓動時,會對比數據庫表中保存的版本。如果沒有表或者版本不匹配,將拋出異常
# true:activiti會對數據庫中所有表進行更新操作,如果表不存在,則會自動創建
# create_drop:在activiti啓動時創建表,在關閉時刪除表(必須手動關閉引擎,才能刪除表)
# drop-create:在activiti啓動時刪除原來的舊錶,然後再創建新表(不需要手動關閉引擎)
# 線上一般使用false,開發中使用true
database-schema-update: true
# 自動部署驗證設置:true-開啓(默認)、false-關閉
check-process-definitions: false
# 開啓歷史表
db-history-used: true
# 歷史記錄存儲等級
history-level: full
server:
port: 8082
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/FV_pDTrCyORwCwm1684ZUA