前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java&Activiti7实战:轻松构建你的第一个工作流

Java&Activiti7实战:轻松构建你的第一个工作流

原创
作者头像
JavaEdge
发布2025-04-23 10:35:07
发布2025-04-23 10:35:07
2521
举报
文章被收录于专栏:JavaEdgeJavaEdge

本文已收录在Github关注我,紧跟本系列专栏文章,咱们下篇再续!

  • 🚀 魔都架构师 | 全网30W技术追随者
  • 🔧 大厂分布式系统/数据中台实战专家
  • 🏆 主导交易系统百万级流量调优 & 车联网平台架构
  • 🧠 AIGC应用开发先行者 | 区块链落地实践者
  • 🌍 以技术驱动创新,我们的征途是改变世界!
  • 👉 实战干货:编程严选网

0 目标

Java项目集成 Activiti7 完成一个简单工作流。

1 添加依赖

添加Activiti7依赖:

代码语言:xml
复制
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M4</version>
</dependency>

<dependency>
    <groupId>org.activiti.dependencies</groupId>
    <artifactId>activiti-dependencies</artifactId>
    <version>7.1.0.M4</version>
    <type>pom</type>
</dependency>

2 Activiti7经典类

  • 任务处理Task
  • 历史任务HistoricTaskInstance:代表一个历史悠久的任务实例(等待,完成或删除),该实例被存储为统计,审计和其他商业智能目的的永久存储
  • 流程部署Deployment
  • 流程定义ProcessDefinition
  • 流程实例Processlnstance

3 流程部署Deployment

将工作流的定义文件(如BPMN文件、流程图等)发布到Activiti引擎中的过程,使流程定义能够被系统识别和使用。

3.1 作用

1. 流程定义管理的基础
代码语言:java
复制
@PostMapping(value = "/addDeploymentByString")
public AjaxResponse addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN) {
    try {
        Deployment deployment = repositoryService.createDeployment()
                .addString("CreateWithBPMNJS.bpmn", stringBPMN)
                .name("不知道在哪显示的部署名称")
                .deploy();
        return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                GlobalConfig.ResponseCode.SUCCESS.getDesc(), deployment.getId());
    } catch (Exception e) {
        // 异常处理
    }
}
2. 支持多种部署方式

从代码中可以看到项目支持多种部署方式:

  • BPMN文件部署
  • ZIP文件包部署
  • 字符串内容部署
  • 文件流部署

部署一个zip:

代码语言:java
复制
//通过ZIP部署流程
@Test
public void initDeploymentZIP() {
    InputStream fileInputStream = this.getClass()
            .getClassLoader()
            .getResourceAsStream("BPMN/Part1_DeploymentV2.zip");
    ZipInputStream zip = new ZipInputStream(fileInputStream);
    Deployment deployment = repoService.createDeployment()
            .addZipInputStream(zip)
            .name("流程部署测试zip")
            .deploy();
    System.out.println(deployment.getName());
}

最终生成的是什么呢?没错,zip 里的 两个文件,同属于一个部署:

3. 版本控制支持

每次部署会创建新的流程定义版本,项目中还通过SQL扩展了部署表:

代码语言:sql
复制
alter table ACT_RE_DEPLOYMENT add column PROJECT_RELEASE_VERSION_ varchar(255) DEFAULT NULL;
alter table ACT_RE_DEPLOYMENT add column VERSION_ varchar(255) DEFAULT NULL;
4. 部署与流程定义的关系

部署后会生成ProcessDefinition(流程定义),项目通过以下代码查询流程定义:

代码语言:java
复制
@GetMapping(value = "/getDefinitions")
public AjaxResponse getDefinitions() {
    try {
        List<HashMap<String, Object>> listMap = new ArrayList<>();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
        // 按版本排序
        list.sort((y,x)->x.getVersion()-y.getVersion());
        // 遍历处理流程定义
        // ...
    } catch (Exception e) {
        // 异常处理
    }
}
5. 部署管理功能

项目实现了部署的查询和删除功能:

代码语言:java
复制
@GetMapping(value = "/getDeployments")
public AjaxResponse getDeployments() {
    // 查询所有部署
}

@GetMapping(value = "/delDefinition")
public AjaxResponse delDefinition(@RequestParam("depID") String depID, @RequestParam("pdID") String pdID) {
    // 删除部署及相关数据
}

3.2 小结

在这个Activiti工作流项目中,Deployment是连接流程设计和流程执行的桥梁,是整个工作流系统的基础。通过部署操作,将流程定义文件转化为系统可识别和执行的流程定义对象,为后续的流程实例创建和任务执行提供必要条件。

先修改配置文件 application.yml 连接本地 MySQL,手动创建 activity 数据库。并确保已经运行过一次项目,让Activiti自动初始化必要的表结构:

