Activiti7工作流學習筆記一
工作流(Workflow),就是“業務過程的部分或整體在計算機應用環境下的自動化”,它主要解決的是“使在多個參與者之間按照某種預定義的規則傳遞文檔、信息或任務的過程自動進行,從而實現某個預期的業務目標,或者促使此目標的實現”。
工作流管理系統(Workflow Management System, WfMS)是一個軟件系統,它完成工作量的定義和管理,並按照在系統中預先定義好的工作流規則進行工作流實例的執行。工作流管理系統不是企業的業務系統,而是爲企業的業務系統的運行提供了一個軟件的支撐環境。
工作流管理聯盟(WfMC,Workflow Management Coalition)給出的關於工作流管理系統的定義是:工作流管理系統是一個軟件系統,它通過執行經過計算的流程定義去支持一批專門設定的業務流程。工作流管理系統被用來定義、管理、和執行工作流程。
工作流管理系統的目標:管理工作的流程以確保工作在正確的時間被期望的人員所執行——在自動化進行的業務過程中插入人工的執行和干預。
Activiti原理分析
使用方式
- 定義工作流
使用eclipse插件完成,leaveProcess.bpmn(計算機進行流程的執行與信息的傳遞使用);leaveProcess.png用戶使用,查看流程的進度
使用https://demo.bpmn.io/,官方推薦 - 執行和管理工作流
調用Activiti的API
1. 流程部署
- 創建
processEngine
對象 - 得到
repositoryService
實例 - 進行部署
- 輸出部署的一些信息
表說明
表名 | 作用 |
---|---|
act_re_deployment | 流程定義部署表,記錄流程部署信息 |
act_re_procdef | 流程定義表,記錄流程定義信息 |
act_ge_bytearray | 資源表 |
說明:
act_re_deployment
和 act_re_procdef
一對多關係
- 一次部署在流程部署表生成一條記錄,但一次部署可以部署多個流程定義
- 每個流程定義在流程定義表生成一條記錄
- 每一個流程定義在
act_ge_bytearray
會存在兩個資源記錄,bpmn
和png
。
建議:一次部署一個流程,這樣部署表和流程定義表是一對一有關係,方便讀取流程部署及流程定義信息。
/**
* com.lxf.activiti
* 流程定義的部署
* act_re_deployment 部署信息
* act_re_procdef 流程定義的一些信息
* act_ge_bytearray 流程定義的bpmn文件及png文件
* @author lxf
* @version 1.0
* @date 2020/4/23 21:20
*/
public class ActivitiDeployment {
// 流程定義部署
public static void main(String[] args) {
// 1.創建processEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.得到repositoryService實例
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.進行部署
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.addClasspathResource("diagrams/holiday1.bpmn")
.addClasspathResource("diagrams/holiday.png")
.name("請假流程申請單");
Deployment deployment = deploymentBuilder.deploy();
// 4.輸出部署的一些信息
System.out.println(deployment.getName());
System.out.println(deployment.getId());
}
/**
* 壓縮形式部署
* 把bpmn,png文件製成zip類型的壓縮包
*/
public void deploymentZip(){
//1.創建ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService實例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.轉化出ZipInputStream流對象
InputStream is = ActivitiDeployment.class.getClassLoader().getResourceAsStream("diagrams/holidayBPMN.zip");
//將 inputstream流轉化爲ZipInputStream流
ZipInputStream zipInputStream = new ZipInputStream(is);
//3.進行部署
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.name("請假申請單流程")
.deploy();
//4.輸出部署的一些信息
System.out.println(deployment.getName());
System.out.println(deployment.getId());
}
}
2. 啓動流程實例
- 流程定義
bpmn文件
- 流程部署
activiti的三張表
- 流程實例
流程定義類似Java中的一個類
流程實例類似 Java中的一個實例(對象),一個流程定義可以對應多個流程實例
表說明
表名 | 作用 |
---|---|
act_hi_actinst | 已完成的活動信息 |
act_hi_identitylink | 參與者信息 |
act_hi_procinst | 流程實例 |
act_hi_taskinst | 任務實例 |
act_ru_execution | 執行表 |
act_ru_identitylink | 參與者信息 |
act_ru_task | 任務 |
/**
* 啓動流程實例:
* 前提是先已經完成流程定義的部署工作
*
* 背後影響的表:
* act_hi_actinst 已完成的活動信息
* act_hi_identitylink 參與者信息
* act_hi_procinst 流程實例
* act_hi_taskinst 任務實例
* act_ru_execution 執行表
* act_ru_identitylink 參與者信息
* act_ru_task 任務
*/
public class ActivitiStartInstance {
public static void main(String[] args) {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RunService對象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.創建流程實例 流程定義的key需要知道 holiday
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");
//4.輸出實例的相關信息
//null
System.out.println("流程部署ID->" + processInstance.getDeploymentId());
//holiday:1:5004
System.out.println("流程定義ID->" + processInstance.getProcessDefinitionId());
//10001
System.out.println("流程實例ID->" + processInstance.getId());
//null
System.out.println("活動ID->" + processInstance.getActivityId());
}
}
流程部署ID->null
流程定義ID->holiday:1:5004
流程實例ID->10001
活動ID->null
3. 查詢任務列表
/**
* 查詢當前用戶的任務列表
*/
public class ActivitiTaskQuery {
public static void main(String[] args) {
ActivitiTaskQuery taskQuery = new ActivitiTaskQuery();
taskQuery.taskQuery4ZhangSan();
}
/**
* wangwu完成自己任務列表的查詢
*/
public void taskQuery4WangWu() {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService對象
TaskService taskService = processEngine.getTaskService();
//3.根據流程定義的key,負責人assignee來實現當前用戶的任務列表查詢
Task task = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("wangwu")
.singleResult();
//4.任務列表的展示
printTaskInfo(task);
}
/**
* lishi完成自己任務列表的查詢
*/
public void taskQuery4LiShi() {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService對象
TaskService taskService = processEngine.getTaskService();
//3.根據流程定義的key,負責人assignee來實現當前用戶的任務列表查詢
Task task = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("lishi")
.singleResult();
//4.任務列表的展示
printTaskInfo(task);
}
/**
* zhangsan任務列表的查詢
*/
public void taskQuery4ZhangSan() {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService對象
TaskService taskService = processEngine.getTaskService();
//3.根據流程定義的key,負責人assignee來實現當前用戶的任務列表查詢
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("zhangsan")
.list();
//4.任務列表的展示
taskList.stream().forEach(this::printTaskInfo);
}
/**
* 輸出任務信息
*/
public void printTaskInfo(Task task) {
System.out.println("流程實例ID:" + task.getProcessInstanceId());
System.out.println("任務ID:" + task.getId());
System.out.println("任務負責人:" + task.getAssignee());
System.out.println("任務名稱:" + task.getName());
}
}
結果:
流程實例ID:10001
任務ID:10005
任務負責人:zhangsan
任務名稱:填寫請假申請單
流程實例ID:7501
任務ID:7505
任務負責人:zhangsan
任務名稱:填寫請假申請單
4. 處理當前用戶的任務
/**
* 處理當前用戶的任務 背後操作的表:
* act_hi_actinst
* act_hi_identitylink 記錄參與者
* act_hi_taskinst
* act_ru_identitylink
* act_ru_task 當前正要執行的任務,每次從流程圖中載入一個任務,當任務完成後刪除,最終爲空
*/
public class ActivitiCompleteTask {
public static void main(String[] args) {
ActivitiCompleteTask completeTask = new ActivitiCompleteTask();
completeTask.zhangSanComplete();
completeTask.complete("lishi");
completeTask.complete("wangwu");
}
/**
* zhangsan完成自己的任務
*/
public void zhangSanComplete() {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService對象
TaskService taskService = processEngine.getTaskService();
//3.處理任務,結合當前用戶任務列表的查詢操作的話,任務ID:10005
taskService.complete("10005");
}
/**
* 查詢當前用戶的任務並處理掉
*/
public void complete(String assignee) {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService對象
TaskService taskService = processEngine.getTaskService();
//3.查詢當前用戶的任務
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee(assignee)
.list();
taskList.stream().forEach(task -> {
//4.處理任務,結合當前用戶任務列表的查詢操作的話,任務ID:task.getId()
taskService.complete(task.getId());
//5.輸出任務的id
System.out.println(task.getId());
});
}
}
流程定義
查看流程定義信息
/**
* 操作一、查詢流程定義信息
*/
public void queryProcessDefinition() {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.創建RepositoryService對象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到ProcessDefinitionQuery對象,可以認爲它就是一個查詢器
ProcessDefinitionQuery processDefinitionQuery = repositoryService
.createProcessDefinitionQuery();
//4.設置條件,並查詢出當前的所有流程定義 查詢條件:流程定義的key=holiday
//orderByProcessDefinitionVersion() 設置排序方式,根據流程定義的版本號進行排序
List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday")
.orderByProcessDefinitionVersion()
.desc().list();
//5.輸出流程定義信息
list.forEach(this::printProcessDefinitionInfo);
}
/**
* 輸出流程定義信息
*/
public void printProcessDefinitionInfo(ProcessDefinition processDefinition) {
System.out.println("流程定義ID:" + processDefinition.getId());
System.out.println("流程定義名稱:" + processDefinition.getName());
System.out.println("流程定義的Key:" + processDefinition.getKey());
System.out.println("流程定義的版本號:" + processDefinition.getVersion());
System.out.println("流程部署的ID:" + processDefinition.getDeploymentId());
}
輸出
流程定義ID:holiday:1:5004
流程定義名稱:請假流程
流程定義的Key:holiday
流程定義的版本號:1
流程部署的ID:5001
刪除流程定義信息
/**
* 刪除流程定義信息
* 背後影響的表(與流程部署用到的一致):
* act_ge_bytearray
* act_re_deployment
* act_re_procdef
* 注意事項:
* 1.當我們正在執行的這一套流程沒有完全審批結束的時候,此時如果要刪除流程定義信息就會失敗
* 2.如果公司層面要強制刪除,可以使用repositoryService.deleteDeployment("1",true);
* 參數true代表級聯刪除,此時就會先刪除沒有完成的流程結點,最後就可以刪除流程定義信息
* false的值代表不級聯
* @param repositoryService
* @param deployId
*/
public void deleteDeployment(RepositoryService repositoryService,String deployId){
//6.執行刪除流程定義 參數代表流程部署的id
repositoryService.deleteDeployment(deployId);
}
流程定義資源查詢
需求:
- 從
Activiti
的act_ge_bytearray
表中讀取兩個資源文件 - 將兩個資源文件保存到路徑:
d:\resources
技術方案:
1.第一種方式使用actviti的api來實現
2.第二種方式:其實就是原理層面,可以使用jdbc的對blob類型,clob類型數據的讀取,並保存
IO流轉換,最好commons-io.jar包可以輕鬆解決IO操作
真實應用場景:用戶想查看這個請假流程具體有哪些步驟要走?
public void queryBpmnFile() throws IOException {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService對象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到查詢器:ProcessDefinitionQuery對象
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.設置查詢條件
processDefinitionQuery.processDefinitionKey("holiday");//參數是流程定義的key
//5.執行查詢操作,查詢出想要的流程定義
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
//6.通過流程定義信息,得到部署ID
String deploymentId = processDefinition.getDeploymentId();
//7.通過repositoryService的方法,實現讀取圖片信息及bpmn文件信息(輸入流)
//getResourceAsStream()方法的參數說明:第一個參數部署id,第二個參數代表資源名稱
//processDefinition.getDiagramResourceName() 代表獲取png圖片資源的名稱
//processDefinition.getResourceName()代表獲取bpmn文件的名稱
InputStream pngIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());
InputStream bpmnIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getResourceName());
//8.構建出OutputStream流
OutputStream pngOs =
new FileOutputStream("G:\\Activiti7開發計劃\\Activiti7-day03\\資料\\"+processDefinition.getDiagramResourceName());
OutputStream bpmnOs =
new FileOutputStream("G:\\Activiti7開發計劃\\Activiti7-day03\\資料\\"+processDefinition.getResourceName());
//9.輸入流,輸出流的轉換 commons-io-xx.jar中的方法
IOUtils.copy(pngIs,pngOs);
IOUtils.copy(bpmnIs,bpmnOs);
//10.關閉流
pngOs.close();
bpmnOs.close();
pngIs.close();
bpmnIs.close();
}
歷史數據的查看
/**
* com.lxf.activiti.ProcessDefinition
* 歷史數據的查看
* @author lxf
* @version 1.0
* @date 2020/4/25 19:30
*/
public class HistoryQuery {
public static void main(String[] args) throws IOException {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到HistoryService
HistoryService historyService = processEngine.getHistoryService();
//3.得到HistoricActivitiInstanceQuery對象
HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
//設置流程實例的id
historicActivityInstanceQuery.processInstanceId("2501");
//4.執行查詢
List<HistoricActivityInstance> list = historicActivityInstanceQuery
//排序StartTime
.orderByHistoricActivityInstanceStartTime().asc().list();
//5.遍歷查詢結果
list.forEach(instance->{
System.out.println(instance.getActivityId());
System.out.println(instance.getActivityName());
System.out.println(instance.getProcessDefinitionId());
System.out.println(instance.getProcessInstanceId());
System.out.println("=============================");
});
}
}
IDEA在快捷鍵
作用 | |
---|---|
Alt+ Insert |
IDEA maven項目pom文件插入依賴快捷鍵 |