简单的activiti5流程框架代码实现:
流程图:
第一步:安装插件activiti-designer-5.18,要用jdk1.5以后的版本
第二步:创建Spring-boot工程,选择activiti组件
第三步:导入相关jar包,并编写相关配置
添加依赖关系
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
编写application.yml配置文件
---
spring:
datasource:
name: mydb
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/test
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
第四步:测试
@Test
public void allStep() {
// 部署
repositoryService
.createDeployment()
.addClasspathResource("MyProcess2.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 启动
ProcessInstance pi = runtimeService.startProcessInstanceById(pd.getId());
// 完成任务
TaskQuery query = taskService.createTaskQuery();
List<Task> ts = query.taskAssignee("zhangsan").list();
for ( Task t : ts ) {
System.out.println( "zhangsan完成的任务 =" + t.getName() );
taskService.complete(t.getId());
}
// 历史查询
HistoricProcessInstanceQuery hpiQuery =
historyService.createHistoricProcessInstanceQuery();
HistoricProcessInstance hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
query = taskService.createTaskQuery();
ts = query.taskAssignee("lisi").list();
for ( Task t : ts ) {
System.out.println( "lisi完成的任务 =" + t.getName() );
taskService.complete(t.getId());
}
hpiQuery =
historyService.createHistoricProcessInstanceQuery();
hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
}
简简单单的一个流程框架就算入门了。
测试遇到的问题:
@Test
public void contextLoads() {
// ProcessEngineImpl
// 1)依赖jar包优先级(将mybatis的依赖关系放置在前面)
// 2) 新版本的activiti框架需要在classpath中增加processes文件夹。
//System.out.println( "processEngine = " + processEngine );
//RepositoryService repositoryService = processEngine.getRepositoryService();
System.out.println(repositoryService);
}
相关知识:
ProcessEngine这个类是Activiti5的核心,所有的服务都需要通过ProcessEngine来创建,该类是线程安全的
Activiti5的持久化层采用的是Mybatis,这样移植性好
Activiti5主要包括7个Service,这些Service都是通过ProcessEngine创建
repositoryService(持久化服务)
runtimeService(运行时服务)
formService(表单服务)
identityService(身份信息)
taskService(任务服务)
historyService(历史信息)
managementService(管理定时任务)
Activiti使用到的表都是ACT_开头的。
ACT_RE_*: ‘RE’表示repository(存储),RepositoryService接口所操作的表。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。
ACT_RU_*: ‘RU’表示runtime,运行时表-RuntimeService。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。Activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。
ACT_ID_*: ’ID’表示identity (组织机构),IdentityService接口所操作的表。用户记录,流程中使用到的用户和组。这些表包含标识的信息,如用户,用户组,等等。
ACT_HI_*: ’HI’表示history,历史数据表,HistoryService。就是这些表包含着流程执行的历史相关数据,如结束的流程实例,变量,任务,等等
ACT_GE_*: 全局通用数据及设置(general),各种情况都使用的数据。
act_ge_bytearray二进制数据表
act_ge_property属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录,
act_hi_actinst历史节点表
act_hi_attachment历史附件表
act_hi_comment历史意见表
act_hi_identitylink历史流程人员表
act_hi_detail历史详情表,提供历史变量的查询
act_hi_procinst历史流程实例表
act_hi_taskinst历史任务实例表
act_hi_varinst历史变量表
act_id_group用户组信息表
act_id_info用户扩展信息表
act_id_membership用户与用户组对应信息表
act_id_user用户信息表
act_re_deployment部署信息表
act_re_model流程设计模型部署表
act_re_procdef流程定义数据表
act_ru_event_subscr throwEvent、catchEvent时间监听信息表
act_ru_execution运行时流程执行实例表
act_ru_identitylink运行时流程人员表,主要存储任务节点与参与者的相关信息
act_ru_job运行时定时任务数据表
act_ru_task运行时任务节点表
act_ru_variable运行时流程变量数据表
附上完整的测试类:
package com.atguigu.atcrowdfunding.member;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootActApplicationTests {
@Autowired
private ProcessEngine processEngine;
@Autowired
private RepositoryService repositoryService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Test
public void contextLoads() {
// ProcessEngineImpl
// 1)依赖jar包优先级(将mybatis的依赖关系放置在前面)
// 2) 新版本的activiti框架需要在classpath中增加processes文件夹。
//System.out.println( "processEngine = " + processEngine );
//RepositoryService repositoryService = processEngine.getRepositoryService();
System.out.println(repositoryService);
}
@Test
public void sendMail() {
repositoryService
.createDeployment()
.addClasspathResource("MyProcess8.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 启动
ProcessInstance pi =
runtimeService.startProcessInstanceById(pd.getId());
}
@Test
public void processListener() {
repositoryService
.createDeployment()
.addClasspathResource("MyProcess7.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 启动
ProcessInstance pi =
runtimeService.startProcessInstanceById(pd.getId());
List<Task> tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
for ( Task task : tasks ) {
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("status", "refuse");
System.out.println("zhangsan完成了任务 =" + task.getName());
taskService.complete(task.getId(), varMap);
}
}
@Test
public void gateway3() {
// 网关其实就是流程中的逻辑分支判断
// 包含(排他+并行)网关:多个逻辑分支不一定全部满足,根据条件执行不同的分支。
// 如果多个分支只有一个条件成立,那么等同于排他网关
// 如果多个分支有多个条件成立,那么等同于并行网关
repositoryService
.createDeployment()
.addClasspathResource("MyProcess6.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("days", 5);
varMap.put("cost", 20000);
// 启动
ProcessInstance pi =
runtimeService.startProcessInstanceById(pd.getId(), varMap);
List<Task> tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
List<Task> tasks1 = taskService.createTaskQuery().taskAssignee("lisi").list();
System.out.println("zhangsan的任务数量 =" +tasks.size());
System.out.println("lisi的任务数量 =" +tasks1.size());
for ( Task task : tasks ) {
System.out.println("zhangsan完成任务 = " + task.getName());
taskService.complete(task.getId());
}
// 历史查询
HistoricProcessInstanceQuery hpiQuery =
historyService.createHistoricProcessInstanceQuery();
HistoricProcessInstance hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
tasks1 = taskService.createTaskQuery().taskAssignee("lisi").list();
System.out.println("zhangsan的任务数量 =" +tasks.size());
System.out.println("lisi的任务数量 =" +tasks1.size());
for ( Task task : tasks1 ) {
System.out.println("lisi完成任务 = " + task.getName());
taskService.complete(task.getId());
}
hpiQuery =
historyService.createHistoricProcessInstanceQuery();
hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
}
@Test
public void gateway2() {
// 网关其实就是流程中的逻辑分支判断
// 并行网关:多个逻辑分支同时满足,同时执行。
// 如果其中一个分支执行完毕,流程不会继续执行,
// 需要等待其他所有的分支全部执行完毕,流程才会继续执行
// 会签
repositoryService
.createDeployment()
.addClasspathResource("MyProcess5.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 启动
ProcessInstance pi =
runtimeService.startProcessInstanceById(pd.getId());
List<Task> tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
List<Task> tasks1 = taskService.createTaskQuery().taskAssignee("lisi").list();
System.out.println("zhangsan的任务数量 =" +tasks.size());
System.out.println("lisi的任务数量 =" +tasks1.size());
for ( Task task : tasks ) {
System.out.println("zhangsan完成任务 = " + task.getName());
taskService.complete(task.getId());
}
// 历史查询
HistoricProcessInstanceQuery hpiQuery =
historyService.createHistoricProcessInstanceQuery();
HistoricProcessInstance hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
tasks1 = taskService.createTaskQuery().taskAssignee("lisi").list();
System.out.println("zhangsan的任务数量 =" +tasks.size());
System.out.println("lisi的任务数量 =" +tasks1.size());
for ( Task task : tasks1 ) {
System.out.println("lisi完成任务 = " + task.getName());
taskService.complete(task.getId());
}
hpiQuery =
historyService.createHistoricProcessInstanceQuery();
hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
}
@Test
public void gateway1() {
// 网关其实就是流程中的逻辑分支判断
// 排他网关:多个逻辑分支,同时只能执行一个。
// 决策
repositoryService
.createDeployment()
.addClasspathResource("MyProcess4.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 声明变量集合
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("days", 5);
// 启动
ProcessInstance pi =
runtimeService.startProcessInstanceById(pd.getId(), varMap);
List<Task> tasks = taskService.createTaskQuery().taskAssignee("zhangsan").list();
for ( Task t : tasks ) {
System.out.println("zhangsan完成了任务= " +t.getName());
taskService.complete(t.getId());
}
// 历史查询
HistoricProcessInstanceQuery hpiQuery =
historyService.createHistoricProcessInstanceQuery();
HistoricProcessInstance hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
}
@Test
public void procVar() {
// 如果流程中使用了流程变量,必须要在变量使用前进行赋值
repositoryService
.createDeployment()
.addClasspathResource("MyProcess3.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 声明变量集合
Map<String, Object> varMap = new HashMap<String, Object>();
varMap.put("TL", "wangwu");
// 启动
ProcessInstance pi =
runtimeService.startProcessInstanceById(pd.getId(), varMap);
List<Task> tasks = taskService.createTaskQuery().taskAssignee("wangwu").list();
varMap.put("PM", "zhaoliu");
for ( Task t : tasks ) {
// 完成任务时,可以传递流程变量
taskService.complete(t.getId(), varMap);
}
}
@Test
public void allStep() {
// 部署
repositoryService
.createDeployment()
.addClasspathResource("MyProcess2.bpmn")
.deploy();
// 获取流程定义ID
ProcessDefinition pd =
repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("myProcess")
.latestVersion()
.singleResult();
// 启动
ProcessInstance pi = runtimeService.startProcessInstanceById(pd.getId());
// 完成任务
TaskQuery query = taskService.createTaskQuery();
List<Task> ts = query.taskAssignee("zhangsan").list();
for ( Task t : ts ) {
System.out.println( "zhangsan完成的任务 =" + t.getName() );
taskService.complete(t.getId());
}
// 历史查询
HistoricProcessInstanceQuery hpiQuery =
historyService.createHistoricProcessInstanceQuery();
HistoricProcessInstance hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
query = taskService.createTaskQuery();
ts = query.taskAssignee("lisi").list();
for ( Task t : ts ) {
System.out.println( "lisi完成的任务 =" + t.getName() );
taskService.complete(t.getId());
}
hpiQuery =
historyService.createHistoricProcessInstanceQuery();
hpi =
hpiQuery.processInstanceId(pi.getId()).finished().singleResult();
System.out.println("流程【"+pi.getId()+"】是否结束 = " + (hpi != null));
}
@Test
public void loadHistoryData() {
HistoricProcessInstanceQuery query =
historyService.createHistoricProcessInstanceQuery();
HistoricProcessInstance hpi = query.processInstanceId("12501").finished().singleResult();
System.out.println("历史流程实例 =" +hpi);
}
@Test
public void nextStep() {
// 让流程执行后续操作(下一步)
// 获取任务
TaskQuery query = taskService.createTaskQuery();
List<Task> ts = query.list();
for ( Task t : ts ) {
// 完成任务,流程继续执行
System.out.println( "完成任务 = " + t.getName() );
taskService.complete(t.getId());
}
}
@Test
public void startInstance() {
// 创建流程实例(流程定义的具体应用)
String id =
repositoryService
.createProcessDefinitionQuery()
.latestVersion().singleResult().getId();
/*
* 启动流程实例之后,数据库表数据会发生变化
* 当启动后,流程框架会自动执行开始(start)操作,然后跳转到第一个task(任务)
* act_hi_actinst :历史节点表,将流程的每一个执行节点数据保存。
* act_hi_procinst :历史流程实例表, 保存当前流程实例数据
* act_hi_taskinst :历史流程任务表,保存执行的任务信息
* act_ru_execution : 运行时流程执行实例表, 保存当前流程执行实例数据
* act_ru_task : 运行时任务表,保存了当前流程执行时任务数据
*/
runtimeService.startProcessInstanceById(id);
}
@Test
public void loadDataFromDB() {
// 获取查询对象,通过对象所提供的方法对数据库进行访问
ProcessDefinitionQuery query =
repositoryService.createProcessDefinitionQuery();
// 查询数据
List<ProcessDefinition> pds = query.list();
for ( ProcessDefinition pd : pds ) {
//System.out.println( "key = " + pd.getKey() + ", name = " + pd.getName() + ", version = " + pd.getVersion());
}
// 根据条件查询
/*
pds = query.processDefinitionVersion(1).list();
for ( ProcessDefinition pd : pds ) {
//System.out.println( "key = " + pd.getKey() + ", name = " + pd.getName() + ", version = " + pd.getVersion());
}
*/
// 获取最新版本的数据
/*
ProcessDefinition pd = query.orderByProcessDefinitionVersion().desc().list().get(0);
System.out.println( "version = " + pd.getVersion());
*/
/*
ProcessDefinition pd = query.latestVersion().singleResult();
System.out.println( "version = " + pd.getVersion());
*/
// 分页查询数据
//query.listPage((pageno-1)*pagesize, pagesize);
//int cnt = (int)query.count();
}
@Test
public void loadImgData() {
// 将流程定义图形加载到流程框架中,让流程可以自动执行
// 部署(流程图==> DB)
// DeploymentEntity(id=1)
/*
* 部署流程图形时,数据库中会有3张表发生变化
* act_ge_bytearray(2) : 保存当前流程的文件和图形信息
* act_re_deployment(1) : 部署信息表, 保存当前部署信息(主键,时间)
* act_re_procdef(1) : 流程定义表,保存当前流程定义信息(id, name, version)
*/
Deployment d = repositoryService
.createDeployment()
.addClasspathResource("MyProcess1.bpmn")
.deploy();
System.out.println("将流程定义图形加载到数据库中 = " + d);
}
}