自学内容网 自学内容网

Activiti 在 Springboot 中实现工作流管理(详解)

简介:

Activiti 是一个轻量级的开源工作流引擎,广泛用于 Java 应用中构建、执行和管理工作流。本文将通过一个简单的示例,展示如何在 Spring Boot 项目中集成 Activiti 工作流引擎,并使用 MySQL 作为数据库存储。

前言:

本文详细介绍了如何在 Spring Boot 项目中集成 Activiti 工作流引擎,并通过 MySQL 数据库进行工作流数据存储与管理。文章首先展示了如何配置必要的 Maven 依赖,接着详细讲解了如何定义 BPMN 流程文件,并通过 Java 服务类与前端接口实现工作流的启动、任务认领、任务完成等操作。此外,文章还提到了如何进行工作流的审计记录,创建相应的数据库表,并优化数据库性能。最后,文章提供了清理历史数据和管理工作流历史信息的最佳实践,帮助开发者在实际项目中高效地使用和管理 Activiti 工作流引擎。

1. 项目依赖配置

首先,我们需要在 pom.xml 文件中添加 Activiti 和 MySQL 的相关依赖。以下是 pom.xml 的依赖配置:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter for Activiti -->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring-boot-starter</artifactId>
        <version>7.1.0.M6</version>
    </dependency>

    <!-- Spring Boot Starter for Data JPA (用于数据库交互) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MySQL JDBC Driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- Spring Boot Starter Test (用于单元测试) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

2. 配置数据库和 Activiti 引擎

application.properties 文件中配置数据库连接(MySQL)和 Activiti 引擎参数。以下是配置示例:

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/activiti_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=update

# Activiti 配置
spring.activiti.database-schema-update=true
spring.activiti.enabled=true
spring.activiti.history-level=full

3. 创建工作流定义文件(BPMN)

Activiti 使用 BPMN 2.0 标准来定义工作流。我们可以创建一个简单的 BPMN 文件,定义一个包含用户任务的流程。

<?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"
             xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
    
    <process id="simpleProcess" name="Simple Process" isExecutable="true">
        <startEvent id="startEvent" name="Start"></startEvent>
        <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="userTask"></sequenceFlow>

        <userTask id="userTask" name="User Task" activiti:assignee="${assignee}">
            <documentation>Task for the user</documentation>
        </userTask>

        <sequenceFlow id="flow2" sourceRef="userTask" targetRef="endEvent"></sequenceFlow>
        
        <endEvent id="endEvent" name="End"></endEvent>
    </process>
</definitions>

这个文件定义了一个包含开始事件、用户任务和结束事件的简单流程。

4. 启动和管理工作流

在我们的服务类中,使用 TaskService 来启动流程、认领任务、完成任务等。下面是服务类的实现:

工作流服务类(WorkflowService.java
@Service
public class WorkflowService {

    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;

    // 启动流程实例
    public void startProcess(String assignee) {
        // 启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("simpleProcess");
        System.out.println("启动流程实例,ID: " + processInstance.getId());

        // 获取当前的任务
        Task task = taskService.createTaskQuery()
                               .processInstanceId(processInstance.getId())
                               .singleResult();
        // 认领任务
        taskService.claim(task.getId(), assignee);
        System.out.println("任务已由 " + assignee + " 认领");
    }

    // 完成任务
    public void completeTask(String taskId) {
        // 完成指定的任务
        taskService.complete(taskId);
        System.out.println("任务 ID " + taskId + " 已完成");
    }

    // 获取任务
    public Task getTaskById(String taskId) {
        // 获取指定任务的信息
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }
}

5. 关键方法详解

  1. taskService.claim(taskId, assignee)
    • 作用:此方法用于认领一个任务,通常用于分配任务给某个用户。
    • 参数
      • taskId:要认领的任务 ID。
      • assignee:任务认领者的用户账号 ID。
    • 说明:调用此方法后,当前用户成为任务的负责人,其他用户无法再认领该任务,直到任务完成或重新分配。
  2. taskService.complete(taskId)
    • 作用:此方法用于完成任务。
    • 参数
      • taskId:要完成的任务 ID。
    • 说明:调用此方法后,任务将被标记为已完成。完成任务后,工作流将继续执行,进入下一个任务或结束事件。
  3. taskService.createTaskQuery()
    • 作用:创建一个任务查询器,用于查询任务。
    • 返回值:返回一个 TaskQuery 对象,用于执行各种任务查询操作。
Task task = taskService.createTaskQuery()
                       .processInstanceId(processInstance.getId())
                       .singleResult();

在上述代码中,createTaskQuery() 用于获取与流程实例相关的任务,processInstanceId() 方法过滤出该流程实例的任务,singleResult() 返回第一个匹配的任务。

6. 控制器和前端交互

为了让用户能够通过 Web 接口与工作流交互,我们可以创建一个简单的控制器类来处理 HTTP 请求。

控制器类(WorkflowController.java
@RestController
public class WorkflowController {

    @Autowired
    private WorkflowService workflowService;

    // 启动工作流并认领任务
    @GetMapping("/startProcess")
    public String startProcess(@RequestParam String assignee) {
        workflowService.startProcess(assignee);
        return "流程启动并由 " + assignee + " 认领任务";
    }

    // 完成任务
    @GetMapping("/completeTask")
    public String completeTask(@RequestParam String taskId) {
        workflowService.completeTask(taskId);
        return "任务 ID " + taskId + " 已完成";
    }

    // 获取任务信息
    @GetMapping("/getTask")
    public String getTask(@RequestParam String taskId) {
        Task task = workflowService.getTaskById(taskId);
        return "任务信息:" + task.getName();
    }
}

然后,使用浏览器或 API 客户端(如 Postman)访问以下端点:

  • 启动工作流并认领任务:http://localhost:8080/startProcess?assignee=admin
  • 完成任务:http://localhost:8080/completeTask?taskId=1
  • 获取任务信息:http://localhost:8080/getTask?taskId=1

7. 工作流审计表(WorkflowAudit

7.1 创建 WorkflowAudit 表

假设你要记录以下信息:

  • task_id:任务的唯一标识
  • assignee:任务的处理人
  • status:任务状态(如:已完成、待处理等)
  • timestamp:任务处理时间

可以使用以下 SQL 语句创建表:

CREATE TABLE workflow_audit (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    task_id VARCHAR(255) NOT NULL,
    assignee VARCHAR(255),
    status VARCHAR(50),
    timestamp TIMESTAMP NOT NULL
);
7.2 Java 中插入数据

创建 WorkflowAudit 类,并通过 JPA 插入数据:

@Entity
public class WorkflowAudit {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String taskId;
    private String assignee;
    private String status;
    private Timestamp timestamp;

    // Getter 和 Setter
}

public void logAudit(String taskId, String assignee, String status) {
    WorkflowAudit audit = new WorkflowAudit();
    audit.setTaskId(taskId);
    audit.setAssignee(assignee);
    audit.setStatus(status);
    audit.setTimestamp(new Timestamp(System.currentTimeMillis()));

    workflowAuditRepository.save(audit);
}
7.3 性能优化
  • 数据库索引优化:为了加速任务查询,可以为 task_idassignee 字段创建索引:
CREATE INDEX idx_task_id ON workflow_audit(task_id);
CREATE INDEX idx_assignee ON workflow_audit(assignee);
  • 历史数据清理:根据工作流的使用量,ACT_HI_* 系列历史表可能会迅速增长,影响系统性能。为了避免数据表过大,可以定期清理历史数据或配置合适的历史数据保留策略。
# 仅保留必要的历史数据,避免全历史存储
spring.activiti.history-level=activity

8. Activiti 自带的表的创建与数据添加

Activiti 工作流引擎自带的一些表用于存储工作流实例、任务、执行记录等信息。你不需要手动创建这些表,Activiti 会根据配置和数据库自动创建这些表。以下是如何配置和向这些表添加数据的过程。

2.1 Activiti 数据库表

Activiti 需要一些预定义的数据库表来存储流程和任务信息。以下是 Activiti 工作流引擎通常会使用的一些表:

  • ACT_RU_TASK:当前任务表
  • ACT_RU_EXECUTION:执行表,存储正在进行的流程实例执行信息
  • ACT_HI_PROCINST:历史流程实例表,存储已结束的流程实例记录
  • ACT_HI_TASKINST:历史任务实例表,存储已完成的任务记录
  • ACT_ID_USER:用户表,存储用户信息

Activiti 会根据其启动时的配置自动创建这些表。默认情况下,如果你在使用 Activiti 时配置了数据库,它会自动执行 SQL 脚本来创建这些表。

例如,以下是ACT_RU_TASK表的结构:

CREATE TABLE act_ru_task (
    id_ VARCHAR(64) PRIMARY KEY,
    rev_ INT,
    name_ VARCHAR(255),
    assignee_ VARCHAR(255),
    create_time_ TIMESTAMP,
    due_date_ TIMESTAMP,
    category_ VARCHAR(255),
    process_instance_id_ VARCHAR(64),
    task_definition_key_ VARCHAR(255)
);
2.2 配置 Activiti 数据库连接

Activiti 中,你需要配置数据库连接,以确保工作流引擎能够与数据库进行交互。在 application.propertiesapplication.yml 配置文件中添加数据库连接信息。

示例(application.properties):

# Activiti 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/activiti?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update

Activiti 会根据这些配置自动创建数据库表(假设 ddl-auto 设置为update)。如果是第一次启动应用,Activiti 会执行预定义的 SQL 脚本来创建这些表。

2.3 向 Activiti 表插入数据

Activiti 的数据是通过流程引擎和任务服务来插入的。你不需要直接向这些表插入数据,而是通过使用 Activiti 的 API 进行操作。

启动流程实例并创建任务:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
TaskService taskService = processEngine.getTaskService();

// 启动一个流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");

// 获取并处理任务
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId()); // 完成任务

通过上面的代码,Activiti 会自动插入数据到相关表中,如 ACT_RU_TASK 表记录当前任务,ACT_HI_PROCINST 表记录流程实例。

2.4 查询 Activiti 表数据

你可以通过 Activiti 的 API 查询数据,也可以直接使用 SQL 语句访问这些表。例如:

Task task = taskService.createTaskQuery().taskAssignee("张三").singleResult();
System.out.println("Task ID: " + task.getId() + ", Task Name: " + task.getName());

这将查询 ACT_RU_TASK 表,返回当前分配给 “张三” 的任务。

2.5 注意:
  1. WorkflowAudit:需要手动创建数据库表并通过 Java 类(例如 JPA)来插入和管理数据。
  2. ActivitiActiviti 自动创建数据库表,通过其 API 来启动流程、创建任务、执行任务,并将数据自动插入到相应的表中。你只需配置数据库连接和流程定义。

原文地址:https://blog.csdn.net/xxiaobaibaibai/article/details/145203806

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!