若依(RuoYi-Vue)+Flowable工作流前后端整合教程

'# 若依(RuoYi-Vue)+Flowable工作流前后端整合教程

一、背景与问题

在企业级应用开发中,工作流系统是核心组件之一。传统开发中,流程审批、业务规则等逻辑常通过自定义代码实现,导致代码冗余、维护困难。而Flowable作为轻量级工作流引擎,结合若依(RuoYi-Vue)框架,可以实现流程定义、流程实例管理、任务审批等完整功能。

在实际开发中,我们常遇到以下问题:

  1. 流程审批需要与现有业务系统深度集成
  2. 复杂审批流程需要动态条件判断
  3. 多角色参与的审批流程需要权限控制
  4. 需要与现有权限系统(如RBAC)对接

传统的解决方案需要开发人员手动编写大量业务逻辑代码,而通过Flowable与若依框架的整合,可以实现流程引擎与业务系统的无缝对接。

二、基本原理

Flowable工作流引擎包含以下核心组件:

  1. 流程定义(Process Definition):通过BPMN2.0定义的业务流程图
  2. 流程实例(Process Instance):运行中的具体流程实例
  3. 任务(Task):流程中的具体操作步骤
  4. 事件(Event):流程中的关键节点事件
  5. 任务参与者(Actor):流程中需要处理任务的用户角色

若依框架作为Spring Boot + Vue的前后端分离架构,通过REST API与Flowable进行交互。其整合方式主要包括:

  • 后端:Spring Boot集成Flowable,处理流程定义、启动流程、任务处理等
  • 前端:Vue组件与后端API对接,展示流程图、任务列表、审批表单等

三、环境准备

1. 技术栈要求

组件版本要求
Java17+
Spring Boot3.1.x
Flowable6.5.x
Vue3.x
Node.js16.x

2. 依赖配置

Spring Boot项目pom.xml中添加Flowable依赖:

<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.5.1</version>
</dependency>
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-engine</artifactId>
    <version>6.5.1</version>
</dependency>

Vue项目package.json中添加依赖:

{
  "dependencies": {
    "vue": "^3.2.15",
    "axios": "^1.5.1",
    "flowable-ui": "^1.0.0"
  }
}

四、核心实现

1. 流程定义接口

创建流程定义的REST接口,用于上传BPMN文件:

@RestController
@RequestMapping("/api/process")
public class ProcessController {

    @Autowired
    private RepositoryService repositoryService;

    @PostMapping("/define")
    public ResponseEntity<String> defineProcess(@RequestParam("file") MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            String processName = file.getOriginalFilename();
            String processKey = processName.substring(0, processName.lastIndexOf("."));
            
            // 上传流程定义文件
            repositoryService.createDeployment()
                .name(processName)
                .addClasspathResource("bpmn/" + file.getOriginalFilename())
                .deploy();
            
            return ResponseEntity.ok("流程定义成功");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("流程定义失败");
        }
    }
}

关键点说明:

  • 使用RepositoryService处理流程定义文件
  • 支持从classpath加载BPMN文件
  • 通过createDeployment()创建部署
  • 需要处理文件上传的异常情况

2. 流程启动接口

创建流程启动的REST接口,用于启动流程实例:

@RestController
@RequestMapping("/api/process")
public class ProcessController {

    @Autowired
    privateRuntimeService runtimeService;

    @PostMapping("/start")
    public ResponseEntity<String> startProcess(
        @RequestParam("processKey") String processKey,
        @RequestParam("businessKey") String businessKey,
        @RequestBody Map<String, Object> variables) {
        
        try {
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
                processKey, businessKey, variables);
            
            return ResponseEntity.ok("流程启动成功,实例ID: " + processInstance.getId());
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("流程启动失败");
        }
    }
}

关键点说明:

  • 使用RuntimeService启动流程实例
  • 支持传入业务参数(variables)
  • 需要处理流程Key不存在的异常

3. 任务处理接口

创建任务处理的REST接口,用于审批任务:

@RestController
@RequestMapping("/api/task")
public class TaskController {

    @Autowired
    private TaskService taskService;

