在开始整合若依Vue前端与Activiti7工作流引擎之前,我们需要先搭建好基础开发环境。我建议使用JDK 1.8或更高版本,配合Maven 3.6+进行依赖管理。数据库方面,MySQL 5.7+是最佳选择,因为Activiti7对MySQL有很好的支持。
首先创建一个名为rouyi-activity的新模块,这个模块将作为工作流的核心承载模块。我在实际项目中发现,将工作流相关代码独立成模块是个好习惯,这样既能保持代码清晰,又方便后期维护。创建完模块后,需要在pom.xml中添加关键依赖:
xml复制<!-- Activiti核心依赖 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M6</version>
<exclusions>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 流程设计器依赖 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-modeler</artifactId>
<version>5.22.0</version>
</dependency>
<!-- 流程图生成工具 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
<version>5.22.0</version>
</dependency>
这里有个容易踩坑的地方:Activiti7自带的mybatis可能会与若依框架中的mybatis版本冲突,所以需要通过exclusions排除掉。我在三个不同项目中都遇到过这个问题,排除后就能完美解决。
完成基础依赖配置后,我们需要将新创建的rouyi-activity模块整合到若依主项目中。这一步很关键,直接关系到前后端能否正常协同工作。
首先在最外层的pom文件中添加模块依赖:
xml复制<!-- activiti模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-activiti</artifactId>
<version>${ruoyi.version}</version>
</dependency>
然后在ruoyi-admin模块的pom文件中同样需要引入这个依赖,但不需要指定版本号,因为版本号会从父pom继承:
xml复制<!-- activiti模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-activiti</artifactId>
</dependency>
我建议在项目结构上采用以下组织方式:
这种结构清晰明了,我在实际项目中验证过多次,特别适合中小型业务流程管理系统。
数据库配置是整合过程中最容易出问题的环节之一。我们需要修改application.yml文件来配置Activiti7:
yaml复制spring:
activiti:
# 数据库策略配置
database-schema-update: true
# 启用历史记录
db-history-used: true
# 历史记录级别配置
history-level: full
# 流程文件校验
check-process-definitions: false
main:
allow-bean-definition-overriding: true
这里有几个重要参数需要注意:
特别提醒:在application-druid.yml中,主库数据源URL需要添加&nullCatalogMeansCurrent=true参数:
yaml复制spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
master:
url: jdbc:mysql://localhost:3306/ruoyi-vue?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true
如果不加这个参数,启动时可能会报错。这个坑我踩过两次,最后在官方文档的角落里找到了解决方案。
现在我们来设计一个具体的业务流程,以请假审批为例。首先在resources/processes目录下创建leave-approval.bpmn20.xml文件:
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">
<process id="leaveApproval" name="请假审批流程">
<startEvent id="startEvent"/>
<userTask id="deptLeaderAudit" name="部门领导审批"/>
<userTask id="hrAudit" name="人事审批"/>
<endEvent id="endEvent"/>
<sequenceFlow sourceRef="startEvent" targetRef="deptLeaderAudit"/>
<sequenceFlow sourceRef="deptLeaderAudit" targetRef="hrAudit"/>
<sequenceFlow sourceRef="hrAudit" targetRef="endEvent"/>
</process>
</definitions>
前端整合方面,我们需要在若依Vue项目中添加工作流相关页面。建议在views目录下新建workflow文件夹,包含以下主要页面:
以task-list.vue为例,关键代码如下:
javascript复制export default {
data() {
return {
queryParams: {
pageNum: 1,
pageSize: 10,
taskName: undefined
},
taskList: []
}
},
created() {
this.getList()
},
methods: {
getList() {
listTask(this.queryParams).then(response => {
this.taskList = response.rows
})
},
handleTask(taskId) {
this.$router.push({ path: '/workflow/task-detail', query: { taskId } })
}
}
}
前后端交互主要通过RESTful API实现。我们需要在ruoyi-activiti模块中创建以下核心控制器:
java复制@RestController
@RequestMapping("/workflow")
public class WorkflowController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@GetMapping("/process/list")
public TableDataInfo listProcess() {
// 获取流程定义列表
}
@PostMapping("/process/start")
public AjaxResult startProcess(@RequestBody StartProcessVo vo) {
// 启动流程实例
}
@GetMapping("/task/list")
public TableDataInfo listTask(TaskQueryVo vo) {
// 获取待办任务列表
}
@PostMapping("/task/complete")
public AjaxResult completeTask(@RequestBody CompleteTaskVo vo) {
// 完成任务
}
}
前端调用API时需要注意以下几点:
我建议在API设计上遵循若依现有的风格,这样能保持项目的一致性。例如返回结果统一使用AjaxResult封装,分页查询使用TableDataInfo等。
完善的流程监控系统对于业务管理至关重要。我们可以利用Activiti7提供的API实现以下功能:
java复制public TableDataInfo listRunningProcess(ProcessQueryVo vo) {
List<ProcessInstance> instances = runtimeService.createProcessInstanceQuery()
.processDefinitionKey(vo.getProcessKey())
.active()
.listPage(vo.getPageNum(), vo.getPageSize());
// 转换为VO并返回
}
java复制public TableDataInfo listHistoryTask(HistoryTaskQueryVo vo) {
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
.taskAssignee(vo.getAssignee())
.finished()
.listPage(vo.getPageNum(), vo.getPageSize());
// 转换为VO并返回
}
java复制public void getProcessImage(String processInstanceId, HttpServletResponse response) {
InputStream imageStream = diagramGenerator.generateDiagram(processInstanceId);
// 将图片流写入response
}
在前端展示时,可以使用el-table组件展示列表数据,配合el-pagination实现分页。对于流程图,可以直接渲染返回的图片流。
在实际项目中,我总结了几个性能优化点和常见问题解决方案:
yaml复制spring:
datasource:
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
java复制@Transactional
public void completeTask(CompleteTaskVo vo) {
// 业务处理
taskService.complete(vo.getTaskId());
// 其他操作
}
特别提醒:Activiti的操作最好放在事务中执行,避免出现数据不一致的情况。我在一个项目中就遇到过因为没加事务导致流程状态异常的问题。