一萬(wàn)字帶你入門(mén) Activiti 工作流,通俗易懂!

來(lái)源:blog.csdn.net/Mr_97xu/article/details/112899079
概念
工作流。通過(guò)計(jì)算機(jī)對(duì)業(yè)務(wù)流程自動(dòng)化執(zhí)行管理,主要解決的是“使在多個(gè)參與者之間按照某種預(yù)定義的規(guī)則自動(dòng)進(jìn)行傳遞文檔、信息或任務(wù)的過(guò)程,從而實(shí)現(xiàn)某個(gè)預(yù)期的業(yè)務(wù)目標(biāo),或者促使此目標(biāo)的實(shí)現(xiàn)”。
Activiti7
介紹
Activiti是一個(gè)工作流引擎,Activiti可以將業(yè)務(wù)系統(tǒng)中復(fù)雜的業(yè)務(wù)流程抽取出來(lái),使用專(zhuān)門(mén)的建模語(yǔ)言BPMN2.0進(jìn)行定義,業(yè)務(wù)流程按照預(yù)先定義的流程進(jìn)行執(zhí)行,實(shí)現(xiàn)了系統(tǒng)的流程由Activiti進(jìn)行管理,減少業(yè)務(wù)系統(tǒng)由于流程變更進(jìn)行系統(tǒng)升級(jí)改造的工作量,從而提高系統(tǒng)的健壯性,同時(shí)也減少了系統(tǒng)開(kāi)發(fā)維護(hù)成本。
在使用activiti之前,首先需要編寫(xiě)activiti.cfg.xml配置文件。并且引入相關(guān)依賴(lài)。
<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的定義、數(shù)據(jù)源定義、事務(wù)管理器等。其實(shí)就是一個(gè)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 name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/activiti"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="3"/>
<property name="maxIdle" value="1"/>
</bean>
<!--在默認(rèn)方式下,bean的id固定為processEngineConfiguration-->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--配置數(shù)據(jù)庫(kù)相關(guān)信息-->
<property name="dataSource" ref="dataSource"/>
<!--
activiti數(shù)據(jù)庫(kù)表處理策略
false(默認(rèn)值):檢查數(shù)據(jù)庫(kù)的版本和依賴(lài)庫(kù)的版本,如果不匹配就拋出異常
true:構(gòu)建流程引擎時(shí),執(zhí)行檢查,如果需要就執(zhí)行更新。如果表不存在,就創(chuàng)建。
create-drop:構(gòu)建流程引擎時(shí)創(chuàng)建數(shù)據(jù)庫(kù)報(bào)表,關(guān)閉流程引擎時(shí)就刪除這些表。
drop-create:先刪除表再創(chuàng)建表。
create:構(gòu)建流程引擎時(shí)創(chuàng)建數(shù)據(jù)庫(kù)表,關(guān)閉流程引擎時(shí)不刪除這些表
-->
<property name="databaseSchemaUpdate" value="true"/>
<property name="asyncExecutorActivate" value="false"/>
<property name="mailServerHost" value="mail.my-corp.com"/>
<property name="mailServerPort" value="5025"/>
</bean>
</beans>
Activiti流程框架,在前期主要需要了解的就是數(shù)據(jù)庫(kù)表的創(chuàng)建、流程的部署、流程的啟動(dòng)和各個(gè)階段任務(wù)的完成。
流程引擎配置類(lèi)
流程引擎配置類(lèi)(ProcessEngineConfiguration),通過(guò) ProcessEngineConfiguration 可以創(chuàng)建工作流引擎 ProceccEngine。
工作流引擎的創(chuàng)建
工作流引擎的創(chuàng)建主要有兩種方式:默認(rèn)創(chuàng)建方式和一般創(chuàng)建方式
默認(rèn)創(chuàng)建方式
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
一般創(chuàng)建方式
//使用自定義方式創(chuàng)建
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
//獲取流程引擎對(duì)象:通過(guò) ProcessEngineConfiguration 創(chuàng)建 ProcessEngine,此時(shí)會(huì)創(chuàng)建數(shù)據(jù)庫(kù)
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
當(dāng)創(chuàng)建好工作流引擎后,對(duì)應(yīng)的數(shù)據(jù)庫(kù)中會(huì)自動(dòng)生成25張數(shù)據(jù)庫(kù)表。

