activiti工作流
时间: 2025-06-03 17:00:29 浏览: 34
<think>嗯,用户这次明确询问Activiti工作流的使用教程和实现示例。从历史记录看,用户之前得到的回答主要集中在快速排序算法,但当前需求已经转向工作流引擎技术,需要完全调整知识范围。用户提供的站内引用很有价值。[^1]展示了SpringBoot+Vue+Activiti的全栈项目,包含在线编辑器、表单集成等关键功能;[^2]则聚焦于代码层面的配置和API调用。这两份材料恰好覆盖了从架构设计到具体实现的完整链路。用户可能是Java后端开发者,正在评估如何将Activiti集成到SpringBoot项目中。ta的提问方式("教程/示例")表明需要实操指导而非理论概念,且引用的资料里包含钉钉集成等企业级功能,暗示用户可能在开发商业OA系统。核心响应策略应分为三层:首先用最小化示例建立认知(配置文件+启动流程),再通过权限审批等高频场景深化理解,最后补充企业实践注意事项。特别注意要区分"基本用法"和"进阶技巧",因为用户引用[^1]提到的"驳回到任意节点"等属于高级特性。需要警惕两个技术细节:一是BPMN文件路径配置容易出错,二是SpringBoot版本与Activiti的兼容性。在代码示例中必须明确标注文件位置,并建议使用6.x以上Activiti版本。对于快速发起流程的两种方式(是否自动完成任务),用户引用[^2]的4.1/4.2章节已经给出模式,需强调事务管理的重要性。企业集成部分虽然用户未明说,但引用的钉钉通知功能值得展开。考虑到大多数企业需要审批提醒,准备补充NotificationListener的编写要点。审批环节的"或签"特性容易引发生产环境bug,将单列注意事项提醒。</think>
好的,了解!Activiti 是一个轻量级的 Java 工作流引擎,非常适合于 SpringBoot 集成。以下是一个结合你提供的引用信息和工作流核心概念的 **Activiti 7.x + SpringBoot 配置与基础实现教程/示例**,包含关键配置、核心流程操作和最佳实践提示。
---
### 一、核心依赖与配置
#### 1. Maven 依赖 (`pom.xml`)
集成 Activiti 7.x Spring Boot Starter。参考[^2]。
```xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Activiti 核心 Starter -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M6</version> <!-- 使用最新稳定版本 -->
</dependency>
<!-- (可选) Activiti 模型器 (在线流程图设计器) -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-cloud-modeling</artifactId>
<version>7.1.0.M6</version>
</dependency>
</dependencies>
```
#### 2. 数据库配置 (`application.properties`)
Activiti 需要数据库存储流程定义、实例、任务等数据。参考[^2]。
```properties
# 数据源配置 (示例使用 MySQL)
spring.datasource.url=jdbc:mysql://localhost:3306/activiti_db?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Activiti 表结构策略: update - 自动更新表结构; create-drop - 启动时创建,关闭时删除; validate - 仅校验
spring.activiti.database-schema-update=update
# 是否在启动时自动部署 classpath:processes/ 下的 BPMN 文件
spring.activiti.check-process-definitions=true
# 指定 BPMN 文件位置 (可选,默认也是 processes/)
spring.activiti.process-definition-location-prefix=classpath:/processes/
```
### 二、流程定义 (`BPMN 2.0` 文件)
1. 在 `src/main/resources/processes/` 下创建 BPMN 文件,如 `simple-approval.bpmn20.xml`。参考[^1][^2]。
2. 可以使用在线编辑器(如集成 `activiti-cloud-modeling`)、桌面工具 `Activiti Modeler` 或 IntelliJ IDEA 插件(推荐)绘制流程图。
3. **简单审批流程示例要素 (`simple-approval.bpmn20.xml`):**
* **启动事件 (`Start Event`):** 流程入口。
* **用户任务 (`User Task`):**
* `员工提交申请 (employeeSubmit)`:申请者任务。
* `主管审批 (managerApproval)`:主管审批任务。设置任务候选人/组(如 `activiti:candidateGroups="manager"`)
* `人事归档 (hrArchive)`:归档任务。
* **排他网关 (`Exclusive Gateway`):** 根据条件路由流程。
* **序列流 (`Sequence Flow`):** 连接节点,可设置条件表达式(如 `${approved == true}`)。
* **结束事件 (`End Event`):** 流程结束。
### 三、核心 Service 方法示例 (基于 Activiti `RuntimeService` & `TaskService`)
```java
@Service
public class ActivitiService {
@Autowired
private RuntimeService runtimeService; // 流程运行管理
@Autowired
private TaskService taskService; // 任务管理
@Autowired
private RepositoryService repositoryService; // 流程定义管理
/**
* 1. 启动流程实例 (不直接跳过第一个任务) - 参考[^2] 4.1
* @param processDefinitionKey 流程定义Key (BPMN中定义的)
* @param businessKey 关联的业务ID (例如: 请假单ID、报销单ID)
* @param variables 启动流程携带的变量
* @return 流程实例ID
*/
public String startProcessInstance(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
return instance.getId();
}
/**
* 2. 启动流程实例并自动完成第一个用户任务 (如提交申请) - 参考[^2] 4.2
* 适用场景:发起申请同时即完成提交操作。
* @param processDefinitionKey 流程定义Key
* @param businessKey 关联的业务ID
* @param variables 包含表单数据、审批人信息等
* @return 流程实例ID 和 后续任务的TaskId (通常是第一个审批节点)
*/
public Map<String, String> startAndSubmitFirstTask(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
// 启动流程,但不做提交(任务在第一个节点)
ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
// 获取当前任务(即第一个节点任务)
Task currentTask = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
// 带上变量完成该任务(模拟提交操作)
taskService.complete(currentTask.getId(), variables);
// 获取完成后可能的下一任务 (如审批任务)
List<Task> nextTasks = taskService.createTaskQuery().processInstanceId(instance.getId()).list();
Map<String, String> result = new HashMap<>();
result.put("processInstanceId", instance.getId());
if (!nextTasks.isEmpty()) { // 假设简单流程下一步是审批
result.put("nextTaskId", nextTasks.get(0).getId());
}
return result;
}
/**
* 3. 审批/完成任务 (核心:任务ID + 审批决定 + 审批意见 + 新变量) - 参考[^2] 4.3
* @param taskId 当前待完成任务的ID
* @param approveResult 审批结果 (e.g., "approved" / "rejected")
* @param comment 审批意见 (可选)
* @param newVariables 完成任务时传递的新变量 (如后续处理需要的数据)
*/
public void completeTask(String taskId, String approveResult, String comment, Map<String, Object> newVariables) {
if (newVariables == null) {
newVariables = new HashMap<>();
}
newVariables.put("approved", "approved".equals(approveResult)); // 设置流程变量
// 添加审批意见(可选)
if (StringUtils.isNotEmpty(comment)) {
taskService.addComment(taskId, null, comment); // 添加全局流程注释
}
// 完成任务, 携带新变量
taskService.complete(taskId, newVariables);
}
/**
* 4. 查询我发起的流程实例 - 参考[^2] 4.4
* @param userId 发起人ID
* @return 我发起的流程实例列表
*/
public List<HistoricProcessInstance> getMyStartedProcesses(String userId) {
return historyService.createHistoricProcessInstanceQuery()
.startedBy(userId)
.orderByProcessInstanceStartTime().desc()
.list();
}
/**
* 5. 查询我的待办任务 (根据候选人用户/组查询) - 参考[^2] 4.7
* @param userId 当前用户ID
* @param groupIds 当前用户所属的角色/组ID列表
* @return 我的待办任务列表
*/
public List<Task> getMyTodoTasks(String userId, List<String> groupIds) {
return taskService.createTaskQuery()
.taskCandidateOrAssigned(userId) // 既可以是候选人也可是签收人
.taskCandidateGroupIn(groupIds) // 候选组匹配
.orderByTaskCreateTime().desc()
.list();
}
}
```
### 四、Controller 示例
```java
@RestController
@RequestMapping("/process")
public class ProcessController {
@Autowired
private ActivitiService activitiService;
// 1. 发起一个请假申请流程 (启动并提交)
@PostMapping("/leave/start")
public Map<String, String> startLeaveProcess(@RequestParam String employeeId,
@RequestBody LeaveRequest leaveRequest) {
Map<String, Object> variables = new HashMap<>();
variables.put("leaveType", leaveRequest.getType());
variables.put("days", leaveRequest.getDays());
variables.put("reason", leaveRequest.getReason());
variables.put("submitter", employeeId); // 设置提交人
// 假设业务Key为"LEAVE_" + 时间戳 (实际应该用数据库生成的ID)
String businessKey = "LEAVE_" + System.currentTimeMillis();
return activitiService.startAndSubmitFirstTask("leave_process", businessKey, variables);
}
// 2. 处理审批任务
@PostMapping("/task/complete/{taskId}")
public void completeTask(@PathVariable String taskId,
@RequestParam String approvalResult,
@RequestParam(required = false) String comment) {
Map<String, Object> variables = new HashMap<>(); // 如果需要向下传递变量, 可以在这里添加
activitiService.completeTask(taskId, approvalResult, comment, variables);
}
// 3. 查看我的待办
@GetMapping("/my/tasks")
public List<Task> getMyTasks(@RequestParam String userId,
@RequestParam List<String> groupIds) { // 假设前端传递了用户的角色ID列表
return activitiService.getMyTodoTasks(userId, groupIds);
}
}
```
### 五、关键点与最佳实践
1. **业务 `Key` 关联:**
* 流程实例启动时务必通过 `businessKey` 参数关联具体的业务实体(如请假单ID、订单号)[^1]。
* 后续所有操作(查询、审批)都依赖这个关联。 `HistoricProcessInstance` 中的 `businessKey` 用于反向查找业务数据。
2. **流程变量 (`Variables`) 管理:**
* 启动时变量 (`startProcessInstanceByKey` 参数):传递表单数据、申请人等。
* 任务完成时变量 (`taskService.complete(taskId, variables)` 参数):传递审批结果、决定路由走向。
* 流程变量存储在 `ACT_RU_VARIABLE` / `ACT_HI_VARINST` 表中,谨慎传递大对象,通常只传递必要数据和业务ID。
3. **候选人(`Candidate`) vs 签收人(`Assignee`):**
* **候选用户/组 (`CandidateUser/CandidateGroup`):** 任务可以由列表中的任何人签收后处理(或签/会签)。`taskService.claim(taskId, userId)` 进行签收。
* **办理人 (`Assignee`):** 任务直接指定给具体的人处理。
* 建议在 BPMN 设计时使用候选组(如 `"manager"`),在 Service 方法中根据用户所属组进行查询[^1][^2]。签收操作通常在任务详情页处理。
4. **监听器 (`Listeners`):**
* **执行监听器/任务监听器 (`ExecutionListener/TaskListener`):** 用于自动化处理逻辑:
* 任务创建/完成时自动通知(如邮件、钉钉[^1])。
* 自动计算变量。
* 记录审计日志。
* **优点:** 解耦业务逻辑与流程处理主代码。
5. **异步处理 (`Async`):**
* Activiti 自动处理流程任务的异步执行(通过 `AsyncExecutor`)。
* 耗时操作(如生成报表、调用远程服务)应放在流程之外的异步服务中,以避免阻塞流程引擎线程。
6. **集成自定义表单:**
* 流程定义文件 (`BPMN`) 本身只描述任务节点和路由,不包含特定表单UI。
* 引用中的 **“工作流表单可平滑的接入自定义表单”** 指:
* 在任务节点关联一个表单定义ID `activiti:formKey="form-approve"`。
* 在应用中根据 `formKey` 动态渲染对应业务表单UI。表单提交数据就是 `completeTask` 的 `variables`。
* 表单设计器生成表单配置和动态渲染引擎是关键。这是 **“[^1]”** 项目的重点之一。
7. **高级流程控制:**
* **驳回到任意节点:** 使用 `runtimeService.createChangeActivityStateBuilder()` 接口实现流程跳转[^1]。
* **挂起/激活:** `runtimeService.suspendProcessInstanceById(processInstanceId)` / `runtimeService.activateProcessInstanceById(processInstanceId)`。
* **委托:** `taskService.delegateTask(taskId, newAssigneeUserId)`。
---
###
阅读全文
相关推荐