    @PostMapping("/complete")
    public ResponseEntity<String> completeTask(
        @RequestParam("taskId") String taskId,
        @RequestParam("assignee") String assignee,
        @RequestBody Map<String, Object> variables) {
        
        try {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task == null) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body("任务不存在");
            }
            
            taskService.complete(taskId, variables);
            
            return ResponseEntity.ok("任务处理成功");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("任务处理失败");
        }
    }
}

关键点说明:

  • 使用TaskService处理任务
  • 需要验证任务是否存在
  • 支持传入处理变量(variables)
  • 需要处理任务处理失败的情况

五、完整案例

1. 请假流程案例

1.1 BPMN流程定义

创建一个简单的请假流程BPMN文件(leave.bpmn):

<definitions xmlns="http://www.omg.org/spec/DMN/20191215/MODEL" 
             xmlns:flowable="http://www.flowable.org/schema/bpmn20"
             targetNamespace="http://www.flowable.org/schema/bpmn20">
  
  <process id="leaveProcess" name="请假流程" isExecutable="true">
    <startEvent id="startEvent" name="提交申请" />
    <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="task1" />
    
    <userTask id="task1" name="审批" activiti:assignee="${assignee}" />
    <sequenceFlow id="flow2" sourceRef="task1" targetRef="endEvent" />
    
    <endEvent id="endEvent" name="流程结束" />
  </process>
</definitions>

1.2 后端实现

创建流程启动的REST接口:

@RestController
@RequestMapping("/api/process")
public class ProcessController {

    @Autowired
    privateRuntimeService runtimeService;

    @PostMapping("/start")
    public ResponseEntity<String> startProcess(
        @RequestParam("processKey") String processKey,
        @RequestParam("businessKey") String businessKey,
        @RequestParam("assignee") String assignee,
        @RequestBody Map<String, Object> variables) {
        
        try {
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
                processKey, businessKey, variables);
            
            return ResponseEntity.ok("流程启动成功,实例ID: " + processInstance.getId());
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("流程启动失败");
        }
    }
}

1.3 前端实现

创建任务列表组件(TaskList.vue):

<template>
  <div>
    <h2>待处理任务</h2>
    <ul>
      <li v-for="task in tasks" :key="task.id">
        <strong>{{ task.name }}</strong> - {{ task.assignee }}
        <button @click="completeTask(task.id, task.assignee)">处理</button>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tasks: []
    };
  },
  mounted() {
    this.fetchTasks();
  },
  methods: {
    async fetchTasks() {
      const response = await this.$axios.get('/api/task/list');
      this.tasks = response.data;
    },
    async completeTask(taskId, assignee) {
      const variables = {
        approvalResult: '通过'
      };
      const response = await this.$axios.post('/api/task/complete', {
        taskId,
        assignee,
        variables
      });
      alert(response.data);
      this.fetchTasks();
    }
  }
};
</script>

六、源码解析

1. 流程引擎初始化

在Spring Boot启动时,Flowable会自动加载配置:

@Configuration
@EnableFlowable
public class FlowableConfig {
    
    @Autowired
    private Environment env;
    
    @PostConstruct
    public void init() {
        // 配置数据库连接
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration()
            .setJdbcUrl(env.getProperty("spring.datasource.url"))
            .setJdbcUsername(env.getProperty("spring.datasource.username"))
            .setJdbcPassword(env.getProperty("spring.datasource.password"));
        
        // 初始化流程引擎
        ProcessEngine processEngine = configuration.buildProcessEngine();
    }
}

关键点说明:

  • 使用StandaloneProcessEngineConfiguration配置
  • 需要配置数据库连接参数
  • @EnableFlowable注解启用流程引擎

2. 流程实例处理

流程启动时的处理逻辑:

public ProcessInstance startProcessInstanceByKey(String processKey, String businessKey, Map<String, Object> variables) {
    // 验证流程定义是否存在
    if (!repositoryService.createProcessDefinitionQuery().processKey(processKey).count() > 0) {
        throw new IllegalArgumentException("流程定义不存在: " + processKey);
    }
    
    // 启动流程实例
    return runtimeService.startProcessInstanceByKey(processKey, businessKey, variables);
}

