跳转至

Flowable Java 深度解析:从基础到最佳实践

简介

Flowable 是一个轻量级、高性能的开源工作流和业务流程管理(BPM)平台,基于 Java 语言开发。它提供了丰富的 API 和工具,使得开发者可以方便地在 Java 应用中集成工作流功能。本文将详细介绍 Flowable Java 的基础概念、使用方法、常见实践以及最佳实践,帮助读者深入理解并高效使用 Flowable Java。

目录

  1. 基础概念
    • 工作流与 BPM
    • Flowable 架构
    • 核心组件
  2. 使用方法
    • 环境搭建
    • 流程定义
    • 流程实例启动
    • 任务处理
  3. 常见实践
    • 并行网关的使用
    • 边界事件的应用
    • 流程变量的管理
  4. 最佳实践
    • 代码结构优化
    • 性能调优
    • 错误处理与日志记录
  5. 小结
  6. 参考资料

基础概念

工作流与 BPM

工作流是指一系列相互关联的任务或活动,按照一定的规则和顺序执行,以实现特定的业务目标。业务流程管理(BPM)则是对业务流程进行建模、执行、监控和优化的方法论和技术。Flowable 作为 BPM 平台,提供了对工作流的全面支持。

Flowable 架构

Flowable 采用分层架构,主要包括引擎层、服务层和 API 层。引擎层负责流程的执行和管理,服务层提供了各种服务接口,API 层则允许开发者通过 Java 代码调用这些服务。

核心组件

  • Process Engine:流程引擎是 Flowable 的核心,负责管理流程定义、启动流程实例、处理任务等。
  • Repository Service:用于管理流程定义和部署,包括上传、查询和删除流程定义。
  • Runtime Service:用于启动流程实例、查询流程实例和执行流程中的活动。
  • Task Service:用于管理用户任务,包括查询、分配和完成任务。

使用方法

环境搭建

首先,需要在项目中添加 Flowable 的依赖。如果使用 Maven,可以在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-engine</artifactId>
    <version>6.7.2</version>
</dependency>

然后,创建流程引擎配置文件 flowable.cfg.xml

<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.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="jdbcUsername" value="sa" />
        <property name="jdbcPassword" value="" />
        <property name="jdbcDriver" value="org.h2.Driver" />
        <property name="databaseSchemaUpdate" value="true" />
    </bean>

    <bean id="processEngine" class="org.flowable.engine.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>
</beans>

最后,创建流程引擎:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;

public class FlowableExample {
    public static void main(String[] args) {
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
               .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000")
               .setJdbcUsername("sa")
               .setJdbcPassword("")
               .setJdbcDriver("org.h2.Driver")
               .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        ProcessEngine processEngine = cfg.buildProcessEngine();
    }
}

流程定义

