Activiti工作流

1.簡(jiǎn)介

Activiti項(xiàng)目是一項(xiàng)新的基于Apache許可的開(kāi)源BPM平臺(tái),從基礎(chǔ)開(kāi)始構(gòu)建,旨在提供支持新的BPMN 2.0標(biāo)準(zhǔn)。

Activiti是一種輕量級(jí),可嵌入的BPM引擎,而且還設(shè)計(jì)適用于可擴(kuò)展的云架構(gòu)。 Activiti將提供寬松的Apache許可2.0,同時(shí)促進(jìn)Activiti BPM引擎和BPMN 2.0的匹配。

2.Activiti的7大服務(wù)

  • RepositoryService:提供一系列管理流程部署和流程定義的API。

  • RuntimeService:在流程運(yùn)行時(shí)對(duì)流程實(shí)例進(jìn)行管理與控制。

  • TaskService:對(duì)流程任務(wù)進(jìn)行管理,例如任務(wù)提醒、任務(wù)完成和創(chuàng)建任務(wù)等。

  • IdentityService:提供對(duì)流程角色數(shù)據(jù)進(jìn)行管理的API,這些角色數(shù)據(jù)包括用戶組、用戶及它們之間的關(guān)系。

  • ManagementService:提供對(duì)流程引擎進(jìn)行管理和維護(hù)的服務(wù)。

  • HistoryService:對(duì)流程的歷史數(shù)據(jù)進(jìn)行操作,包括查詢、刪除這些歷史數(shù)據(jù)。

  • FormService:表單服務(wù)。

3.應(yīng)用實(shí)例

3.1.開(kāi)發(fā)組件

名稱 版本
HighGoDB 安全版V4.5、企業(yè)版V5及以上
HgdbJdbc 6.2.4
JDK 1.6、1.7、1.8
Java IDE IntelliJ IDEA
SpringBoot 2.1.0.RELEASE
Activiti 7.0.0.Beta2

3.2.工程示例

image

3.3.主要文件

pom.xml

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring-boot-starter -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.highgo</groupId>
<artifactId>HgdbJdbc</artifactId>
<version>6.2.4</version>
</dependency>
</dependencies>

application.yml

spring:
datasource:
url: jdbc:highgo://xxxx:5866/activiti?currentSchema=activiti
username : sysdba
password : XXXX
driver-class-name: com.highgo.jdbc.Driver
activiti:
#1.flase:默認(rèn)值。activiti在啟動(dòng)時(shí),對(duì)比數(shù)據(jù)庫(kù)表中保存的版本,如果沒(méi)有表或者版本不匹配,將拋出異常
#2.true: activiti會(huì)對(duì)數(shù)據(jù)庫(kù)中所有表進(jìn)行更新操作。如果表不存在,則自動(dòng)創(chuàng)建
#3.create_drop: 在activiti啟動(dòng)時(shí)創(chuàng)建表,在關(guān)閉時(shí)刪除表(必須手動(dòng)關(guān)閉引擎,才能刪除表)
#4.drop-create: 在activiti啟動(dòng)時(shí)刪除原來(lái)的舊表,然后在創(chuàng)建新表(不需要手動(dòng)關(guān)閉引擎)
database-schema-update: true
#自動(dòng)部署驗(yàn)證設(shè)置:true-開(kāi)啟(默認(rèn))、false-關(guān)閉 true時(shí)項(xiàng)目啟動(dòng)會(huì)自動(dòng)部署
check-process-definitions: false
#注意,如果activiti后面加上了/,就要求啟動(dòng)的時(shí)候process文件夾中需要有流程定義文件
#是指定activiti流程描述文件的前綴(路徑),啟動(dòng)時(shí),activiti就會(huì)去尋找此路徑下的流程描述文件,并且自動(dòng)部署
process-definition-location-prefix: classpath:/processes/
# suffix 是一個(gè)String數(shù)組,表示描述文件的默認(rèn)后綴名,默認(rèn)**.bpmn和**.bpmn20.xml
# process-definition-location-suffixes:
# - **.bpmn
# - **.bpmn20.xml
# Activiti7歷史數(shù)據(jù)無(wú)法自動(dòng)插入,開(kāi)啟下面兩個(gè)配置
# 檢測(cè)歷史表是否存在 activiti7默認(rèn)沒(méi)有開(kāi)啟數(shù)據(jù)庫(kù)歷史記錄 啟動(dòng)數(shù)據(jù)庫(kù)歷史記錄
db-history-used: true
#記錄歷史等級(jí) 可配置的歷史級(jí)別有none, activity, audit, full
#none:不保存任何的歷史數(shù)據(jù),因此,在流程執(zhí)行過(guò)程中,這是最高效的。
#activity:級(jí)別高于none,保存流程實(shí)例與流程行為,其他數(shù)據(jù)不保存。
#audit:除activity級(jí)別會(huì)保存的數(shù)據(jù)外,還會(huì)保存全部的流程任務(wù)及其屬性。audit為history的默認(rèn)值。
#full:保存歷史數(shù)據(jù)的最高級(jí)別,除了會(huì)保存audit級(jí)別的數(shù)據(jù)外,還會(huì)保存其他全部流程相關(guān)的細(xì)節(jié)數(shù)據(jù),包括一些流程參數(shù)等。
history-level: full
# 解決頻繁查詢SQL問(wèn)題
async-executor-activate: false