代码语言:java
复制
// 通过bpmn部署流程
@Test
public void initDeploymentBPMN() {
    String filename = "BPMN/Part4_Task_claim.bpmn";
    Deployment deployment = repoService.createDeployment()
            .addClasspathResource(filename)
            .name("流程部署测试候选人task")
            .deploy();
    System.out.println(deployment.getName());
}

第一次启动项目,执行以上用例时,代码报错:

代码语言:java
复制
org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
### The error may exist in org/activiti/db/mapping/entity/Deployment.xml
### The error may involve org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl.insertDeployment-Inline
### The error occurred while setting parameters
### SQL: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_, VERSION_, PROJECT_RELEASE_VERSION_)     values(?, ?, ?, ?, ?, ?, ?, ?, ?)
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'

典型的Activiti 7 M4版本的已知Bug - 表结构定义中缺少字段导致的问题。根据错误信息,当尝试向ACTRE_DEPLOYMENT表插入数据时,系统找不到VERSION字段。执行项目根目录下的user.sql文件中的SQL语句即可。向ACT_RE_DEPLOYMENT表中添加Activiti 7 M4版本缺失的两个字段。重新执行该用例方法,运行成功!

3.3 ACT_RE_DEPLOYMENT表

属于Repository服务相关的表(RE前缀代表Repository)。

作用
  • 存储流程部署信息:记录所有通过API或工具部署到Activiti引擎的流程部署数据
  • 管理部署元数据:包含以下关键字段:
    • ID_:部署的唯一标识符
    • NAME_:部署名称
    • DEPLOYMENT_TIME:部署时间
    • KEY_:部署的键值
    • PROJECTRELEASE_VERSIO:项目发布版本
    • VERSION_:版本信息
  • 流程定义的容器:一个部署可包含多个流程定义(ProcessDefinition)

看表里创的数据:

3.4 ACT_GE_BYTEARRAY表

存储流程定义的二进制文件资源。

作用
  1. 存储流程定义资源
    • 存储BPMN XML文件内容
    • 存储流程图(PNG)文件
    • 存储ZIP归档中的资源文件
  2. 资源类型
    • 在你的Part1_Deployment.java测试类中,可以看到你通过.addClasspathResource().addZipInputStream()添加的资源都会被存储到这个
  3. 数据结构
    • ID_:主键
    • REV_:版本号
    • NAME_:资源名称
    • DEPLOYMENTID:部署ID,关联到ACT_RE_DEPLOYMENT表
    • BYTES_:二进制内容
    • GENERATED_:是否是自动生成的资源
表关联
  • ACT_RE_DEPLOYMENT表关联:每次部署创建的资源都会有一个对应的部署ID
  • ACT_RE_PROCDEF表关联:流程定义引用这些资源
实际应用场景

执行以下代码时:

代码语言:java
复制
Deployment deployment = repoService.createDeployment()
    .addClasspathResource(filename)
    .name("流程部署测试V1")
    .deploy();

底层会将该BPMN文件的内容读取并存储到ACT_GE_BYTEARRAY表,同时创建相应的部署记录和流程定义记录。

这种设计使得Activiti运行时直接从数据库获取流程定义,而无需每次从文件系统读取,提高执行效率和可靠性。

咋让别人看到你画的图?

同时生成一个图片即可。但其实.bpmn文件就能用bpmn.js插件渲染出来了。

代码语言:JAVA
复制
// 通过bpmn部署流程
@Test
public void initDeploymentBPMN() {
    String filename = "BPMN/Part4_Task_claim.bpmn";
     String pngname="BPMN/Part1_Deployment.png";
    Deployment deployment = repoService.createDeployment()
            .addClasspathResource(filename)
            .addClasspathResource(pngname)//图片
            .name("流程部署测试V1")
            .deploy();
    System.out.println(deployment.getName());
}

说明同属于一个部署:

4 流程定义ProcessDefinition

和 deploymentid 一对一:

$ ID_ = key + 部署次数版本 + id$

既不是因为表的字段太多,也不是因为一对多,就是设计成了一对一关系。

查询

代码语言:java
复制
@Test
public void getDefinitions() {
    List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
            .list();
    for (ProcessDefinition pd : list) {
        System.out.println("------流程定义--------");
        System.out.println("Name:" + pd.getName());
        System.out.println("Key:" + pd.getKey());
        System.out.println("ResourceName:" + pd.getResourceName());
        System.out.println("DeploymentId:" + pd.getDeploymentId());
        System.out.println("Version:" + pd.getVersion());
    }
}

删除

代码语言:java
复制
@Test
public void delDefinition() {

    String pdID = "44b15cfe-ce3e-11ea-92a3-dcfb4875e032";
    repositoryService.deleteDeployment(pdID, true);
    System.out.println("删除流程定义成功");
}
  • Deployment:添加资源文件、获取部署信息、部署时间
  • ProcessDefinition:获取版本号、 key、资源名称、部署ID等

