技术:spring boot2+Activiti6.0+MySQL5.7
开发工具:IDEA首先在IDEA中安装Activiti插件actiBPM新建一个SpringBoot项目,添加Activiti和MySQL的依赖
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
在MySQL中新建一个数据库,yml中配置数据库信息
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
启动类排除SecurityAutoConfiguration不然可能会报错
import org.activiti.spring.boot.SecurityAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class ActivititestApplication {
public static void main(String[] args) {
SpringApplication.run(ActivititestApplication.class, args);
}
}
启动项目成功之后,数据库中会新增以下Activiti相关的表结构接下来我们就可以创建流程图进行流程操作了,右击原文件目录新建BPMN File文件,然后我们创建一个简单的报销流程(提交报销单->部门总监审批->财务总监审批->流程结束)
Assignee代表的是受理人,比如我这里部门总监是老王,财务总监是老李
流程创建成功之后我们把 报销流程.bpmn这个文件的后缀名改为xml,就可以看到xml格式的流程
我们右击这个xml选择Diagram然后选中Show BPMN 2.0 Designer就可以看到这个流程,我们可以选择把这个流程保存为图片方便查看
准备工作已经做好了,接下来我们开始一步一步的执行一个流程,首先先把流程文件的后缀名改回bpmn,我们来使用测试类一步一步执行流程
部署一个简单的报销流程(提交报销单->部门总监审批->财务总监审批->流程结束)
/*
* @Author wls
* @Date 2020/5/8 15:26
* @Description //TODO 部署一个简单的报销流程(提交报销单->部门总监审批->财务总监审批->流程结束)
* @Param []
* @Return void
* @Exception
**/
@Test
public void createActivitiTask(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("processes/报销流程.bpmn")
.addClasspathResource("processes/报销流程.png")
.deploy();
LOGGER.info("部署流程成功");
}
暂时没有写页面主要看一下数据库表中的变化,初始化生成的表都是空的,我们部署流程后act_re_procdef表中多了一条报销流程的数据,并且act_ge_bytearray表中已经将报销流程.bpmn和报销流程.png进行二进制存储部署 成功之后我们就可以启动这个流程
/*
* @Author wls
* @Date 2020/5/8 15:27
* @Description //TODO 启动流程实例
* @Param []
* @Return void
* @Exception
**/
@Test
public void startActiviti(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//Id就是act_re_procdef表中的ID_
processEngine.getRuntimeService()
.startProcessInstanceById("myProcess_1:1:4");
}
act_hi_actinst表中存储了流程执行步骤,目前已经开始流程并到了报销的步骤act_hi_procinst表中存储了历史的流程实例,当END_TIME_为空时,说明这个流程正在执行中,如果不为空则说明这个流程已经结束
act_ru_execution表是张临时表,存储当前正在执行的流程实例,当流程实例执行结束就会被删除掉
act_ru_task表也是张临时表,存储当前正在执行的任务,当任务完成后就会被删除掉
目前我们已经到达报销的步骤,下面我们完成报销申请提交的步骤
/**
* @Author wls
* @Date 2020/5/9 15:38
* @Description //TODO 完成报销单提交流程,等待部门总监审批
* @Param []
* @Return void
* @Exception
**/
@Test
public void completeBaoxiao(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//查看act_ru_task表的ID_
processEngine.getTaskService()
.complete("2505");
}
当我们执行完后发现act_ru_task表数据的ID_已经变了,NAME_也变成了部门总监审批,受理人是部门总监老王,这个时候流程已经到了部门总监这里,等待老王审批了
老王作为一个受理人,肯定会有不止一个的流程需要审批,所以我们可以查询审批流程到老王这的流程
/*
* @Author wls
* @Date 2020/5/9 15:54
* @Description //TODO 查询受理人老王需要审批的流程,创建一个查询,根据创建时间倒叙、受理人是老王的流程
* @Param []
* @Return void
* @Exception
**/
@Test
public void queryLaoWangApprove(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
List<Task> taskList = processEngine.getTaskService()
.createTaskQuery()
.orderByTaskCreateTime()
.desc()
.taskAssignee("老王")
.list();
taskList.forEach(System.out::println);
}
当前等待老王审批的的流程
我们查到老王有个id=5002的流程需要审批,我们通过id去给他审批通过
/*
* @Author wls
* @Date 2020/5/9 16:01
* @Description //TODO 部门总监审批通过
* @Param []
* @Return void
* @Exception
**/
@Test
public void completeDepartment(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
processEngine.getTaskService()
.complete("5002");
}
当我们执行完后发现act_ru_task表数据的ID_已经变了,NAME_也变成了财务总监审批,受理人是财务总监老李,这个时候流程已经到了财务总监这里,等待老李审批了
当财务总监老李给审批通过之后,这整个流程就结束了
/*
* @Author wls
* @Date 2020/5/9 16:09
* @Description //TODO 财务总监审批通过
* @Param []
* @Return void
* @Exception
**/
@Test
public void completeFinance(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
processEngine.getTaskService()
.complete("7502");
}
此时整个报销流程就结束了,我们再看act_ru_xxx表已经没有数据了,act_hi_actinst表记录了整个流程所有的流程实例,从开始到结束的过程
一个简单的报销流程就结束了,Activiti数据表有二十多张,我们了解了表的存储内容就很容易明白这流程的运作,简单说一下大致表结构,详细请自行百度
act_ge_xxx:“ge"代表"general”,表示通用表
act_hi_xxx:“hi"代表"history”,表示历史数据表,存储的是历史数据
act_id_xxx:“id"代表"identity”,表示身份,存储的是一些身份信息
act_re_xxx:“re"代表"repository”,表示仓库,保存流程定义及资源等
act_ru_xxx:“ru"代表"runtime”,表示运行时数据,保存运行时的流程数据,流程结束会立即移除