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. 关键方法详解
- taskService.claim(taskId, assignee)
- 作用:此方法用于认领一个任务,通常用于分配任务给某个用户。
- 参数:
taskId
:要认领的任务 ID。assignee
:任务认领者的用户账号 ID。
- 说明:调用此方法后,当前用户成为任务的负责人,其他用户无法再认领该任务,直到任务完成或重新分配。
- taskService.complete(taskId)
- 作用:此方法用于完成任务。
- 参数:
taskId
:要完成的任务 ID。
- 说明:调用此方法后,任务将被标记为已完成。完成任务后,工作流将继续执行,进入下一个任务或结束事件。
- 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_id
和assignee
字段创建索引:
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.properties
或 application.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 注意:
WorkflowAudit
表:需要手动创建数据库表并通过Java
类(例如JPA
)来插入和管理数据。Activiti
表:Activiti
自动创建数据库表,通过其 API 来启动流程、创建任务、执行任务,并将数据自动插入到相应的表中。你只需配置数据库连接和流程定义。
原文地址:https://blog.csdn.net/xxiaobaibaibai/article/details/145203806
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!