SpringBoot整合Activiti7使用
发表于|更新于
|阅读量:
<Excerpt in index | 首页摘要>
最近做的一个项目中需要实现员工请假的功能,计划使用 activiti 来实现请假流程,所以去学习了一下相关的知识。并且完成了一个简单的请假实例。
<The rest of contents | 余下全文>
Activiti 相关
Activiti 介绍
Activiti 是基于 Apache 许可的开源 BPM 平台,创始人 Tom Baeyens 原是 JBPM 架构师,可以理解为与 JBPM 出自同一祖师爷。它提供了 Eclipse 插件,开发可以通过插件直接绘制业务流程图。基于 Spring,ibatis 等框架,并在此之上构建了非常清晰的开发框架。是由 Alfresco 软件发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。 本文基于 Activiti7 的 Activiti Core,基于 Spring Boot 做简单学习总结。
Acticiti 核心类介绍
ProcessEngine
流程引擎的抽象,可以通过此类获取需要的所有服务。
Service 类
通过 ProcessEngine 获取,Activiti 将不同生命周期的服务封装在不同 Service 中,包括定义、部署、运行。通过服务类可获取相关生命周期中的服务信息。
taskService
流程运行过程中,每个任务节点的相关操作接口,如 complete,delete,delegate 等。
RepositoryService
流程定义和部署相关的存储服务
RuntimeService
流程运行时相关的服务,如根据流程好启动流程实例 startProcessInstanceByKey。
HistoryService
历史记录相关服务接口。
项目搭建
创建 SpringBoot 项目并且添加 maven 依赖
pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description>
<properties> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </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> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifactId> <version>7.0.0.Beta2</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
</dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
</project>
|
添加配置文件
application.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/test2?nullCatalogMeansCurrent=true driver-class-name: com.mysql.cj.jdbc.Driver devtools: restart: enabled: true #设置开启热部署 activiti: database-schema-update: true history-level: full db-history-used: true
debug: true
|
创建流程图
在创建流程图之前首先需要安装 idea 支持 bpm 文件的插件

安装成功后在 resources 目录下创建 processes 文件夹并新建 holiday.bpmn 文件并且创建流程

对应 xml 文件代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1562573992349" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"> <process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"> <startEvent id="_2" name="StartEvent"/> <userTask activiti:assignee="${userId}" activiti:exclusive="false" id="_3" name="填写申请单"/> <userTask activiti:assignee="department" activiti:exclusive="true" id="_4" name="审核"/> <endEvent id="_6" name="EndEvent"/> <sequenceFlow id="_7" sourceRef="_2" targetRef="_3"/> <sequenceFlow id="_8" sourceRef="_3" targetRef="_4"/> <sequenceFlow id="_11" sourceRef="_4" targetRef="_6"/> </process> <bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"> <bpmndi:BPMNPlane bpmnElement="myProcess_1"> <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"> <omgdc:Bounds height="32.0" width="32.0" x="225.0" y="175.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"> <omgdc:Bounds height="55.0" width="85.0" x="435.0" y="175.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"> <omgdc:Bounds height="55.0" width="85.0" x="655.0" y="175.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6"> <omgdc:Bounds height="32.0" width="32.0" x="875.0" y="185.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_3"> <omgdi:waypoint x="257.0" y="191.0"/> <omgdi:waypoint x="435.0" y="202.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_4"> <omgdi:waypoint x="520.0" y="202.5"/> <omgdi:waypoint x="655.0" y="202.5"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_4" targetElement="_6"> <omgdi:waypoint x="740.0" y="202.5"/> <omgdi:waypoint x="875.0" y="201.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
|
运行 Application
启动后查看数据库发现 springboot 自动读取了 processes 下的 holiday.bpmn 文件并且部署任务流程到 activiti。数据库中生成了 25 张工作表。

并且在 ACT_GE_BYTEARRAY 表中也存在部署的信息

编写实例
开启请假流程
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Test public void start() { String instanceKey = "myProcess_1"; logger.info("开启请假流程..."); Map<String, Object> map = new HashMap<String, Object>(); map.put("userId", "10001"); ProcessInstance instance = runtimeService.startProcessInstanceByKey(instanceKey, map); logger.info("启动流程实例成功:{}", instance); logger.info("流程实例ID:{}", instance.getId()); logger.info("流程定义ID:{}", instance.getProcessDefinitionId());
}
|
运行结果:

运行后成功开启了一个请假实例并且获取到 id 为:adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff。
填写请假单
通过实例 id 可以查询到实例所对应的任务,模拟用户请假的内容存入 map 中添加为流程变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Test public void employeeApply() { String instanceId = "adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff"; String leaveDays = "10"; String leaveReason = "回老家结婚"; Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult(); if (task == null) { logger.info("任务ID:{}查询到任务为空!", instanceId); } Map<String, Object> map = new HashMap<String, Object>(); map.put("days", leaveDays); map.put("date", new Date()); map.put("reason", leaveReason); taskService.complete(task.getId(), map); logger.info("执行【员工申请】环节,流程推动到【上级审核】环节"); }
|
运行结果如下:

流程变量查看
上级审核的时候需要查看到员工所提交的请假相关信息,可以通过 taskService.getVariable 的形式来获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Test public void showTaskVariable (){ String instanceId = "adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff";
Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult(); String days = (String) taskService.getVariable(task.getId(), "days"); Date date = (Date) taskService.getVariable(task.getId(), "date"); String reason = (String) taskService.getVariable(task.getId(), "reason"); String userId = (String) taskService.getVariable(task.getId(), "userId"); System.out.println("请假天数: " + days); System.out.println("请假理由: " + reason); System.out.println("请假人id: " + userId); System.out.println("请假日期: " + date.toString()); }
|
运行结果:

上级审批
上级审批并且添加意见
1 2 3 4 5 6 7 8 9 10 11
| @Test public void departmentAudit() { String instanceId = "adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff"; String departmentalOpinion = "早去早回"; Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult(); Map<String, Object> map = new HashMap<String, Object>(); map.put("departmentalOpinion", departmentalOpinion); taskService.complete(task.getId(), map); logger.info("添加审批意见,请假流程结束"); }
|
运行结果:

总结
使用 Activiti 可以方便对流程进行控制。本文只是对简单的请假流程做了实例,没有涉及到多任务或多分支等情景。对于此类情况以后再做补充。