流程定义使用 BPMN 2.0 标准进行建模,可以使用 Flowable Modeler 或其他 BPMN 建模工具创建流程定义文件(.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"
             targetNamespace="http://www.flowable.org/processdef">
    <process id="myProcess" name="My Process" isExecutable="true">
        <startEvent id="startEvent" />
        <userTask id="task1" name="Task 1" />
        <endEvent id="endEvent" />
        <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="task1" />
        <sequenceFlow id="flow2" sourceRef="task1" targetRef="endEvent" />
    </process>
</definitions>

将该文件部署到 Flowable 引擎中:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;

public class DeploymentExample {
    public static void main(String[] args) {
        ProcessEngine processEngine = ...; // 获取流程引擎
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
               .addClasspathResource("myProcess.bpmn20.xml")
               .deploy();
    }
}

流程实例启动

使用 RuntimeService 启动流程实例:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;

public class StartProcessInstanceExample {
    public static void main(String[] args) {
        ProcessEngine processEngine = ...; // 获取流程引擎
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");
    }
}

任务处理

使用 TaskService 处理用户任务:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;

import java.util.List;

public class TaskHandlingExample {
    public static void main(String[] args) {
        ProcessEngine processEngine = ...; // 获取流程引擎
        TaskService taskService = processEngine.getTaskService();
        List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
        for (Task task : tasks) {
            taskService.complete(task.getId());
        }
    }
}

常见实践

并行网关的使用

并行网关用于实现并行执行的流程分支。以下是一个使用并行网关的流程定义示例:

<process id="parallelProcess" name="Parallel Process" isExecutable="true">
    <startEvent id="startEvent" />
    <parallelGateway id="parallelGateway1" />
    <userTask id="task1" name="Task 1" />
    <userTask id="task2" name="Task 2" />
    <parallelGateway id="parallelGateway2" />
    <endEvent id="endEvent" />
    <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="parallelGateway1" />
    <sequenceFlow id="flow2" sourceRef="parallelGateway1" targetRef="task1" />
    <sequenceFlow id="flow3" sourceRef="parallelGateway1" targetRef="task2" />
    <sequenceFlow id="flow4" sourceRef="task1" targetRef="parallelGateway2" />
    <sequenceFlow id="flow5" sourceRef="task2" targetRef="parallelGateway2" />
    <sequenceFlow id="flow6" sourceRef="parallelGateway2" targetRef="endEvent" />
</process>

边界事件的应用

边界事件用于在特定事件发生时中断或触发流程中的活动。例如,使用定时器边界事件实现任务超时提醒:

<process id="timerBoundaryEventProcess" name="Timer Boundary Event Process" isExecutable="true">
    <startEvent id="startEvent" />
    <userTask id="task1" name="Task 1">
        <boundaryEvent id="timerBoundaryEvent" attachedToRef="task1">
            <timerEventDefinition>
                <timeDuration>PT5M</timeDuration>
            </timerEventDefinition>
        </boundaryEvent>
    </userTask>
    <userTask id="reminderTask" name="Reminder Task" />
    <endEvent id="endEvent" />
    <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="task1" />
    <sequenceFlow id="flow2" sourceRef="timerBoundaryEvent" targetRef="reminderTask" />
    <sequenceFlow id="flow3" sourceRef="task1" targetRef="endEvent" />
    <sequenceFlow id="flow4" sourceRef="reminderTask" targetRef="endEvent" />
</process>

流程变量的管理

流程变量用于在流程执行过程中传递数据。可以在启动流程实例时设置流程变量:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;

import java.util.HashMap;
import java.util.Map;

public class ProcessVariableExample {
    public static void main(String[] args) {
        ProcessEngine processEngine = ...; // 获取流程引擎
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> variables = new HashMap<>();
        variables.put("amount", 1000);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess", variables);
    }
}

在任务处理时获取和设置流程变量:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;

import java.util.Map;

public class TaskVariableExample {
    public static void main(String[] args) {
        ProcessEngine processEngine = ...; // 获取流程引擎
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().taskId("taskId").singleResult();
        Map<String, Object> variables = taskService.getVariables(task.getId());
        variables.put("status", "completed");
        taskService.setVariables(task.getId(), variables);
        taskService.complete(task.getId());
    }
}

最佳实践

代码结构优化

将流程相关的代码封装到独立的服务类中,提高代码的可维护性和可测试性。例如,创建一个 WorkflowService 类:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;

import java.util.List;
import java.util.Map;

public class WorkflowService {
    private final ProcessEngine processEngine;
    private final RuntimeService runtimeService;
    private final TaskService taskService;

    public WorkflowService(ProcessEngine processEngine) {
        this.processEngine = processEngine;
        this.runtimeService = processEngine.getRuntimeService();
        this.taskService = processEngine.getTaskService();
    }

    public ProcessInstance startProcessInstance(String processDefinitionKey, Map<String, Object> variables) {
        return runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
    }

    public List<Task> getTasksByAssignee(String assignee) {
        return taskService.createTaskQuery().taskAssignee(assignee).list();
    }

    public void completeTask(String taskId, Map<String, Object> variables) {
        taskService.setVariables(taskId, variables);
        taskService.complete(taskId);
    }
}

性能调优

  • 合理配置数据库连接池,避免频繁创建和销毁数据库连接。
  • 对流程定义进行缓存,减少部署和查询流程定义的开销。
  • 优化查询条件,避免全表扫描。

错误处理与日志记录

在流程执行过程中,可能会出现各种异常情况。可以使用 try-catch 块捕获异常,并记录详细的日志信息。例如:

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ErrorHandlingExample {
    private static final Logger logger = LoggerFactory.getLogger(ErrorHandlingExample.class);

    public static void main(String[] args) {
        ProcessEngine processEngine = ...; // 获取流程引擎
        RuntimeService runtimeService = processEngine.getRuntimeService();
        try {
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");
        } catch (Exception e) {
            logger.error("Failed to start process instance", e);
        }
    }
}

小结

本文详细介绍了 Flowable Java 的基础概念、使用方法、常见实践以及最佳实践。通过学习这些内容,读者可以在 Java 应用中高效地集成 Flowable 工作流功能,实现复杂的业务流程管理。

参考资料