spring boot 整合 activiti 教程

Spring Boot整合Activiti指南

1、pom.xml

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.3.0</version> <!-- 选择与项目匹配的版本 -->
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

2、application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/activiti_db?useSSL=false&serverTimezone=UTC
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update # 可选:同步JPA实体与数据库表(非Activiti必需)
activiti:
  database-schema-update: true # 关键配置:自动创建/更新Activiti表
  async-executor-activate: true # 可选:启用异步执行器提升性能

3、

配置文件方式:通过XML配置自动建表​

对于习惯使用XML配置的项目,可通过activiti.cfg.xml文件定义流程引擎配置。

​步骤1:创建配置文件​
src/main/resources目录下创建activiti.cfg.xml,内容如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 配置流程引擎 -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 数据库连接 -->
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti_db?useSSL=false&serverTimezone=UTC"/>
        <property name="jdbcUsername" value="root"/>
        <property name="jdbcPassword" value="password"/>
        
        <!-- 自动建表策略(关键参数) -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>

步骤2:通过配置文件获取引擎​
在代码中加载配置文件,获取流程引擎:

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;

public class ActivitiXmlConfigExample {
    public static void main(String[] args) {
        // 加载activiti.cfg.xml配置文件
        ProcessEngineConfiguration config = ProcessEngineConfiguration
            .createProcessEngineConfigurationFromResource("activiti.cfg.xml");
        
        // 构建流程引擎(自动建表)
        ProcessEngine processEngine = config.buildProcessEngine();
        System.out.println("Activiti引擎启动成功,表已自动创建!");
    }
}

步骤3:验证表创建​
启动应用后,检查数据库中的ACT_前缀表是否存在

自动建表策略说明​

Activiti支持四种数据库表更新策略,通过databaseSchemaUpdate参数控制:

  • false(默认)​​:严格模式,启动时检查表是否存在及版本是否匹配。若无表或版本不符,抛出异常(适用于生产环境,避免意外修改表结构)。
  • true​:宽松模式,若表不存在则自动创建;若表存在但版本不符,自动更新表结构(适用于开发/测试环境,平衡灵活性与安全性)。
  • create-drop​:启动时创建表,应用关闭时删除表(需手动调用processEngine.close(),适用于临时测试场景)。
  • drop-create​:启动时删除旧表,再重新创建(无需手动关闭,适用于需要频繁重置表结构的场景)。
  • 常见问题排查​

•​​表未生成​​:检查数据库连接配置是否正确(如URL、用户名、密码)、依赖是否冲突(如Activiti版本与数据库驱动版本不兼容)、databaseSchemaUpdate参数是否设置为true

工作流.xml配置

leave-approval.bpmn20.xml

<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:activiti="http://activiti.org/bpmn"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             targetNamespace="http://www.activiti.org/test"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <process id="leaveApproval1" name="请假审批流程">
        <startEvent id="startEvent" name="开始"/>
        <userTask id="applyTask" name="填写申请" activiti:assignee="${employee}">
            <extensionElements>
                <activiti:formProperty id="days" name="请假天数" type="int" required="true"/>
                <activiti:formProperty id="reason" name="请假原因" type="string" required="true"/>
            </extensionElements>
        </userTask>
        <userTask id="managerApprove" name="经理审批" activiti:assignee="经理" >
        <extensionElements>
            <activiti:formProperty id="approved" name="审批标志" type="string" required="true"/>
            <activiti:formProperty id="comment" name="原因" type="string" required="true"/>
        </extensionElements>
        </userTask>
        <exclusiveGateway id="decision" name="审批决策" />
        <exclusiveGateway id="decisionGateway" name="天数判断"/>
        <userTask id="hrRecord" name="人事备案" activiti:assignee="人事"/>
        <endEvent id="endEvent" name="结束"/>
        <endEvent id="endRejected" name="审批不通过" />
        <sequenceFlow id="flow1" sourceRef="startEvent" targetRef="applyTask"/>
        <sequenceFlow id="flow2" sourceRef="applyTask" targetRef="managerApprove"/>
        <sequenceFlow id="flow3" sourceRef="managerApprove" targetRef="decision"/>
        <sequenceFlow id="flow4" sourceRef="decisionGateway" targetRef="hrRecord">
            <conditionExpression xsi:type="tFormalExpression">${days > 3}</conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow5" sourceRef="decisionGateway" targetRef="endEvent">
            <conditionExpression xsi:type="tFormalExpression">${days &gt;= 3}</conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="approvedFlow" sourceRef="decision" targetRef="decisionGateway">
            <conditionExpression xsi:type="tFormalExpression">${approved == true}</conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="rejectedFlow" sourceRef="decision" targetRef="endRejected">
            <conditionExpression xsi:type="tFormalExpression">${approved == false}</conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="flow6" sourceRef="hrRecord" targetRef="endEvent"/>
    </process>
