Activiti基本操作整理

一、Activiti介紹

Activiti項目是一項新的基於Apache許可的開源BPM平臺,從基礎開始構建,旨在提供支持新的BPMN 2.0標準,包括支持對象管理組(OMG),面對新技術的機遇,諸如互操作性和雲架構,提供技術實現。
Activiti是一個獨立運作和經營的開源項目品牌,並將獨立於Alfresco開源ECM(企業內容管理)系統運行。Activiti將是一種輕量級,可嵌入的BPM引擎,而且還設計適用於可擴展的雲架構。

官網給出的定義如下Activiti 是一個針對企業用戶、開發人員 、系統管理員的輕量級工作流業務管理平臺(Business Process Management, 簡稱BPM),其核心是使用 Java 開發的快速 、 穩定的 BPMN2.0 流程引擎 。Activiti是開源的,並基於Apache許可發行。Activiti可以在任何Java應用程序、服務器、集羣或雲中運行,它可以與 Spring 完美集成。
Activiti Github地址https://github.com/Activiti/Activiti

二、Activiti插件

Activiti要在Eclipse中使用,需要安裝如下插件
在這裏插入圖片描述
在這裏插入圖片描述

三、配置啓動流程

1.引入配置文件

Activiti自帶的表在實際開發中是使用activiti.cfg.xml配置文件生成,在src/test/resources下創建一個xml文件 名字是:activiti.cfg.xml

<?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">
  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti" />
    <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUsername" value="root" />
    <property name="jdbcPassword" value="123456" />
    <property name="databaseSchemaUpdate" value="true" />
  </bean>
</beans>

2.獲取流程引擎實例

/**
* 使用xml配置 簡化
*/
@Test
public void testCreateTableWithXml(){
    // 引擎配置
    ProcessEngineConfiguration pec=ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
    // 獲取流程引擎對象
    ProcessEngine processEngine=pec.buildProcessEngine();
}

流程引擎配置對象的繼承樹如下:
在這裏插入圖片描述
流程引擎對象默認使用h2內存數據庫
在這裏插入圖片描述
在創建完上面的流程引擎對象後,生成28張數據表
在這裏插入圖片描述
activiti5.19.0.2支持的是25張表
在這裏插入圖片描述

3.使用Eclipse繪製流程圖

在這裏插入圖片描述
啓動流程實例步驟分三步:
1.部署流程定義文件(涉及到資源表,流程部署記錄表,流程定義信息表)
2.啓動流程實例
3.查看流程任務以及完成流程任務

4.部署流程定義文件

public void deploy() {
	Deployment deployment = processEngine.getRepositoryService()
						.createDeployment()
						.addClasspathResource("diagrams/MyProcess.bpmn")
						.addClasspathResource("diagrams/MyProcess.png")
						.name("FirstApprove流程")
						.deploy();
	System.out.println("流程部署ID:"+deployment.getId());
	System.out.println("流程部署Name:"+deployment.getName());
}

部署完之後,三張表的變化
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

5.啓動流程實例

//啓動流程實例
@Test
public void start() {
    ProcessInstance processInstance =  processEngine.getRuntimeService().startProcessInstanceByKey(“myProcess”);//通過流程定義表中的key_字段獲取
    System.out.println("流程實例ID:"+processInstance.getId());
    System.out.println("流程定義ID:"+processInstance.getProcessDefinitionId());
}

表的變化:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

6.執行任務

@Test
public void completeTask(){
	processEngine.getTaskService() // 任務相關Service
             .complete("2505"); // 指定要完成的任務ID
}

表的變化
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在歷史表中,包括歷史參與者表、歷史任務表、歷史節點信息表,未完成的任務所涉及的參與者、節點信息都會記錄
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

7.查看任務