ACT_GE_PROPERTY中會(huì)先展示下一次流程的ID(next.dbid),并且在下一次流程部署的時(shí)候,對(duì)下一次流程的ID進(jìn)行賦值。

Activiti表說(shuō)明
這里以表名的前綴進(jìn)行說(shuō)明:

Service服務(wù)接口
Activiti中還有許多的Service服務(wù)接口。這些Service 是工作流引擎提供用于進(jìn)行工作流部署、執(zhí)行、管理的服務(wù)接口,我們可以使用這些接口操作服務(wù)對(duì)應(yīng)的數(shù)據(jù)表。
Service創(chuàng)建方式
通過(guò)ProcessEngine創(chuàng)建Service方式:
Runtimeservice runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
Service總覽

RepositoryService
Activiti 的資源管理類(lèi),提供了管理和控制流程發(fā)布包和流程定義的操作。使用工作流建模工具設(shè)計(jì)的業(yè)務(wù)流程圖需要使用此service將流程定義文件的內(nèi)容部署到計(jì)算機(jī)。除了部署流程定義以外,還可以查詢(xún)引擎中的發(fā)布包和流程定義。
暫?;蚣せ畎l(fā)布包,對(duì)應(yīng)全部和特定流程定義。暫停意味著它們不能再執(zhí)行任何操作了,激活是對(duì)應(yīng)的反向操作。獲得多種資源,像是包含在發(fā)布包里的文件,或引擎自動(dòng)生成的流程圖。獲得流程定義的pojo版本,可以用來(lái)通過(guò)java解析流程,而不必通過(guò)xml。
Runtimeservice
Activiti的流程運(yùn)行管理類(lèi)??梢詮倪@個(gè)服務(wù)類(lèi)中獲取很多關(guān)于流程執(zhí)行相關(guān)的信息
Taskservice
Activiti的任務(wù)管理類(lèi)??梢詮倪@個(gè)類(lèi)中獲取任務(wù)的信息。
Historyservice
Activiti的歷史管理類(lèi),可以查詢(xún)歷史信息,執(zhí)行流程時(shí),引擎會(huì)保存很多數(shù)據(jù)(根據(jù)配置),比如流程實(shí)例啟動(dòng)時(shí)間,任務(wù)的參與者,完成任務(wù)的時(shí)間,每個(gè)流程實(shí)例的執(zhí)行路徑,等等。這個(gè)服務(wù)主要通過(guò)查詢(xún)功能來(lái)獲得這些數(shù)據(jù)。
ManagementService
Activiti的引擎管理類(lèi),提供了對(duì)Activiti流程引擎的管理和維護(hù)功能,這些功能不在工作流驅(qū)動(dòng)的應(yīng)用程序中使用,主要用于Activiti 系統(tǒng)的日常維護(hù)。
流程圖符號(hào)說(shuō)明

BPMN插件
使用IDEA進(jìn)行開(kāi)發(fā),建議下載一個(gè)插件。actiBPM插件,直接搜索下載。
流程符號(hào)、畫(huà)流程圖
流程符號(hào):事件Event,活動(dòng)Activity,網(wǎng)關(guān)Gateway,流向
使用流程設(shè)計(jì)器畫(huà)出流程圖
創(chuàng)建bpmn文件,在流程設(shè)計(jì)器使用流程符號(hào)來(lái)表達(dá)流程,指定流程的key,指定任務(wù)負(fù)責(zé)人 生成png文件 創(chuàng)建的bpmn文件要放在resourse下的bpmn文件夾下。