关键点说明:

  • 需要验证流程定义是否存在
  • businessKey用于关联业务数据
  • variables参数用于传递业务参数

七、进阶使用

1. 动态审批条件

使用Flowable的条件表达式实现动态审批:

<userTask id="task1" name="审批" flowable:conditionExpression="${approvalLevel == '部门'}" />
// 设置审批级别参数
Map<String, Object> variables = new HashMap<>();
variables.put("approvalLevel", "部门");

2. 事件监听器

添加事件监听器处理流程事件:

public class TaskCreateListener implements TaskCreateListener {
    
    @Override
    public void notify(DelegateTask delegateTask) {
        // 处理任务创建事件
        System.out.println("创建任务: " + delegateTask.getName());
    }
}
@Configuration
public class FlowableConfig {
    
    @Bean
    public TaskCreateListener taskCreateListener() {
        return new TaskCreateListener();
    }
}

3. 并行流程

使用并行网关实现并行审批:

<parallelGateway id="parallelGateway" />
<sequenceFlow id="flow1" sourceRef="parallelGateway" targetRef="task1" />
<sequenceFlow id="flow2" sourceRef="parallelGateway" targetRef="task2" />

八、性能与工程实践

1. 性能优化

  1. 数据库索引优化

    CREATE INDEX idx_process_definition_key ON act_re_procdef (process_definition_key_);
  2. 缓存流程定义

    @Cacheable("processDefinition")
    public ProcessDefinition getProcessDefinition(String processKey) {
        return repositoryService.createProcessDefinitionQuery().processKey(processKey).singleResult();
    }
  3. 流程实例清理

    @Scheduled(cron = "0 0 0 * * ?")
    public void cleanUpProcessInstances() {
        runtimeService.deleteProcessInstancesByProcessDefinitionKey("leaveProcess", true);
    }

2. 安全风险

  1. 未授权访问

    @PreAuthorize("hasRole('ROLE_ADMIN') or #taskId == authentication.name")
    public ResponseEntity<String> completeTask(...) {
        // ...
    }
  2. SQL注入防范

    String safeQuery = "SELECT * FROM act_ru_task WHERE task_id_ = '" + taskId + "'";

3. 异常处理

  1. 事务管理

    @Transactional
    public void startProcessInstance(...) {
        // ...
    }
  2. 异常日志记录

    try {
        // ...
    } catch (Exception e) {
        logger.error("流程处理异常", e);
        throw new RuntimeException("流程处理异常", e);
    }

九、常见问题与踩坑

1. 流程无法启动

原因:未正确配置数据库连接
解决:检查application.yml中数据库配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/flowable?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456

2. 任务处理失败

原因:未正确设置assignee
解决:确保在启动流程时传递assignee参数

3. 流程图显示异常

原因:未正确部署流程定义
解决:确保BPMN文件路径正确,使用createDeployment()方法部署

4. 性能瓶颈

原因:频繁查询流程定义
解决:使用缓存机制,如Redis缓存流程定义信息

十、最佳实践

1. 推荐方案

  • 使用Flowable的BPMN2.0标准定义流程
  • 与现有权限系统集成,实现角色绑定
  • 使用REST API实现前后端分离
  • 对关键流程添加事件监听器
  • 对高频流程启用缓存机制

2. 不推荐场景

  • 需要快速开发的简单审批流程(建议使用表单模板)
  • 对性能要求极高的场景(建议使用异步处理)
  • 需要实时处理的场景(建议使用消息队列)

十一、总结

通过将Flowable工作流引擎与若依(RuoYi-Vue)框架整合,可以构建出功能完善的业务流程管理系统。本文深入探讨了流程定义、流程实例、任务处理等核心机制,并提供了完整的代码示例和案例分析。在实际开发中,需要注意安全风险、性能优化和异常处理等问题。建议在需要复杂审批流程的业务场景中使用该方案,在简单流程或需要快速开发的场景中选择其他方案。通过合理的设计和实现,可以充分发挥Flowable和若依框架的优势,构建高效、可维护的业务流程管理系统。

VUE
最后修改于:2026年10月07日 21:22

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日