关于springboot整合工作流的代码我也做了个整理下面是我git上的源码 在activiti下QingjiaController下面
https://gitee.com/mz5255/zg5.git
pom 依赖
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatis plus-->
<dependency>
<!--包米豆-->
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- mybatis -->
<!--<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>-->
<!-- 连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.16</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
java 原生 activiti
首先需要建一个工作流程图 如图所示
画好以后需要下载到这个文件夹
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 这里可以使用 链接池 dbcp-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///activiti" />
<property name="username" value="root" />
<property name="password" value="5255" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
</bean>
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 引用数据源 上面已经设置好了-->
<property name="dataSource" ref="dataSource" />
<!-- activiti 数据库表处理策略
false (默认):检查数据库表的版本和依赖库的版本, 如果版本不匹配就抛出异常。
true: 构建流程引擎时,执行检查,如果需要就执行更新。 如果表不存在,就创建。
create-drop: 构建流程引擎时创建数据库表, 关闭流程引擎时删除这些表。
drop-create:先删除表再创建表。
create: 构建流程引擎时创建数据库表, 关闭流程引擎时不删除这些表。
-->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
properties log日志 配置文件
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=C:\act\activiti.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
## 部署-流程定义
描述: 将定义好的流程加载到数据库中,便于后续使用
```java
package com.bw.activiti.demo;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
/**
* todo: 流程定义 部署
* 操作的数据库表:
* `act_re_procdef`: 存放流程定义数据
* `act_re_deployment`: 部署信息表
* `act_ge_bytearray`: 存储部署流程的xml文件和生成的图片信息
*/
public class Activiti1Deployment {
public static void main(String[] args) {
// 1.创建activiti引擎对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.获取流程部署对象 (将定义好的流程部署到仓库中)
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("activiti/holiday.bpmn20.xml") //添加bpmn资源
.addClasspathResource("activiti/holiday.png")
.name("请假申请单流程")
.deploy();
//4.输出部署的一些信息
System.out.println(deployment.getName());
System.out.println(deployment.getId());
}
}
```
## 查询-流程定义
描述: 从数据库中查询已经部署好的流程定义
```java
package com.bw.activiti.demo;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import java.util.List;
/**
* 查询流程定义信息
*/
public class Activiti2QueryProcessDefinition {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.创建RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.设置条件,并查询出当前的所有流程定义 查询条件:流程定义的key=holiday
//orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday")
.orderByProcessDefinitionVersion()
.desc().list();
//5.输出流程定义信息
for(ProcessDefinition processDefinition :list){
System.out.println("流程定义ID:"+processDefinition.getId());
System.out.println("流程定义名称:"+processDefinition.getName());
System.out.println("流程定义的Key:"+processDefinition.getKey());
System.out.println("流程定义的版本号:"+processDefinition.getVersion());
System.out.println("流程部署的ID:"+processDefinition.getDeploymentId());
}
}
}
```
## 删除-流程定义
描述: 根据流程定义ID删除部署的流程
```java
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
/**
* 删除已经部署的流程定义
*
* 背后影响的表:
* act_ge_bytearray
act_re_deployment
act_re_procdef
*/
public class Activiti3DeleteProcessDefinition {
/**
* 注意事项:
* 1.当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败
* 2.如果公司层面要强制删除,可以使用repositoryService.deleteDeployment("1",true);
* //参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息 false的值代表不级联
*
* @param args
*/
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.创建RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.执行删除流程定义 参数代表流程部署的id
repositoryService.deleteDeployment("1");
}
}
```
## 查询流程定义资源
描述: 查询定义当前流程时,参考的xml文件和bpmn文件(图片)
```java
package com.bw.activiti.demo2;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.apache.commons.io.IOUtils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 需求:
* 1.从Activiti的act_ge_bytearray表中读取两个资源文件
* 2.将两个资源文件保存到路径: G:\Activiti7开发计划\Activiti7-day03\资料
*
* 技术方案:
* 1.第一种方式使用actviti的api来实现
* 2.第二种方式:其实就是原理层面,可以使用jdbc的对blob类型,clob类型数据的读取,并保存
* IO流转换,最好commons-io.jar包可以轻松解决IO操作
*
* 真实应用场景:用户想查看这个请假流程具体有哪些步骤要走?
*
*
*/
public class Activiti4QueryBpmnFile {
public static void main(String[] args) throws IOException {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到查询器:ProcessDefinitionQuery对象
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.设置查询条件
processDefinitionQuery.processDefinitionKey("holiday");//参数是流程定义的key
//5.执行查询操作,查询出想要的流程定义
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
//6.通过流程定义信息,得到部署ID
String deploymentId = processDefinition.getDeploymentId();
//7.通过repositoryService的方法,实现读取图片信息及bpmn文件信息(输入流)
//getResourceAsStream()方法的参数说明:第一个参数部署id,第二个参数代表资源名称
//processDefinition.getDiagramResourceName() 代表获取png图片资源的名称
//processDefinition.getResourceName()代表获取bpmn文件的名称
InputStream pngIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());
InputStream bpmnIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getResourceName());
//8.构建出OutputStream流
OutputStream pngOs =
new FileOutputStream("F:\\img\\"+processDefinition.getDiagramResourceName());
OutputStream bpmnOs =
new FileOutputStream("F:\\img\\"+processDefinition.getResourceName());
//9.输入流,输出流的转换 commons-io-xx.jar中的方法
IOUtils.copy(pngIs,pngOs);
IOUtils.copy(bpmnIs,bpmnOs);
//10.关闭流
pngOs.close();
bpmnOs.close();
pngIs.close();
bpmnIs.close();
}
}
```
## 流程历史信息查看
即使流程定义已经删除了,流程执行的历史信息通过前面的分析,依然保存在 activiti 的 act_hi_*相关的表中。所以我们还是可以查询流程执行的历史信息,可以通过 HistoryService 来查看相关的历史记录
```java
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import java.io.IOException;
import java.util.List;
/**
* 需求:
* 历史数据的查看
*
*
*/
public class Activiti5HistoryQuery {
public static void main(String[] args) throws IOException {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到HistoryService
HistoryService historyService = processEngine.getHistoryService();
//3.得到HistoricActivitiInstanceQuery对象
HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
historicActivityInstanceQuery.processInstanceId("2501");//设置流程实例的id
//4.执行查询
List<HistoricActivityInstance> list = historicActivityInstanceQuery
.orderByHistoricActivityInstanceStartTime().asc().list();//排序StartTime
//5.遍历查询结果
for (HistoricActivityInstance instance :list){
System.out.println(instance.getActivityId());
System.out.println(instance.getActivityName());
System.out.println(instance.getProcessDefinitionId());
System.out.println(instance.getProcessInstanceId());
System.out.println("=============================");
}
}
}
```
# 第6章 Activiti-流程实例
## 启动流程实例
流程定义部署在 activiti后,就可以在系统中通过 activiti去管理该流程的执行,执行流程表示流程的一次执行。比如部署系统请假流程后,如果某用户要申请请假这时就需要执行这个流程,如果另外一个用户也要申请请假则也需要执行该流程,每个执行互不影响,每个执行是单独的流程实例。
```java
package com.bw.activiti.demo;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
/**
* todo: 根据流程定义信息创建实例
* 操作的表:
* 历史表:
* ACT_HI_TASKINST: 历史任务实例表
* ACT_HI_PROCINST: 历史流程实例表
* ACT_HI_ACTINST: 历史节点表
* ACT_HI_IDENTITYLINK: 历史流程人员表
* 运行表:
* ACT_RU_EXECUTION: 运行时流程执行实例
* ACT_RU_TASK: 运行时任务节点表
* ACT_RU_IDENTITYLINK: 允许时流程人员表,主要存储任务节点与参与者的相关信息
*/
public class Activiti1StartInstance {
public static void main(String[] args) {
// 1.创建activiti引擎对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RunService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.创建流程实例 流程定义的key需要知道 holiday
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");
//4.输出实例的相关信息
System.out.println("流程部署ID"+processInstance.getDeploymentId());//null
System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4
System.out.println("流程实例ID"+processInstance.getId());//2501
System.out.println("活动ID"+processInstance.getActivityId());//null
}
}
```
## 业务标识
启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey。
Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。
比如:请假流程启动一个流程实例,就可以将请假单的 id 作为业务标识存储到 activiti中,将来查询activiti的流程实例信息就可以获取请假单的 id 从而关联查询业务系统数据库得到请假单信息。
代码:
```java
// 根据流程定义的key启动一个流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,
businessKey);
```
Activiti中存储业务标识:
![image-20230504091358806](imgs/image-20230504091358806.png)
```java
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
/**
* 启动流程实例,添加进businessKey
* 本质:act_ru_execution表中的businessKey的字段要存入业务标识
*/
public class BusinessKeyAdd {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.启动流程实例,同时还要指定业务标识businessKey 它本身就是请假单的id
//第一个参数:是指流程定义key
//第二个参数:业务标识businessKey
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");
//4.输出processInstance相关的属性,取出businessKey使用:processInstance.getBusinessKey()
System.out.println(processInstance.getBusinessKey());
}
}
```
## 查询流程实例
流程在运行过程中可以查询流程实例的状态,当前运行结点等信息。
```java
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import java.util.List;
/**
* 查询流程定义信息
*/
public class QueryProcessDefinition {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.创建RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.设置条件,并查询出当前的所有流程定义 查询条件:流程定义的key=holiday
//orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday")
.orderByProcessDefinitionVersion()
.desc().list();
//5.输出流程定义信息
for(ProcessDefinition processDefinition :list){
System.out.println("流程定义ID:"+processDefinition.getId());
System.out.println("流程定义名称:"+processDefinition.getName());
System.out.println("流程定义的Key:"+processDefinition.getKey());
System.out.println("流程定义的版本号:"+processDefinition.getVersion());
System.out.println("流程部署的ID:"+processDefinition.getDeploymentId());
}
}
}
```
## 查询代办任务
```java
package com.bw.activiti;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
/**
* 查询当前用户的任务列表
*/
public class Activiti4TaskQuery {
//wangwu完成自己任务列表的查询
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
Task task = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("wangwu")
.singleResult();
//4.任务列表的展示
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("任务ID:"+task.getId()); //5002
System.out.println("任务负责人:"+task.getAssignee());
System.out.println("任务名称:"+task.getName());
}
//lishi完成自己任务列表的查询
/*public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
Task task = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("lishi")
.singleResult();
//4.任务列表的展示
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("任务ID:"+task.getId()); //5002
System.out.println("任务负责人:"+task.getAssignee());
System.out.println("任务名称:"+task.getName());
}
*/
//zhangsan任务列表的查询
/* public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("zhangsan")
.list();
//4.任务列表的展示
for(Task task :taskList){
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("任务ID:"+task.getId());
System.out.println("任务负责人:"+task.getAssignee());
System.out.println("任务名称:"+task.getName());
}
}*/
}
# 直击Activiti作用
```java
遇到了什么问题? 问题分析? 需求分析?
在工作生活中有很多流程化的业务,大多时候都是线下纸质版的传递与审核.
随着公司规模的扩张,流程化的业务,在线下进行时特别的繁琐.
请假:
开始 --> 学生填写请假单 --> 导员审核(签字) --> 存档 --> 结束
开始 --> 员工填写请假单 --> 部门领导审核 --> 项目经理审核 --> 总经理审批 --> 人事存档 --> 结束
看病:
开始 --> 挂号 --> 看病 --> 缴费 --> 取药 --> 结束
申请加薪:
开始 --> 员工填写涨薪申请单(1000) --> 部门经理 --> 财务审批 --> 结束
开始 --> 员工填写涨薪申请单(20000) --> 总经理 --> 财务审批 --> 结束
入职流程:
体检流程:
结婚流程:
点餐流程:
......
哪个技术可以解决这个问题? 技术的解决方案?
activiti: 工作流
这个技术如何使用?
```
# 第1章 工作流概述
## 1.1 工作流介绍
工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。
## 1.2 工作流系统
一个软件系统中具有工作流的功能,我们把它称为工作流系统,一个系统中工作流的功能是什么?就是对系统的业务流程进行自动化管理,所以工作流是建立在业务流程的基础上,所以一个软件的系统核心根本上还是系统的业务流程,工作流只是协助进行业务流程管理。即使没有工作流业务系统也可以开发运行,只不过有了工作流可以更好的管理业务流程,提高系统的可扩展性。
### 1.2.1 适用行业
消费品行业,制造业,电信服务业,银证险等金融服务业,物流服务业,物业服务业,物业管理,大中型进出口贸易公司,政府事业机构,研究院所及教育服务业等,特别是大的跨国企业和集团公司。
### 1.2.2 具体应用
1. 关键业务流程:订单、报价处理、合同审核、客户电话处理、供应链管理等
2. 行政管理类:出差申请、加班申请、请假申请、用车申请、各种办公用品申请、购买申请、日报
周报等凡是原来手工流转处理的行政表单。
3. 人事管理类:员工培训安排、绩效考评、职位变动处理、员工档案信息管理等。
4. 财务相关类:付款请求、应收款处理、日常报销处理、出差报销、预算和计划申请等。
5. 客户服务类:客户信息管理、客户投诉、请求处理、售后服务管理等。
6. 特殊服务类:ISO系列对应流程、质量管理对应流程、产品数据信息管理、贸易公司报关处理、物流公司货物跟踪处理等各种通过表单逐步手工流转完成的任务均可应用工作流软件自动规范地实施。
## 1.3 工作流实现方式
在没有专门的工作流引擎之前,我们之前为了实现流程控制,通常的做法就是采用状态字段的值来跟踪流程的变化情况。这样不用角色的用户,通过状态字段的取值来决定记录是否显示。
针对有权限可以查看的记录,当前用户根据自己的角色来决定审批是否合格的操作。如果合格将状态字段设置一个值,来代表合格;当然如果不合格也需要设置一个值来代表不合格的情况。
这是一种最为原始的方式。通过状态字段虽然做到了流程控制,但是当我们的流程发生变更的时候,这种方式所编写的代码也要进行调整。
那么有没有专业的方式来实现工作流的管理呢?并且可以做到业务流程变化之后,我们的程序可以不用改变,如果可以实现这样的效果,那么我们的业务系统的适应能力就得到了极大提升。
## 1.4 工作流实现原理分析
如何可以做到我们在业务流程发生变更后,我们的业务系统代码可以不发生改变?此时我们就来分析一下原理。
具体分析过程如下图所示:
![image-20230428112409185](imgs/image-20230428112409185.png)
# 第2章 Activiti7概述
## 2.1 Activiti 介绍
Alfresco 软件在 2010 年 5 月17 日宣布 Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理 BPM的专家 Tom Baeyens 担任,Tom Baeyens 就是原来 jbpm的架构师,而 jbpm 是一个非常有名的工作流引擎,当然 activiti也是一个工作流引擎。
Activiti 是一个工作流引擎, activiti 可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言(BPMN2.0)进行定义,业务系统按照预先定义的流程进行执行,实现了业务系统的业务流程由 activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
官方网站:https://www.activiti.org/
![image-20230427205741080](imgs/image-20230427205741080.png)
### 2.1.1 BPM
BPM(Business Process Management),即业务流程管理,是一种以规范化的构造端卓越业务流程为中心,以持续的提高组织业务绩效为目的系统化方法,常见商业管理教育如EMBA、MBA等均将 BPM 包含在内。
企业流程管理主要是对企业内部改革,改变企业职能管理机构重叠、中间层次多、流程不闭环等,做到机构不重叠、业务不重复,达到缩短流程周期、节约运作资本、提高企业效益的作用。
比较下边的两个人事加薪流程哪个效率更高?
流程一:
![image-20230427205831377](imgs/image-20230427205831377.png)
流程二:
![image-20230427205847283](imgs/image-20230427205847283.png)
上边两个流程的区别在于第二个流程在执行时,如果本次加薪金额在一万元以内不再由总经理审批将比第一个流程缩短流程周期,从而提交效率。
再比较下边的例子,哪个效率更高?
流程一:
![image-20230427205918737](imgs/image-20230427205918737.png)
流程二:
![image-20230427210014820](imgs/image-20230427210014820.png)
上边两个流程的区别在于第二个流程将交费和取药放在一起进行,这样导致的结果是此窗口的工作人员必须具备财务、药学专业知识,岗位强度加大,人员培训难度加大从而导致人员不易扩展,工作效率低下。
### 2.1.2 BPM 软件
BPM 软件就是根据企业中业务环境的变化,推进人与人之间、人与系统之间以及系统与系统之间的整合及调整的经营方法与解决方案的 IT 工具。 通常以 Internet方式实现信息传递、数据同步、业务监控和企业业务流程的持续升级优化,从而实现跨应用、跨部门、跨合作伙伴与客户的企业运作。通过 BPM 软件对企业内部及外部的业务流程的整个生命周期进行建模、自动化、管理监控和优化,使企业成本降低,利润得以大幅提升。
BPM 软件在企业中应用领域广泛,凡是有业务流程的地方都可以 BPM 软件进行管理,比如企业人事办公管理、采购流程管理、公文审批流程管理、财务管理等。
2.1.3 BPMN
BPMN(Business Process Model And Notation)- 业务流程模型和符号 是由 BPMI(Business Process Management Initiative)开发的一套标准的业务流程建模符号,使用 BPMN 提供的符号可以创建业务流程。 2004 年 5 月发布了 BPMN1.0 规范.BPMI 于 2005 年 9 月并入 OMG(The Object Management Group对象管理组织)组织。OMG 于 2011 年 1月发布BPMN2.0 的最终版本。
具体发展历史如下:
![image-20230427210132814](imgs/image-20230427210132814.png)
BPMN 是目前被各 BPM 厂商广泛接受的 BPM 标准。Activiti 就是使用 BPMN 2.0 进行流程建模、流程执行管理,它包括很多的建模符号,比如:
Event 用一个圆圈表示,它是流程中运行过程中发生的事情。
![image-20230427210155247](imgs/image-20230427210155247.png)
活动用圆角矩形表示,一个流程由一个活动或多个活动组成
![image-20230427210224688](imgs/image-20230427210224688.png)
一个 bpmn 图形的例子:
1. 首先当事人发起一个请假单;
2. 其次他所在部门的经理对请假单进行审核;
3. 然后人事经理进行复核并进行备案;
4. 最后请假流程结束。
![image-20230427210257093](imgs/image-20230427210257093.png)
Bpmn 图形其实是通过 xml表示业务流程,上边的.bpmn 文件使用文本编辑器打开:
```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"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://www.activiti.org/test">
<process id="myProcess" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name=" 创建请假单 "></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<userTask id="usertask2" name=" 部门经理审核 "></userTask>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<userTask id="usertask3" name=" 人事复核 "></userTask>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
<bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="130.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="210.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="360.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="510.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="660.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="165.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="210.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="315.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="360.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="465.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="510.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="615.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="660.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
```
## 2.2 Activiti 如何使用
### 1) 部署 activiti
Activiti是一个工作流引擎(其实就是一堆 jar 包 API),业务系统使用activiti来对系统的业务流程进行自动化管理,为了方便业务系统访问(操作)activiti 的接口或功能,通常将 activiti 环境与业务系统的环境集成在一起。
### 2) 流程定义
使用 activiti流程建模工具(activity-designer)定义业务流程(.bpmn文件) 。
.bpmn 文件就是业务流程定义文件,通过 xml定义业务流程。
如果使用其它公司开发的工作作引擎一般都提供了可视化的建模工具(Process Designer)用于生成流程定义文件,建模工具操作直观,一般都支持图形化拖拽方式、多窗口的用户界面、丰富的过程图形元素、过程元素拷贝、粘贴、删除等功能。
### 3) 流程定义部署
向 activiti部署业务流程定义(.bpmn文件)。
使用 activiti 提供的 api向 activiti 中部署.bpmn 文件(一般情况还需要一块儿部署业务流程的图片.png)
### 4) 启动一个流程实例(ProcessInstance )
启动一个流程实例表示开始一次业务流程的运行,比如员工请假流程部署完成,如果张三要请假就可以启动一个流程实例,如果李四要请假也启动一个流程实例,两个流程的执行互相不影响,就好比定义一个 java类,实例化两个对象一样,部署的流程就好比 java 类,启动一个流程实例就好比 new 一个 java 对象。
### 5) 用户查询待办任务(Task)
因为现在系统的业务流程已经交给 activiti管理,通过activiti就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些activiti帮我们管理了,而不像上边需要我们在sql语句中的where条件中指定当前查询的状态值是多少。
### 6) 用户办理任务
用户查询待办任务后,就可以办理某个任务,如果这个任务办理完成还需要其它用户办理,比如采购单创建后由部门经理审核,这个过程也是由 activiti帮我们完成了,不需要我们在代码中硬编码指定下一个任务办理人了
### 7) 流程结束
当任务办理完成没有下一个任务/结点了,这个流程实例就完成了。
# 第3章 activiti环境
## 3.1 activiti下载
Activiti下载地址:http://activiti.org/download.html
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>7.0.0.Beta1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
```
## 3.2 IDEA安装activiti插件
在 IDEA的 File 菜单中找到子菜单”Settings”,后面我们再选择左侧的“plugins”菜单,如下图所示:
## ![image-20230427211456964](imgs/image-20230427211456964.png)3.3 activiti 支持的数据库类型
![image-20230427211655444](imgs/image-20230427211655444.png)
## 3.4 创建 mysql 库
本教程使用mysql数据库。
创建 mysql数据库 activiti(名字任意):
```sql
CREATE DATABASE activiti DEFAULT CHARACTER SET utf8;
```
## 3.5 项目环境准备
### 创建maven的java项目
### 导入依赖
首先需要在 java 工程中加入ProcessEngine 所需要的 jar包,包括:
1) activiti-engine-7.0.0.beta1.jar
2) activiti依赖的 jar 包:mybatis、alf4j、log4j 等
3) activiti依赖的 spring包
4) 数据库驱动
5) 第三方数据连接池 dbcp druid
6) 单元测试 Junit-4.12.jar
我们使用 maven 来实现项目的构建,所以应当导入这些 jar所对应的坐标到pom.xml文件中。
```xml
<properties>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>alfresco</id>
<name>Activiti Releases</name>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
```
### 添加log4j.properties日志记录
```properties
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\activiti.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
```
### activiti.cfg.xml核心配置
```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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--数据源配置druid-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activiti" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!--
processEngineConfiguration 用来创建ProcessEngine,在创建ProcessEngine 时会执行数据库的操作。
activiti单独运行的ProcessEngine配置对象(processEngineConfiguration),使用单独启动方式
默认情况下:bean的id=processEngineConfiguration
-->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--代表数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--代表是否生成表结构-->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
```
关于 processEngineConfiguration 中的 databaseSchemaUpdate 参数,通过此参数设计 activiti数据表的处理策略,参数如下:
false(默认):检查数据库表的版本和依赖库的版本, 如果版本不匹配就抛出异常。
true: 构建流程引擎时,执行检查,如果需要就执行更新。 如果表不存在,就创建。
create-drop: 构建流程引擎时创建数据库表, 关闭流程引擎时删除这些表。
drop-create:先删除表再创建表。
create: 构建流程引擎时创建数据库表, 关闭流程引擎时不删除这些表。
### 生成数据库表
创建 ProcessEngineConfiguration,通过 ProcessEngineConfiguration 创建 ProcessEngine,在创建ProcessEngine 时会自动创建数据库。
```java
package com.bw.activiti;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.junit.Test;
/**
* 测试类
* 作用:测试activiti所需要的25张表的生成
*/
public class ActivitiTest {
@Test
public void testGenTable(){
//条件:
// 1.activiti配置文件名称:activiti.cfg.xml
// 2.bean的id="processEngineConfiguration"
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
// HistoryService historyService = processEngine.getHistoryService();
}
@Test
public void testGenTable2(){
//1.创建ProcessEngineConfiguration对象
// 第一个参数:配置文件名称
// 第二个参数是processEngineConfiguration的bean的id
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml","processEngineConfiguration01");
//2.创建ProcesEngine对象
ProcessEngine processEngine = configuration.buildProcessEngine();
//3.输出processEngine对象
System.out.println(processEngine);
}
}
```
![image-20230428084550914](imgs/image-20230428084550914.png)
### 数据库表介绍
Activiti 的表都以 ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的 API 对应。_
-
ACT_RE\_*: 'RE'表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
- ACT_RU\_*: 'RU'表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
- ACT_HI\_*: 'HI'表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
- AC T_GE_*: GE表示 general。通用数据, 用于不同场景下。
# 第4章 Activiti服务架构
## 4.1 内部对象结构图
![image-20230428085052122](imgs/image-20230428085052122.png)
![image-20230428085341506](imgs/image-20230428085341506.png)
在新版本中,我们通过实验可以发现 IdentityService,FormService 两个Serivce 都已经删除了。所以后面我们对于这两个 Service 也不讲解了,但老版本中还是有这两个 Service,同学们需要了解一下。
## 4.2 核心对象的创建方式
### ProcessEngine对象
方式1
```java
//1.解析配置文件,创建ProcessEngineConfiguration对象
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml","processEngineConfiguration01");
//2.调用ProcessEngineConfiguration对象的buildProcessEngine方法,创建ProcesEngine对象
ProcessEngine processEngine = configuration.buildProcessEngine();
```
方式2:
```java
// 通过ProcessEngines对象的getDefaultProcessEngine方法创建
//条件:
// 1.activiti配置文件名称:activiti.cfg.xml
// 2.bean的id="processEngineConfiguration"
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
```
### 其他Service的创建方式
```java
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
processEngine.getXxxService();
```
![image-20230428090123352](imgs/image-20230428090123352.png)
### service对象总览
| 对象名称 | 作用 |
| --------------------- | ------------------------- |
| **RepositoryService** | activiti 的资源管理类 |
| **RuntimeService** | activiti 的流程运行管理类 |
| **TaskService** | activiti 的任务管理类 |
| **HistoryService** | activiti 的历史管理类 |
| ManagerService | activiti 的引擎管理类 |
### service对象概述
#### RepositoryService
是 activiti的资源管理类,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此 service 将流程定义文件的内容部署到计算机。
除了部署流程定义以外还可以:
- 查询引擎中的发布包和流程定义。
- 暂停或激活发布包,对应全部和特定流程定义。 暂停意味着它们不能再执行任何操作了,激活是对应的反向操作。
- 获得多种资源,像是包含在发布包里的文件, 或引擎自动生成的流程图。
- 获得流程定义的 pojo 版本, 可以用来通过 java 解析流程,而不必通过 xml。
#### RuntimeService
它是 activiti的流程运行管理类。可以从这个服务类中获取很多关于流程执行相关的信息
#### TaskService
是 activiti的任务管理类。可以从这个类中获取任务的信息。
#### HistoryService
是 activiti 的历史管理类,可以查询历史信息,执行流程时,引擎会保存很多数据(根据配置),比如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径,等等。 这个服务主要通过查询功能来获得这些数据。
#### ManagementService
是 activiti的引擎管理类,提供了对 Activiti 流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于 Activiti 系统的日常维护。
# 第5章 Activiti-流程定义
在 eclipse 或 idea 中安装 activiti-designer 插件即可使用,画板中包括以下结点:
Connection—连接
Event---事件
Task---任务
Gateway---网关
Container—容器
Boundary event—边界事件
Intermediate event- -中间事件
流程图设计完毕保存生成.bpmn 文件。
## 绘制流程
![image-20230428100807475](imgs/image-20230428100807475.png)
图形绘制好后会生成两个文件:
![image-20230428152201167](imgs/image-20230428152201167.png)