注意: 當(dāng)前任務(wù)流程的ID不能是數(shù)字開(kāi)頭。

找到本地的文件,選擇notepad打開(kāi)
<?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" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="myEvection" isClosed="false" isExecutable="true" name="出差申請(qǐng)" processType="None">
<startEvent id="_2" name="StartEvent"/>
<userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" name="創(chuàng)建出差申請(qǐng)"/>
<userTask activiti:assignee="jerry" activiti:exclusive="true" id="_4" name="經(jīng)理審批"/>
<userTask activiti:assignee="jack" activiti:exclusive="true" id="_5" name="總經(jīng)理審批"/>
<userTask activiti:assignee="rose" activiti:exclusive="true" id="_6" name="財(cái)務(wù)審批"/>
<endEvent id="_7" name="EndEvent"/>
<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" name="New Diagram">
<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 把流程圖的內(nèi)容寫(xiě)入到數(shù)據(jù)庫(kù)中
屬于資源操作類(lèi),使用 RepositoryService
單文件部署:把bpmn文件和png文件逐個(gè)處理 壓縮包部署:把bpmn文件和png文件打成壓縮包來(lái)處理 部署操作表: act_re_deployment、act_re_procdef、act_ge_bytearray
/**
* 流程部署
*/
public void deployment() {
// 創(chuàng)建 ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 使用 service 進(jìn)行流程的部署,定義一個(gè)流程的名字,把bpmn和png部署到數(shù)據(jù)中
Deployment deployment = repositoryService.createDeployment()
.name("出差申請(qǐng)流程") //流程圖標(biāo)的名字
.addClasspathResource("bpmn/evection.bpmn") //bpmn文件
.addClasspathResource("bpmn/evection.png") //bpmn文件生成的圖片
.deploy();
// 輸出部署信息
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署名字:" + deployment.getName());
}
有時(shí)候我們會(huì)有多個(gè)流程,需要?jiǎng)?chuàng)建多個(gè)bpmn流程文件,這個(gè)時(shí)候想要同時(shí)部署,我們可以對(duì)bpmn文件進(jìn)行打包壓縮,使用Zip包進(jìn)行批量的部署
/**
* 使用Zip包進(jìn)行批量的部署
*/
@Test
public void deployProcessByZip() {
// 獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 流程部署
// 讀取資源包文件,構(gòu)造成 InputStream
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
// 使用 InputStream 構(gòu)造 ZipInputStream
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 使用壓縮包的流,進(jìn)行流程的部署
Deployment deploy = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
// 輸出
System.out.println("流程部署的ID:" + deploy.getId());
System.out.println("流程部署的名稱(chēng):" + deploy.getName());
}
操作的數(shù)據(jù)庫(kù)表:
act_ge_bytearray act_ge_property act_re_deployment act_re_procdef
啟動(dòng)流程實(shí)例
流程部署完成以后,需要啟動(dòng)流程實(shí)例。使用 RuntimeService 根據(jù)流程定義的 key進(jìn)行啟動(dòng)。
核心代碼:
/**
* 啟動(dòng)流程
*/
public void starProcess() {
// 創(chuàng)建 ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取 RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根據(jù)流程定義的ID啟動(dòng)流程
ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
// 輸出內(nèi)容
System.out.println("流程定義ID:" + instance.getProcessDefinitionId());
System.out.println("流程實(shí)例的ID:" + instance.getId());
System.out.println("當(dāng)前活動(dòng)的ID:" + instance.getActivityId());
}
任務(wù)查詢(xún)
使用 TaskService ,根據(jù)流程定義的 key ,任務(wù)負(fù)責(zé)人來(lái)進(jìn)行查詢(xún)
核心代碼:
/**
* 查詢(xún)個(gè)人待執(zhí)行的任務(wù)
*/
@Test
public void findPersonalTaskList() {
// 獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 獲取TaskService
TaskService taskService = processEngine.getTaskService();
// 根據(jù)流程的key和任務(wù)的負(fù)責(zé)人去查詢(xún)?nèi)蝿?wù)
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("myEvection") // 流程的key
.includeProcessVariables()
.taskAssignee("zhangsan") // 要查詢(xún)的負(fù)責(zé)人
.list();
// 輸出
for (Task task : taskList) {
System.out.println("流程實(shí)例的ID:" + task.getProcessInstanceId());
System.out.println("任務(wù)的ID:" + task.getId());
System.out.println("任務(wù)的負(fù)責(zé)人:" + task.getAssignee());
System.out.println("任務(wù)的名稱(chēng):" + task.getName());
}
}
任務(wù)完成
使用 TaskService ,用任務(wù) ID 直接完成任務(wù)。
核心代碼:
/**
* 完成個(gè)人任務(wù)
*/
@Test
public void completTask() {
String key = "testCandidiate";
String assignee = "張三1"; //任務(wù)的負(fù)責(zé)人
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assignee)
.singleResult();
if (task != null) {
taskService.complete(task.getId());
}
}
關(guān)于流程實(shí)例的掛起和激活
全部流程實(shí)例的掛起和激活
/**
* 全部流程實(shí)例的掛起和激活
*/
@Test
public void suspendAllProcessInstance() {
// 1.獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.獲取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.查詢(xún)流程定義
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("myEvection")
.singleResult();
// 4.獲取當(dāng)前流程定義的實(shí)例是否都是掛起狀態(tài)
boolean flag = processDefinition.isSuspended();
// 5.獲取流程定義的ID
String id = processDefinition.getId();
// 6.判斷是否掛起狀態(tài)。是:改為激活;否:改為掛起
if (flag) {
// 改為激活. 參數(shù)1:流程定義的ID,參數(shù)2:是否激活,參數(shù)3:激活時(shí)間
repositoryService.activateProcessDefinitionById(id, true, null);
System.out.println("流程定義ID:" + id + "已激活");
} else {
// 改為掛起. 參數(shù)1:流程定義的ID;參數(shù)2:是否掛起;參數(shù)3:掛起時(shí)間
repositoryService.suspendProcessDefinitionById(id, true, null);
System.out.println("流程定義ID:" + id + "已掛起");
}
}
單個(gè)流程實(shí)例的掛起和激活
/**
* 單個(gè)流程實(shí)例的掛起和激活
*/
@Test
public void suspendSingleProcessInstance() {
// 1.獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.獲取 RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3.通過(guò) RuntimeService 獲取流程實(shí)例對(duì)象
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId("17501")
.singleResult();
// 4.得到當(dāng)前流程實(shí)例的暫停狀態(tài)
boolean flag = instance.isSuspended();
// 5.獲取流程實(shí)例的ID
String instanceId = instance.getId();
// 6.判斷是否暫停。是:改為激活;否:改為暫停
if (flag) {
runtimeService.activateProcessInstanceById(instanceId);
System.out.println("流程實(shí)例ID:" + instanceId + "已激活");
} else {
runtimeService.suspendProcessInstanceById(instanceId);
System.out.println("流程實(shí)例ID:" + instanceId + "已暫停");
}
}
注意: 流程實(shí)例在掛起的狀態(tài)下是無(wú)法進(jìn)行下一步操作的。
流程變量
我們?cè)谑褂昧鞒套兞康臅r(shí)候。如果我們將一個(gè)對(duì)象存儲(chǔ)到一個(gè)流程變量中,那么這個(gè)對(duì)象需要實(shí)現(xiàn)Serializable接口。
/**
* 出差申請(qǐng)中的流程變量對(duì)象
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Evection implements Serializable {
private Long id; //主鍵ID
private Integer days; //出差天數(shù)
private String evectionName; //出差單名字
private Date startTime; //出差開(kāi)始時(shí)間
private Date endTime; //出差結(jié)束時(shí)間
private String address; //目的地
private String reason; //出差原因
}
流程變量的作用域
整個(gè)流程實(shí)例、任務(wù)、執(zhí)行實(shí)例。 默認(rèn):整個(gè)流程實(shí)例。
使用方法
在屬性上使用UEL表達(dá)式 ${assignee},assignee就是一個(gè)流程變量的名稱(chēng)。

在連線(xiàn)上使用UEL表達(dá)式 ${days<=3},days就是一個(gè)流程變量名稱(chēng),返回結(jié)果為true或者false。

Activiti有很多種方式設(shè)置流程變量,這里簡(jiǎn)單介紹兩種:
啟動(dòng)流程時(shí)設(shè)置流程變量
/**
* 啟動(dòng)流程
*/
@Test
public void startProcess() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 流程變量map
Map<String, Object> map = new HashMap<>();
// 設(shè)置流程變量
Evection evection = new Evection();
evection.setDays(2);
// 把流程變量的pojo放入map
map.put("evection", evection);
map.put("assignee0", "張三");
map.put("assignee1", "李經(jīng)理");
map.put("assignee2", "王財(cái)務(wù)");
map.put("assignee3", "趙總經(jīng)理");
runtimeService.startProcessInstanceByKey("myProcess_1", map);
}
任務(wù)辦理時(shí)設(shè)置
/**
* 完成任務(wù)
*/
@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("王財(cái)務(wù)0")
.singleResult();
if (task != null) {
String taskId = task.getId();
// 完成任務(wù)
taskService.complete(taskId, map);
}
}
網(wǎng)關(guān)
用來(lái)控制流程的走向
排他網(wǎng)關(guān)——ExclusiveGateway
用來(lái)在流程中實(shí)現(xiàn)決策,當(dāng)流程執(zhí)行到這個(gè)網(wǎng)關(guān),所有的分支都會(huì)判斷條件是否為true,如果為true,則執(zhí)行該分支。
注意: 排他網(wǎng)關(guān)只會(huì)選擇一個(gè)作為true的分支執(zhí)行,如果有兩個(gè)分支都為true,排他網(wǎng)關(guān)會(huì)選擇ID值比較小的一條分支去執(zhí)行。
如果從排他網(wǎng)關(guān)出去的流程所有的條件都不滿(mǎn)足,則會(huì)拋出異常。
并行網(wǎng)關(guān)——ParallelGateway
并行網(wǎng)關(guān),允許流程分成多條分支,也可以把多分支匯聚到一起,并行網(wǎng)關(guān)的功能是基于進(jìn)入和外出順序流的:
fork分支:并行后的所有外出順序流,為每個(gè)順序流都創(chuàng)建一個(gè)并發(fā)分支 join匯聚:所有到達(dá)并行網(wǎng)關(guān),在此等待的分支,直到所有進(jìn)入順序流的分支都到達(dá)以后,流程就會(huì)通過(guò)匯聚網(wǎng)關(guān)。
注意: 如果同一個(gè)并行網(wǎng)關(guān)有多個(gè)進(jìn)入和多個(gè)外出順序流,它就同時(shí)具有分支和匯聚功能,這時(shí),網(wǎng)關(guān)會(huì)先匯聚所有進(jìn)入的順序流,然后再切分成多個(gè)并行分支。
與其他網(wǎng)關(guān)的主要區(qū)別是:并行網(wǎng)關(guān)不會(huì)解析條件,即使順序流中定義了條件,也會(huì)被忽略。
并行網(wǎng)關(guān)需要所有分支的全部運(yùn)行完了,才會(huì)匯聚,繼續(xù)向下執(zhí)行。
包含網(wǎng)關(guān)——InclusiveGateway
包含網(wǎng)關(guān)可以看成是排他網(wǎng)關(guān)和并行網(wǎng)關(guān)的結(jié)合體,和排他網(wǎng)關(guān)一樣,可以在外出順序流上定義條件,包含網(wǎng)關(guān)會(huì)解析它們,但是主要的區(qū)別是:包含網(wǎng)關(guān)可以選擇多于一條順序流,這和并行網(wǎng)關(guān)一樣。
包含網(wǎng)關(guān)的功能是基于進(jìn)入和外出順序流的。
分支:所有外出順序流的條件都會(huì)被解析,結(jié)果為true的順序流會(huì)以并行方式繼續(xù)執(zhí)行,會(huì)為每一個(gè)順序流創(chuàng)建一個(gè)分支。 匯聚:所有并行分支到達(dá)包含網(wǎng)關(guān),會(huì)進(jìn)入等待狀態(tài),直到每個(gè)包含流程token的進(jìn)入順序流的分支都到達(dá)。這是和并行網(wǎng)關(guān)最大的不同。
事件網(wǎng)關(guān)——EventGateway
Activiti和Spring的整合開(kāi)發(fā)
配置文件:
<?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">
<!--工作流引擎配置對(duì)象-->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!--數(shù)據(jù)源-->
<property name="dataSource" ref="dataSource"/>
<!--使用Spring的事務(wù)管理器-->
<property name="transactionManager" ref="transactionManager"/>
<!--
數(shù)據(jù)庫(kù)策略:
false:默認(rèn)值。activiti在啟動(dòng)時(shí),會(huì)對(duì)比數(shù)據(jù)庫(kù)表中保存的版本。如果沒(méi)有表或者版本不匹配,將拋出 異常。
true:activiti會(huì)對(duì)數(shù)據(jù)庫(kù)中所有表進(jìn)行更新操作,如果表不存在,則會(huì)自動(dòng)創(chuàng)建。
create_drop:在activiti啟動(dòng)時(shí)創(chuàng)建表,在關(guān)閉時(shí)刪除表(必須手動(dòng)關(guān)閉引擎,才能刪除表)。
drop-create:在activiti啟動(dòng)時(shí)刪除原來(lái)的舊表,然后再創(chuàng)建新表(不需要手動(dòng)關(guān)閉引擎)。
-->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
<!--配置數(shù)據(jù)源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/actspring"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="3"/>
<property name="maxIdle" value="1"/>
</bean>
<!-- 流程引擎對(duì)象 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
</bean>
<!--資源服務(wù)-->
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
<!--流程管理-->
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
<!--任務(wù)管理-->
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
<!--歷史管理-->
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
<!--事務(wù)管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--傳播行為-->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
Activiti和SpringBoot的整合開(kāi)發(fā)
配置文件:
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:默認(rèn)值。activiti在啟動(dòng)時(shí),會(huì)對(duì)比數(shù)據(jù)庫(kù)表中保存的版本。如果沒(méi)有表或者版本不匹配,將拋出異常
# true:activiti會(huì)對(duì)數(shù)據(jù)庫(kù)中所有表進(jìn)行更新操作,如果表不存在,則會(huì)自動(dòng)創(chuàng)建
# create_drop:在activiti啟動(dòng)時(shí)創(chuàng)建表,在關(guān)閉時(shí)刪除表(必須手動(dòng)關(guān)閉引擎,才能刪除表)
# drop-create:在activiti啟動(dòng)時(shí)刪除原來(lái)的舊表,然后再創(chuàng)建新表(不需要手動(dòng)關(guān)閉引擎)
# 線(xiàn)上一般使用false,開(kāi)發(fā)中使用true
database-schema-update: true
# 自動(dòng)部署驗(yàn)證設(shè)置:true-開(kāi)啟(默認(rèn))、false-關(guān)閉
check-process-definitions: false
# 開(kāi)啟歷史表
db-history-used: true
# 歷史記錄存儲(chǔ)等級(jí)
history-level: full
server:
port: 8082