//查看任務
@Test
public void findTask(){
    // 查詢並且返回任務即可
    List<Task> taskList=processEngine.getTaskService() // 任務相關Service
            .createTaskQuery()  // 創建任務查詢
            .taskAssignee("李四") // 指定某個人
            .list();
    for(Task task:taskList){
        System.out.println("任務ID:"+task.getId());
        System.out.println("任務名稱:"+task.getName());
        System.out.println("任務創建時間:"+task.getCreateTime());
        System.out.println("任務委派人:"+task.getAssignee());
        System.out.println("流程實例ID:"+task.getProcessInstanceId());
    }
}

在這裏插入圖片描述
當完成最後一個人工任務後,所有的以act_run_開頭的表都置空,但能在歷史信息表中查看到相關信息
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

四、Activiti的實際應用

Activiti流程定義ZIP部署方式

Activiti支持以壓縮包的形式部署流程定義文件,從而擺脫通過classpath方式加載資源文件的侷限性。

/**
* 使用zip方式部署流程定義文件
*/
@Test
public void deployWithZip() {
	InputStream imInputStream = this.getClass().getClassLoader()
		.getResourceAsStream("diagrams/MyProcessZipTest.zip");//獲取指定文件資源流
	ZipInputStream zipInputStream = new ZipInputStream(imInputStream);//實例化zip輸入流
	Deployment deployment = processEngine.getRepositoryService()
		.createDeployment()
		.name("MyProcessZip部署")
		.addZipInputStream(zipInputStream)
		.deploy();
	System.out.println("流程部署ID:"+deployment.getId());
	System.out.println("流程部署Name:"+deployment.getName());
}

因爲MyProcessZipTest.zip壓縮包中含有兩個文件,bpmn和png,因此上傳到流程引擎中之後,在act_ge_bytearray中多了兩個資源文件,相應的數據表的變化:
在這裏插入圖片描述
在這裏插入圖片描述

Activiti流程定義查詢

  • 通過Activiti提供的API 把act_re_procdef表的所有列的數據全部查詢出來,在開發系統的時候管理員、用戶可以通過用戶界面來維護這些數據。
  • Activiti提供非常豐富的API,可以做SQL查詢、對某些字段查詢、模糊查詢、分頁查詢和排序等。
/**
* 查詢流程定義,返回流程定義集合
*/
@Test
public void ListAll() {
	List<ProcessDefinition> list = processEngine.getRepositoryService()
		.createProcessDefinitionQuery()//創建流程定義查詢
		.processDefinitionKey("myProcess")
		.list();
	for(ProcessDefinition pdf : list) {
	System.out.println("ID=" + pdf.getId());
	System.out.println("Name=" + pdf.getName());
	System.out.println("Key=" + pdf.getKey());
	System.out.println("Version" + pdf.getVersion());
	System.out.println("=================");
	}
}

在這裏插入圖片描述
activiti提供的流程定義查詢方法:
在這裏插入圖片描述

Activiti流程定義刪除

  • 在開發中肯定會有一些流程不需要了,要刪除,Activiti中也是存在刪除操作的
  • 通過流程定義部署ID來執行刪除流程定義
/**
* 刪除流程定義文件,通過流程定義部署ID來進行刪除
*/
@Test
public void deleteProdef() {
	processEngine.getRepositoryService().deleteDeployment("15001");
	System.out.println("刪除流程定義" );
}
/**
* 級聯刪除,正在運行的流程實例也會刪除,包括歷史記錄表中的信息也會被刪除
*/
@Test
public void deleteProdefForce() {
	processEngine.getRepositoryService().deleteDeployment("15001", true);//默認是False,true表示級聯刪除
	System.out.println("刪除流程定義成功" );
}

不能刪除正在運行的流程定義文件,有主外鍵關係
Cannot delete or update a parent row: a foreign key constraint fails (db_activiti.act_ru_execution, CONSTRAINT ACT_FK_EXE_PROCDEF FOREIGN KEY (PROC_DEF_ID_) REFERENCES act_re_procdef (ID_))

Activiti查看流程圖片

  • 在開發中可能需要查看某個流程的流程圖片,對應操作的數據庫表是act_ge_bytearray的Bytes_字段
  • Activiti提供了操作接口,可以查詢返回一個資源文件輸入流,然後就可以得到這張流程圖片保存到本地服務器,然後圖片多在自己的服務器上

