最近做的一个项目中需要实现员工请假的功能,计划使用activiti来实现请假流程,所以去学习了一下相关的知识。并且完成了一个简单的请假实例。
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:
<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:
spring: datasource: username: root password: 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文件的插件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XRNZOHIG-24)([外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XdduQyP7-02)(http://114.116.239.228:8090/upload/2020/07/2-f4a15b2d52a92e60150a5.jpg)]])
安装成功后在resources目录下创建processes文件夹并新建holiday.bpmn文件并且创建流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0r8r0iq9-26)(
])
对应xml文件代码如下
<definitions xmlns="http://www.omg.org/spec/BPMN//MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN//DI" xmlns:omgdc="http://www.omg.org/spec/DD//DC" xmlns:omgdi="http://www.omg.org/spec/DD//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="m49" 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张工作表。

编写实例
开启请假流程
@Test public void start() {
String instanceKey = "myProcess_1"; logger.info("开启请假流程..."); Map<String, Object> map = new HashMap<String, Object>(); //在holiday.bpmn中,填写请假单的任务办理人为动态传入的userId,此处模拟一个id 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中添加为流程变量。
@Test public void employeeApply() {
String instanceId = "adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff"; // 任务ID 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的形式来获取。
@Test public void showTaskVariable (){
String instanceId = "adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff"; // 任务ID 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()); }
运行结果:

上级审批
上级审批并且添加意见
@Test public void departmentAudit() {
String instanceId = "adc6a5f0-a2c3-11e9-bb83-00e04c83a7ff"; // 任务ID 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可以方便对流程进行控制。本文只是对简单的请假流程做了实例,没有涉及到多任务或多分支等情景。对于此类情况以后再做补充。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/178205.html原文链接:https://javaforall.net