5 流程实例ProcessInstance

ProcessDefinition与ProcessInstance是一对多关系,理解为:行动计划与具体行动的关系。

ProcessDefinition 是对业务流程的静态描述,定义了流程的结构、节点、连线和规则,相当于流程的"蓝图"。每个流程定义在部署后会有唯一标识,并支持版本控制。

作用

流程模型展示
  • 通过 getDefinitions() 方法查询所有流程定义,获取名称、键值、资源名等基本信息
  • ProcessInstanceController 中获取流程定义信息并返回给前端展示
流程部署管理
  • 流程定义与部署关联,每个 ProcessDefinition 对应一个 deploymentId
  • Part1_Deployment.java 中通过 BPMN 文件部署流程,生成流程定义
  • 支持删除操作,如 delDefinition() 方法中删除特定流程定义
流程实例创建的基础
  • ProcessInstanceController 中通过流程定义键(processDefinitionKey)启动流程实例
  • 流程实例是流程定义的运行时执行态,每个实例都基于特定的流程定义
版本管理
  • ProcessDefinitionController 中可以看到流程定义支持版本控制
  • 通过 list.sort((y,x)->x.getVersion()-y.getVersion()) 实现按版本排序
  • 同一个流程可以有多个版本的流程定义,最新版本用于启动新实例
流程资源关联
  • 流程定义关联了 BPMN 资源文件,通过 getResourceName() 可获取
  • 在项目中用于展示或下载流程图相关资源

示例

代码语言:java
复制
// 查询流程定义
@Test
public void getDefinitions() {
    List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
            .list();
    for (ProcessDefinition pd : list) {
        System.out.println("------流程定义--------");
        System.out.println("Name:" + pd.getName());
        System.out.println("Key:" + pd.getKey());
        System.out.println("ResourceName:" + pd.getResourceName());
        System.out.println("DeploymentId:" + pd.getDeploymentId());
        System.out.println("Version:" + pd.getVersion());
    }
}

综上所述,ProcessDefinition是连接流程设计、流程部署和流程执行的核心概念,为工作流的生命周期管理提供基础支持。

5.1 初始化

需要的就是一个流程的 key:

代码语言:java
复制
@Test
public void initProcessInstance(){
    // 1、获取页面表单填报的内容,请假时间,请假事由,String fromData
    // 2、fromData 写入业务表,返回业务表主键ID==businessKey
    // 3、把业务数据与Activiti7流程数据关联
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_claim","bKey002");
    System.out.println("流程实例ID:"+processInstance.getProcessDefinitionId());
}

5.2 获取列表

代码语言:java
复制
@Test
public void getProcessInstances(){
    List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
    for(ProcessInstance pi : list){
        System.out.println("--------流程实例------");
        System.out.println("ProcessInstanceId:"+pi.getProcessInstanceId());
        System.out.println("ProcessDefinitionId:"+pi.getProcessDefinitionId());
        System.out.println("isEnded"+pi.isEnded());
        System.out.println("isSuspended:"+pi.isSuspended());
    }
}

5.3 暂停与激活

代码语言:java
复制
@Test
public void activitieProcessInstance(){
    // runtimeService.suspendProcessInstanceById("73f0fb9a-ce5b-11ea-bf67-dcfb4875e032");
    //System.out.println("挂起流程实例");
    runtimeService.activateProcessInstanceById("73f0fb9a-ce5b-11ea-bf67-dcfb4875e032");
    System.out.println("激活流程实例");
}

5.4 删除

代码语言:java
复制
@Test
public void delProcessInstance(){
    runtimeService.deleteProcessInstance("73f0fb9a-ce5b-11ea-bf67-dcfb4875e032","删着玩");
    System.out.println("删除流程实例");
}

6 任务Task

代表流程执行过程中需要人工处理的环节。

6.0 作用

人工任务表示

Task接口用于表示需要人类用户执行的任务,Task接口定义:

代码语言:java
复制
public interface Task extends TaskInfo {
  // 任务相关属性和操作
}
任务管理功能

通过TaskServiceTaskRuntime提供多种任务操作:

  • 查询任务:获取所有任务或特定条件的任务
  • 拾取任务:用户认领待办任务
  • 完成任务:标记任务为已完成,推动流程继续执行
  • 分配任务:设置任务的执行人
  • 归还任务:将已认领的任务归还到候选人池
任务状态管理

Task具有多种状态,如代码中显示:

  • 待拾取状态
  • 已分配状态(assignee有具体用户)
  • 完成状态(通过complete方法标记)
  • 挂起状态(通过suspend方法实现)
任务权限控制

通过assignee和候选人组实现任务访问控制:

代码语言:java
复制
List<Task> list = taskService.createTaskQuery()
        .taskAssignee("bajie")
        .list();
前后端交互

项目中TaskController负责向前端提供任务相关API,如获取当前用户的代办任务:

代码语言:java
复制
@GetMapping(value = "/getTasks")
public AjaxResponse getTasks() {
    // 获取并返回任务列表
}

Task是Activiti工作流引擎中连接业务流程和实际操作人员的桥梁,通过它可以实现人工审批、处理等业务场景的工作流管理。

6.1 任务的类型

任务的图形化是以矩形为基础,在左侧添加具体的图标,用来描述一种特定任务类型。

用户任务需要人来参与,需要人为触发。

6.2 关键属性

关注用户任务:

  • Assignee:执行人/代理人
  • Candidate Users:候选人 谁先拾取任务,谁来执行任务
  • Candidate Groups:候选组
  • Due Date:任务到期时间

下面串起这些概念:

7 报销流程设计

7.1 bpmn设计

猪头三发起了报销请求:

JavaEdge 审核报销请求:

注意流程 id 名为:myProcess_Task,

7.2 bpmn部署

先bpmn部署该流程:

代码语言:java
复制
public void startDeploymentBPMN() {
    String filename = "BPMN/Part4_Task.bpmn";
    Deployment deployment = repoService.createDeployment()
            .addClasspathResource(filename)
            .name("Part4_Task")
            .deploy();
}

7.3 启动流程

再启动一个这样的流程实例:

代码语言:java
复制
public void initProcessInstance(){
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_Task","bKey002");
}

最后,我们来查询任务执行情况:

7.4 任务查询

代码语言:java
复制
@Test
public void getTasks(){
    List<Task> list = taskService.createTaskQuery().list();
    for(Task tk : list){
        System.out.println("Id:"+tk.getId());
        System.out.println("Name:"+tk.getName());
        System.out.println("Assignee:"+tk.getAssignee());
    }
}

output:
Id:9ec8d75e-9b86-11ef-8c93-a202cf5d45d9
Name:发起报销
Assignee:猪头三

该全量任务列表方法一般是由管理员查看任务执行情况。

查询我的代办任务
代码语言:java
复制
@Test
public void getTasksByAssignee(){
    List<Task> list = taskService.createTaskQuery()
            .taskAssignee("猪头三")
            .list();
    for(Task tk : list){
        System.out.println("Id:"+tk.getId());
        System.out.println("Name:"+tk.getName());
        System.out.println("Assignee:"+tk.getAssignee());
    }
}

output:
Id:9ec8d75e-9b86-11ef-8c93-a202cf5d45d9
Name:发起报销
Assignee:猪头三

配置流程引擎

创建一个 ProcessEngineConfiguration 实例来初始化流程引擎:

代码语言:java
复制
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;

public class ActivitiConfig {
    public static ProcessEngine buildProcessEngine() {
        ProcessEngineConfiguration config = ProcessEngineConfiguration
                .createStandaloneInMemProcessEngineConfiguration();
        config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        config.setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000");
        config.setJdbcDriver("org.h2.Driver");
        config.setJdbcUsername("sa");
        config.setJdbcPassword("");
        return config.buildProcessEngine();
    }
}

上面的代码创建了一个内存数据库中的流程引擎配置,这在开发和测试阶段非常便捷。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0 目标
  • 1 添加依赖
  • 2 Activiti7经典类
  • 3 流程部署Deployment
    • 3.1 作用
      • 1. 流程定义管理的基础
      • 2. 支持多种部署方式
      • 3. 版本控制支持
      • 4. 部署与流程定义的关系
      • 5. 部署管理功能
    • 3.2 小结
    • 3.3 ACT_RE_DEPLOYMENT表
      • 作用
    • 3.4 ACT_GE_BYTEARRAY表
      • 作用
      • 表关联
      • 实际应用场景
      • 咋让别人看到你画的图?
  • 4 流程定义ProcessDefinition
    • 查询
    • 删除
  • 5 流程实例ProcessInstance
    • 作用
      • 流程模型展示
      • 流程部署管理
      • 流程实例创建的基础
      • 版本管理
      • 流程资源关联
    • 示例
    • 5.1 初始化
    • 5.2 获取列表
    • 5.3 暂停与激活
    • 5.4 删除
  • 6 任务Task
    • 6.0 作用
      • 人工任务表示
      • 任务管理功能
      • 任务状态管理
      • 任务权限控制
      • 前后端交互
    • 6.1 任务的类型
    • 6.2 关键属性
  • 7 报销流程设计
    • 7.1 bpmn设计
    • 7.2 bpmn部署
    • 7.3 启动流程
    • 7.4 任务查询
      • 查询我的代办任务
  • 配置流程引擎
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档