需要commons-io依賴

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
ProcessEngine processEngine  =  ProcessEngines.getDefaultProcessEngine();
/**
* 通過流程部署ID獲得流程圖片
* @throws IOException
*/
@Test
public void getImageById() throws IOException {
	InputStream inputStream = processEngine.getRepositoryService().getResourceAsStream("1", "diagrams/MyProcess.png");
	FileUtils.copyInputStreamToFile(inputStream, new File("D:/MyProcess.png"));
}

在這裏插入圖片描述

Activiti修改流程定義

流程定義按本質來說是不能修改的。所以在開發中,不能修改流程定義,而是通過增加版本號的方式。來實現“修改”的。
在這裏插入圖片描述
每進行一次流程部署,version就會加1,啓動流程實例的時候,是用Key來啓動。這樣啓動的時候就是用的最新版本的流程定義來啓動流程實例。Id值組成是 key值:版本號:流程定義ID
在這裏插入圖片描述

Activiti刪除key相同的流程

一個流程定義不需要的,需要刪除所有版本
把所有Key相同的流程定義批量刪除
1、根據Key查詢所有的流程定義
2、遍歷集合,取得每個流程的部署ID
3、根據流程部署ID即可刪除所有的流程定義

public void deleteProdefBykeyForce() {
	List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("myProcess").list();
	for(ProcessDefinition pd : list) {
    System.out.println(pd.getDeploymentId());
    //processEngine.getRepositoryService().deleteDeployment(pd.getDeploymentId(), true);
    }
}

Activiti歷史流程操作

act_hi_procinst表的id和流程實例id始終是一樣的

/**
* 歷史流程實例相關信息查詢
* 根據流程實例ID進行查詢
*/
@Test
public void getHistoryProcessInstance() {
    HistoricProcessInstance historicProcessInstance = processEngine.getHistoryService().createHistoricProcessInstanceQuery().processInstanceId("2501").singleResult();
    System.out.println("=======歷史流程實例相關信息查詢===========");
    System.out.println("流程實例ID:"+ historicProcessInstance.getId());
    System.out.println("流程實例創建時間:"+ historicProcessInstance.getStartTime());
    System.out.println("流程實例結束時間:"+ historicProcessInstance.getEndTime());
}
/**
* 歷史任務實例相關信息查詢
* 查詢某個流程定義的所有歷史任務
*/
@Test
public void getHistoryTaskQuery() {
    List<HistoricTaskInstance> list = processEngine.getHistoryService().createHistoricTaskInstanceQuery().processDefinitionId("myProcess:1:4").finished().list();
    System.out.println("=======歷史任務實例相關信息查詢===========");
    for(HistoricTaskInstance his : list) {
        System.out.println("任務ID:" + his.getId());
        System.out.println("流程實例ID:" + his.getProcessInstanceId());
        System.out.println("辦理人:" + his.getAssignee());
        System.out.println("================");
    }
}

Activiti流程變量設置與獲取

根據流程定義的key啓動一個流程

@Test
public void start() {
    ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("employeeMyProcess");
    System.out.println("流程實例ID:" + processInstance.getId());
    System.out.println("流程實例創建時間:" + processInstance.getStartTime());
}

設置流程變量
要設置流程變量,需要獲取Service,在這裏,TaskService可以設置變量,RuntimeService也可以設置流程變量
假如節點不是任務節點的時候,只能用RuntimeService。接口和方法和TaskService一樣的;執行設置變量的方法會對應的把數據庫查詢到對應的流程變量表(act_ru_variable)中,當然那個序列化對象,特殊點,存到了字節文件表(act_ge_bytearray)裏去了

@Test
public void setProcVariable() {
    String taskId = "27505";
    Employee employee = new Employee(1526, "張三");
    TaskService taskService = processEngine.getTaskService();
    taskService.setVariable(taskId, "date", new Date());
    taskService.setVariable(taskId, "reason", "發燒");
    taskService.setVariable(taskId, "days", 2);
    taskService.setVariable(taskId, "employee", employee);//序列化對象
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
獲取“員工請假提交”任務節點設置的流程變量

@Test
public void getVariables() {
    TaskService taskService = processEngine.getTaskService();
    String taskId = "32502";
    Employee employee = (Employee) taskService.getVariable(taskId, "employee");
    Date date = (Date) taskService.getVariable(taskId, "date");
    String reason = (String) taskService.getVariable(taskId, "reason");
    Integer days = (Integer) taskService.getVariable(taskId, "days");
    System.out.println("請假人:" + employee);
    System.out.println("請假日期:" + date);
    System.out.println("請假原因" + reason);
    System.out.println("請假天數:" + days);
}

在這裏插入圖片描述

Activiti連線

在這裏插入圖片描述
完成任務

public class EmplyeeTest2 {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//部署流程
@Test
public void deploy() {
    Deployment deployment = processEngine.getRepositoryService()
        .createDeployment()
        .addClasspathResource("diagrams/employeeMyProcess2.bpmn")
        .addClasspathResource("diagrams/employeeMyProcess2.png")
        .name("員工請假流程2")
        .deploy();
    System.out.println("流程部署ID:"+deployment.getId());
    System.out.println("流程部署Name:"+deployment.getName());
}
//啓動一個流程實例
@Test
public void start() {
    ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("employeeMyProcess2");
    System.out.println("流程實例ID:" + processInstance.getId());
    System.out.println("流程定義ID:" + processInstance.getProcessDefinitionId());
    System.out.println("流程實例創建時間:" + processInstance.getStartTime());
}
//查看任務
@Test
public void findTask(){
    // 查詢並且返回任務即可
    List<Task> taskList=processEngine.getTaskService() // 任務相關Service
            .createTaskQuery()  // 創建任務查詢
            .taskAssignee("李四") // 指定某個人
            .list();
    for(Task task:taskList){
        System.out.println("任務ID:"+task.getId());
        System.out.println("任務名稱:"+task.getName());
        System.out.println("任務創建時間:"+task.getCreateTime());
        System.out.println("任務委派人:"+task.getAssignee());
        System.out.println("流程實例ID:"+task.getProcessInstanceId());
    }
}
//完成任務
@Test
public void completeTask() {
    processEngine.getTaskService().complete("42503");
}
@Test
public void completeTask2() {
    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("msg", "重要情況");
    processEngine.getTaskService().complete("40002", variables);
    }
}

Activiti排他網關

private static String completeTask(String taskID){
    String daysValue = "7";
    Map<String, Object> variables = new HashMap<>();
    variables.put("days",daysValue);
    processEngine.getTaskService().complete(taskID, variables);
    System.out.println("完成任務:" + taskID);
    System.out.println("下一任務:" + processEngine.getTaskService()
            .createTaskQuery().singleResult().getName());
    return processEngine.getTaskService().createTaskQuery().singleResult().getId();
}


private static void completeTask2(String taskID){
    System.out.println("當前任務:" + processEngine.getTaskService()
            .createTaskQuery().singleResult().getName());
    processEngine.getTaskService().complete(taskID);
    System.out.println("完成任務");
}

在這裏插入圖片描述

Activiti並行網關

private static void completeTask(String taskID){
    processEngine.getTaskService().complete(taskID);
    System.out.println("完成任務:" + taskID);
    List<Task> taskList = processEngine.getTaskService().createTaskQuery().list();
    for(Task task : taskList){
        System.out.println("任務名稱:" + task.getName());
        System.out.println("任務委任人:" + task.getAssignee());
        System.out.println("=================");
    }
}


private static void completeTask2(){
    List<Task> taskList = processEngine.getTaskService().createTaskQuery()
            .processInstanceId("90005").list();
    if (taskList.size()>0){
        for(Task task : taskList){
            System.out.println("任務名稱:" + task.getName());
            System.out.println("任務委任人:" + task.getAssignee());
            processEngine.getTaskService().complete(task.getId());
            System.out.println("完成任務:" + task.getName());
        }
    }
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章