</definitions>
工作流服务WorkflowService接口代码编写
@Service
public interface WorkflowService {
    String deployProcess();
    void startProcess(Leave leaveApplication);
    public List<Task> getPendingTasks(String assignee);
    public void completeTask(String taskId, Map<String, Object> variables);
}

工作流服务实现类

@Service
public class WorkflowServiceImpl implements WorkflowService {
    @Autowired
    private EntityManagerFactory entityManagerFactory;
    @Override
    public String deployProcess() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        Deployment deployment =  processEngine.getRepositoryService().createDeployment()
                .addClasspathResource("processes/leave-approval.bpmn20.xml") // 注意路径匹配实际存放位置
                .name("申请任务流程部署")
                .deploy();

        return null;
    }

    @Override
    public void startProcess(Leave leaveApplication) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        Map<String, Object> variables = new HashMap<>();
        variables.put("employee", leaveApplication.getEmployee());
        variables.put("days", leaveApplication.getDays());
        variables.put("reason", leaveApplication.getReason());
        RuntimeService runtimeService=processEngine.getRuntimeService();
        ProcessInstance processInstance= runtimeService.startProcessInstanceByKey("leaveApproval1", variables); // 通过流程Key启动
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        String sql = "SELECT  t.TASK_ID_  FROM  act_hi_actinst  t WHERE  ACT_ID_='applyTask' AND PROC_INST_ID_='"+ processInstance.getId()+"'";
        Query query = entityManager.createNativeQuery(sql);

// 执行查询并获取结果(Object类型需转换)
        Object result = query.getSingleResult();
        TaskService taskService= processEngine.getTaskService();
        taskService.complete( result.toString());

       System.out.println("processInstanceid111111111111:"+ processInstance.getId());
    }

    @Override
    public List<Task> getPendingTasks(String assignee) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService= processEngine.getTaskService();
        return taskService.createTaskQuery()
                .taskAssignee(assignee)  // 指定办理人
                .orderByTaskCreateTime().desc()  // 按创建时间倒序
                .list();
    }

    @Override
    public void completeTask(String taskId, Map<String, Object> variables) {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService= processEngine.getTaskService();
        variables.put("approved",false);
        taskService.complete(taskId, variables);
    }

需要注意的是如果有多个分支表达式中用到的逻辑变量 例如approved ,必须在任务的<extensionElements>标签下配置该属性

controller层代码编写

@RestController
public class WorkflowController {
    @Autowired
    private WorkflowService workflowService;

    /**
     * 启动请假流程
     */
    @PostMapping("/api/public/pending-tasks/{assignee}")
    public List<Map> getPendingTasks(@PathVariable String assignee) {
        List<Task> list=workflowService.getPendingTasks(assignee);
        List<Map> arraylist =new ArrayList<>();
        for (Task  task:list) {
            Map map=new HashMap();
            map.put("id",task.getId());
            map.put("name",task.getName());
            map.put("createtime",task.getCreateTime());
            arraylist.add(map);
        }
        return arraylist ;
    }
    @PostMapping("/api/public/deployProcess")
    public String deployProcess() {
        workflowService.deployProcess();
        return "Leave process started successfully!";
    }
    /**
     * 启动请假流程
     */

    @PostMapping("/api/public/start-leave")
    public String startLeave(@RequestBody Leave leave) {
        workflowService.startProcess(leave);
        return "Leave process started successfully!";
    }
    /**
     * 完成任务
     */
    @PostMapping("/api/public/complete-task/{taskId}")
    public String completeTask(@PathVariable String taskId, @RequestBody Map<String, Object> variables) {
        workflowService.completeTask(taskId, variables);
        return "Task completed successfully!";
    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值