leave.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: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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
<process id="leave" name="leave" isExecutable="true">
<startEvent id="sid-4bb1b894-4189-4443-9d51-08408088e392"/>
<userTask id="sid-76b385e0-c375-40af-afbe-9623fe40ee7f" name="部門經(jīng)理審批" activiti:assignee="${bm}"/>
<sequenceFlow id="sid-fbfc3fc7-99c7-46fd-9825-1f5d3fa6e82a" sourceRef="sid-4bb1b894-4189-4443-9d51-08408088e392" targetRef="sid-76b385e0-c375-40af-afbe-9623fe40ee7f"/>
<userTask id="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b" name="總經(jīng)理審批" activiti:assignee="${gm}"/>
<sequenceFlow id="sid-d37f31eb-c958-4c5e-a834-3c48191d1091" sourceRef="sid-76b385e0-c375-40af-afbe-9623fe40ee7f" targetRef="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b"/>
<endEvent id="sid-9e1a9189-9194-4a79-86ba-8dcbb2280e31"/>
<sequenceFlow id="sid-b945400f-4bae-4f2e-b6e1-0d2083d4b028" sourceRef="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b" targetRef="sid-9e1a9189-9194-4a79-86ba-8dcbb2280e31"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leave">
<bpmndi:BPMNPlane bpmnElement="leave" id="BPMNPlane_leave">
<bpmndi:BPMNShape id="shape-eaad1e5b-25df-445e-a846-7ed05e474f7e" bpmnElement="sid-4bb1b894-4189-4443-9d51-08408088e392">
<omgdc:Bounds x="-225.0" y="-60.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-990f85eb-2522-47cf-963d-0f16efbe9011" bpmnElement="sid-76b385e0-c375-40af-afbe-9623fe40ee7f">
<omgdc:Bounds x="-130.0" y="-85.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-b4d997db-6421-434c-b10f-285b7f28fc26" bpmnElement="sid-fbfc3fc7-99c7-46fd-9825-1f5d3fa6e82a">
<omgdi:waypoint x="-195.0" y="-45.0"/>
<omgdi:waypoint x="-130.0" y="-45.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="shape-b3139f61-0389-4cd6-ba9a-da6f41b22e9c" bpmnElement="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b">
<omgdc:Bounds x="40.0" y="-85.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-2676f501-c646-4be0-9f69-325b55e2384e" bpmnElement="sid-d37f31eb-c958-4c5e-a834-3c48191d1091">
<omgdi:waypoint x="-30.0" y="-45.0"/>
<omgdi:waypoint x="40.0" y="-45.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="shape-55c9ee0f-8507-449d-abf2-459285170784" bpmnElement="sid-9e1a9189-9194-4a79-86ba-8dcbb2280e31">
<omgdc:Bounds x="195.0" y="-60.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-ca8ae4f1-3bfd-4011-83e0-f864a8799213" bpmnElement="sid-b945400f-4bae-4f2e-b6e1-0d2083d4b028">
<omgdi:waypoint x="140.0" y="-45.0"/>
<omgdi:waypoint x="195.0" y="-45.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

