首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Activiti 5.19 工作流開發實戰:從流程部署到任務辦理完整指南

     編輯:Java 綜合教學

Activiti 5.19 工作流開發實戰

Activiti 是輕量級 Java 工作流引擎,核心以 BPMN 2.0 為標準。本文基於 5.19 版本,通過一個「請假審批」流程實例,完整演示從流程定義部署、實例啟動、任務查詢與辦理、流程掛起/激活、查詢 API 使用、變量管理、表達式、單元測試到 Web 集成的全流程開發要點。

一、流程定義部署

流程定義以 BPMN 2.0 XML 形式存儲,部署後持久化至資料庫(ACT_RE_* 表),引擎重啟不丟失。使用 RepositoryService 部署:

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();

repositoryService.createDeployment()
    .addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
    .deploy();

System.out.println("流程定義數量: " + repositoryService.createProcessDefinitionQuery().count());

部署後,XML 被解析為可執行的 Java 對象模型,包含開始事件、用戶任務、排他網關、順序流等元素。

二、啟動流程實例

流程定義與實例是一對多、靜態與動態的關系。使用 RuntimeService 通過流程定義 Key 啟動,並攜帶初始流程變量:

Map variables = new HashMap<>();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", 4);
variables.put("vacationMotivation", "I'm really tired!");

RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);

System.out.println("流程實例 ID: " + processInstance.getId());
System.out.println("運行中實例數: " + runtimeService.createProcessInstanceQuery().count());

流程變量作用域覆蓋整個實例,也是任務間傳遞數據的橋樑。

三、任務查詢與辦理

流程啟動後,首個節點通常是用戶任務,需人工介入。使用 TaskService 查詢候選組任務:

TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery()
    .taskCandidateGroup("management")
    .list();

for (Task task : tasks) {
    System.out.println("待辦任務: " + task.getName() + " [ID: " + task.getId() + "]");
}

辦理任務時攜帶任務變量,驅動流程流轉(如審批通過/駁回):

Task task = tasks.get(0);
Map taskVars = new HashMap<>();
taskVars.put("vacationApproved", "false"); // 駁回
taskVars.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVars);

引擎根據排他網關條件表達式 ${vacationApproved == 'false'} 走向「修改請假單」節點,形成循環或結束。

四、流程掛起與激活

支持流程定義級和實例級掛起:

  • 定義級:repositoryService.suspendProcessDefinitionByKey("vacationRequest"),後續無法啟動新實例,拋 ActivitiException。激活用 activateProcessDefinitionByKey。
  • 實例級:runtimeService.suspendProcessInstance(instanceId),實例凍結,任務無法辦理。激活用 activateProcessInstance。

五、工作流查詢 API

Activiti 提供鏈式查詢 API,邏輯為 AND 組合:

List tasks = taskService.createTaskQuery()
    .taskAssignee("kermit")
    .processVariableValueEquals("orderId", "0815")
    .orderByDueDate().asc()
    .list();

複雜查詢(OR 條件、跨表)可用原生 SQL:

List tasks = taskService.createNativeTaskQuery()
    .sql("SELECT * FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAME_ = #{taskName}")
    .parameter("taskName", "gonzoTask")
    .list();

六、變量管理機制

變量分流程變量(實例級,存 ACT_RU_VARIABLE)和局部變量(執行/任務級,僅當前作用域可見)。

設置/獲取 API

  • RuntimeService:setVariable(s)、setVariableLocal(s)(局部)。
  • TaskService:getVariable(s)、getVariableLocal(s)、complete(taskId, variables) 會將任務變量合併到流程變量。
  • Execution/Task 對象直接調用 get/setVariable。

性能優化(5.17+)

默認獲取變量會一次性加載所有並緩存。大量變量場景可用新增參數控制:

execution.getVariable("myVar", false); // fetchAllVariables=false,僅查指定變量

七、統一表達式語言 (UEL)

支持值表達式 ${myVar}、${bean.prop} 和方法表達式 ${printer.print()}、${bean.addOrder('name')}。內置對象:execution、task、authenticatedUserId。廣泛用於網關條件、監聽器、腳本任務、表單屬性等。

八、單元測試最佳實踐

JUnit 4 + ActivitiRule(推薦):

public class VacationProcessTest {
    @Rule
    public ActivitiRule activitiRule = new ActivitiRule("activiti.cfg.xml");

    @Test
    @Deployment(resources = "vacation.bpmn20.xml")
    public void testRejectFlow() {
        RuntimeService rs = activitiRule.getRuntimeService();
        TaskService ts = activitiRule.getTaskService();

        Map vars = new HashMap<>();
        vars.put("employeeName", "test");
        vars.put("numberOfDays", 1);
        vars.put("vacationMotivation", "test");
        rs.startProcessInstanceByKey("vacationRequest", vars);

        Task task = ts.createTaskQuery().taskCandidateGroup("management").singleResult();
        assertNotNull(task);

        Map completeVars = new HashMap<>();
        completeVars.put("vacationApproved", "false");
        completeVars.put("managerMotivation", "busy");
        ts.complete(task.getId(), completeVars);

        // 驗證流程走向「修改請假單」
        Task adjustTask = ts.createTaskQuery().taskAssignee("test").singleResult();
        assertEquals("修改休假單", adjustTask.getName());
    }
}

@Deployment 自動部署同目錄下同名 .bpmn20.xml,測試結束自動清理數據。

九、Web 應用集成:Open Session in View

引擎線程安全,Web 環境需在啟動時創建、關閉時銷毀。配置 ServletContextListener:

public class ProcessEngineListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        ProcessEngines.init(); // 載入默認 activiti.cfg.xml
    }
    public void contextDestroyed(ServletContextEvent sce) {
        ProcessEngines.destroy();
    }
}

關鍵點:Service 層返回帶延遲加載關聯的實體給 Web 層時,需保證 Hibernate Session 仍開啟(或 Activiti 命令上下文未關閉),否則訪問關聯數據拋異常。可用過濾器在請求開始開啟命令上下文、請求結束關閉,實現「Open Session in View」模式。

總結

Activiti 核心服務(RepositoryService、RuntimeService、TaskService、HistoryService、ManagementService)覆蓋流程全生命周期。掌握流程變量作用域、查詢 API、表達式、測試框架與 Web 集成模式,即可構建健壯、可維護的業務流程系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved