Activiti 是一个开源架构的工作流引擎,基于bpmn2.0 标准进行流程定义。其前身是JBPM,Activiti 通过嵌入到业务系统开发中进行使用。
整合springboot
引入相关依赖
org.activiti
activiti-spring-boot-starter
7.1.0.M4
org.mybatis
mybatis
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.2.0
org.springframework.boot
spring-boot-starter
com.mysql
mysql-connector-j
runtime
org.projectlombok
lombok
true
配置yml
spring:
# 数据源配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/activiti?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&rewriteBatchedStatements=true
username: root
password: 159741
type: com.zaxxer.hikari.HikariDataSource
hikari:
max-lifetime: 120000
# activiti7配置
activiti:
# 自动部署验证设置:true-开启(默认)、false-关闭
check-process-definitions: true
# 保存历史数据
history-level: full
# 检测历史表是否存在
db-history-used: true
# 关闭自动部署,如果不关闭,每次重新启动项目的时候,总是会在 ACT_RE_DEPLOYMENT 自动创建一个名为 SpringAutoDeployment 工作流记录。
deployment-mode: never-fail
# flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。(生产环境常用)
# true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。(开发时常用)
# create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。(单元测试常用)
# drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。
database-schema-update: true
# 解决频繁查询SQL问题
async-executor-activate: false
项目主类排除security相关依赖,否则启动会报错
@SpringBootApplication(exclude = {
SecurityAutoConfiguration.class,
ManagementWebSecurityAutoConfiguration.class
})
public class ActivitiApplication {
public static void main(String[] args) {
SpringApplication.run(ActivitiApplication.class, args);
}
}
数据库建名为activiti的库,启动让Activiti表自动生成
由于7.1.0.M4 版本自动生成的表字段不全所以需要添加2个字段
alter table ACT_RE_DEPLOYMENT add column PROJECT_RELEASE_VERSION_ varchar(255) DEFAULT NULL;
alter table ACT_RE_DEPLOYMENT add column VERSION_ varchar(255) DEFAULT NULL;
在resources目录下创建processes文件夹,在该目录下创建自己的bpmn文件,遵循命名规范,项目启动会进行自动部署
手动部署的方式
//提供流程定义和部署等功能。比如说,实现流程的的部署、删除,暂停和激活以及流程的查询等功能
@Autowired
private RepositoryService repositoryService;
//流程部署
public void initDeployment() {
Deployment deployment =repositoryService.createDeployment()
.addClasspathResource("bpmn/Leave.bpmn")
.addClasspathResource("bpmn/Leave.myleave.png")
.name("流程部署测试")
.deploy();
System.out.println("流程部署名称:" + deployment.getName());
System.out.println("流程部署名称:" + deployment.getId());
}
//流程部署zip形式(zip若添加图片类型,则需要遵循命名规范,bpmn/Leave.bpmn,bpmn/Leave.myleave.png)
public void initDeployment() {
InputStream inputStream = this.getClass().getClass().getClassLoader()
.getResourceAsStream("bpmn/Leave.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.name("流程部署测试")
.deploy();
System.out.println("流程部署名称:" + deployment.getName());
System.out.println("流程部署名称:" + deployment.getId());
}
构建bpmn文件
xml
${leave.num>=3}
${leave.num<3}
需要的entity
@Data
public class Leave implements Serializable {
//申请人id
private Integer userId;
//申请天数
private Integer num;
//请假原因
private String reason;
//技术组长审批
private Integer approver1;
//项目经理审批
private Integer approver2;
//总经理审批
private Integer approver3;
//总经理审批
private String taskId;
}
Controller包含整个流程
@RestController
@RequestMapping("/leave")
public class LeaveController {
//RuntimeService:提供了处理流程实例不同步骤的结构和行为。包括启动流程实例、暂停和激活流程实例等功能
@Autowired
private RuntimeService runtimeService;
//TaskService:提供有关任务相关功能的服务。包括任务的查询、删除以及完成等功能
@Autowired
private TaskService taskService;
//HistoryService:提供 Activiti 引擎收集的历史记录信息服务。主要用于历史信息的查询功能
@Autowired
private HistoryService historyService;
//activiti核心对象可提供各个ActivitiService
@Autowired
private ProcessEngine processEngine;
/**
* 启动流程
* @param userId
* @return
*/
@GetMapping("/start")
public String start(@RequestParam Integer userId){
Map vars = new HashMap<>();
Leave leave = new Leave();
leave.setUserId(userId);
vars.put("leave",leave);
runtimeService.startProcessInstanceByKey("myleave",vars);
return "流程启动成功!";
}
/**
* 申请请假
* @param leave
* @return
*/
@PostMapping(value="/apply")
public String apply(@RequestBody Leave leave){
Map vars = new HashMap<>();
vars.put("leave", leave);
taskService.setVariables(leave.getTaskId(),vars);
taskService.complete(leave.getTaskId());
return "申请成功!";
}
/**
* 查询用户流程
* @param userId
* @return
*/
@GetMapping("/queryTask")
public Map find(@RequestParam("userId")String userId) throws JsonProcessingException {
List taskList = taskService.createTaskQuery().taskAssignee(userId).list();
List resultList = new ArrayList<>();
if(!CollectionUtils.isEmpty(taskList)){
for(Task task : taskList){
//获取指定任务id,leave前缀的信息
Object leave = taskService.getVariable(task.getId(), "leave");
ObjectMapper objectMapper = new ObjectMapper();
Leave leave1 = objectMapper.readValue(leave.toString(), Leave.class);
leave1.setTaskId(task.getId());
leave1.setTaskId(task.getId());
resultList.add(leave1);
}
}
Map resultMap = new HashMap<>();
resultMap.put("data", resultList);
return resultMap;
}
/**
* 技术组长审批
* @param leave
* @return
*/
@PostMapping(value = "/approve1")
public String approve1(@RequestBody Leave leave){
taskService.complete(leave.getTaskId());
return "组长审批通过!";
}
/**
* 项目经理审批
* @param leave
* @return
*/
@PostMapping(value = "/approve2")
public String approve2(@RequestBody Leave leave){
taskService.complete(leave.getTaskId());
return "项目经理审批通过!";
}
/**
* 总经理审批
* @param leave
* @return
*/
@PostMapping(value = "/approve3")
public String approve3(@RequestBody Leave leave){
taskService.complete(leave.getTaskId());
return "总经理审批通过!";
}
/**
* 查看历史记录
* @param userId
* @return
*/
@GetMapping("/queryHistory")
public Map findClosed(String userId){
// 1.根据部署对象ID删除流程定义
//
// repositoryService.deleteDeployment(deploymentId, true);
//
// 2.删除历史流程实例根据流程实例ID
//
// historyService.deleteHistoricProcessInstance(processInstan);
//
// 3.删除正在运行中的流程根据流程实例ID
// runtimeService.deleteProcessInstance(processInstanceId,"");
HistoryService historyService = processEngine.getHistoryService();
List list = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("myleave").variableValueEquals("leave.userId",userId).list();
List leaves = new ArrayList<>();
for(HistoricProcessInstance pi : list){
leaves.add((Leave) pi.getProcessVariables().get("leave"));
}
Map resultMap =new HashMap<>();
resultMap.put("data", leaves);
return resultMap;
}
按流程测试
1.启动流程
2.申请人查询自己的任务
3.申请人提交请假申请
4.技术组长查看自己任务
5.技术组长审批
6.项目经理查看自己任务
7.项目经理审批
由于请假日期不超过3天,到此流程就结束了。
以上就是工作流的一个简单例子。