3.4.流程部署

3.4.1.自動(dòng)部署

當(dāng) check-process-definitions:true 配置true時(shí)則為自動(dòng)部署,需要把流程文件放到/processes/文件夾下。

3.4.2.手動(dòng)部署
@Test
public void deployment(){
Deployment deployment = repositoryService.createDeployment()
.name("請(qǐng)假流程")
.addClasspathResource("processes/leave.bpmn20.xml")
.deploy();
System.out.println("流程ID:"+deployment.getId());
System.out.println("流程名稱:"+deployment.getName());
}

日志打印輸出

image

查看數(shù)據(jù)庫(kù)表act_ge_bytearray中會(huì)增加一條數(shù)據(jù),對(duì)應(yīng)的就是剛剛新增的流程。

image

查看act_re_deployment

image

查看act_re_procdef

image

3.5.開(kāi)啟流程

@Test
public void startProcess(){
String processDefinitionKey = "leave";
String businessKey = "001";
Map<String,Object> map = new HashMap<>();
map.put("bm","張三");
ProcessInstance leave = runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey, map);
System.out.println("流程id:"+leave.getProcessDefinitionId());
System.out.println("流程實(shí)例id:"+leave.getId());
System.out.println("當(dāng)前活動(dòng)id:"+leave.getActivityId());
}

日志打印

image

因?yàn)槭莿傞_(kāi)始流程,所以沒(méi)有人需要處理,當(dāng)前活動(dòng)id為null。這時(shí)查看act_hi_actinst就可以看到下一個(gè)需要處理的人。

image

3.6.查詢?nèi)蝿?wù)

@Test
public void findTask(){
List<Task> taskList = taskService.createTaskQuery()
//流程實(shí)例key
.processDefinitionKey("leave")
//任務(wù)負(fù)責(zé)人
.taskAssignee("張三")
.list();
for (Task task : taskList) {
System.out.println("任務(wù)id:"+task.getId());
System.out.println("任務(wù)名稱:"+task.getName());
System.out.println("任務(wù)負(fù)責(zé)人:"+task.getAssignee());
System.out.println("流程定義id:"+task.getProcessDefinitionId());
System.out.println("流程實(shí)例id:"+task.getProcessInstanceId());
System.out.println("任務(wù)創(chuàng)建時(shí)間:"+task.getCreateTime());
}
}

image

查詢的數(shù)據(jù)來(lái)自表act_ru_task,需要注意的是act_ru_task 表中的數(shù)據(jù)只有需要處理的任務(wù),一但任務(wù)完成,則會(huì)刪除已完成任務(wù)的數(shù)據(jù)。

image

3.7.處理任務(wù)

@Test
public void dealTask(){
Map<String,Object> map = new HashMap<>();
map.put("gm","李四");
Task task = taskService.createTaskQuery()
// 流程id
.processDefinitionKey("leave")
// 處理人
.taskAssignee("張三")
.singleResult();
taskService.complete(task.getId(),map);
System.out.println("處理任務(wù)id:"+task.getId());
}

act_hi_actinst表中,處理時(shí)間已填充,并且添加了一下個(gè)處理人

image

act_ru_task表,zhangsan的數(shù)據(jù)不再了,新增了李四的數(shù)據(jù)

image

3.8.完成任務(wù)

任務(wù)處理只需重復(fù)執(zhí)行上述方法即可,只是更改了任務(wù)的處理人,直至任務(wù)結(jié)束。

@Test
public void dealTask2() {
Task task = taskService.createTaskQuery()
// 流程id
.processDefinitionKey("leave")
// 處理人
.taskAssignee("李四")
.singleResult();
taskService.complete(task.getId());
System.out.println("處理任務(wù)id:"+task.getId());
}

3.9.獲取流程處理歷史

@Test
public void getHistoryList() {
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
.processDefinitionId("leave:1:0079b147-ed6c-11ee-a186-64bc58439558")
.list();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("開(kāi)始時(shí)間:" + historicTaskInstance.getStartTime());
System.out.println("流程名稱:" + historicTaskInstance.getName());
System.out.println("處理人名稱:" + historicTaskInstance.getAssignee());
System.out.println("結(jié)束時(shí)間:" + historicTaskInstance.getEndTime());
}
}

image