可以使用插件进行绘制流程图
插件支持.xml,bpmn20.xml,.bpmn三种格式的文件
如果不支持则可以在idea中进行配置
新建
在resource/bpmn 目录上右键新建bpmn文件
1、绘制流程定义
在生成的文件上或者打开的文件中右键使用插件预览
在新打开的窗口中进行绘制流程
绘制中需要设置一些属性
结果
查看源码
导出为png格式的图片
指定的节点负责人【woker】【manager】【financer】
2、部署
通用上传部署
将流程定义文件和导出的png文件上传进行部署
/**
* 分别上传流程定义文件和流程示意图进行部署
*/
@Test
void testDeploy() {
// 创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
// 使用repositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/Leave-1.bpmn20.xml")//添加流程定义文件
.addClasspathResource("bpmn/Leave-1.png")//添加流程png资源
.name("员工请假流程Leave")//定义部署名称
.deploy();
// 输出部署信息
log.info("流程部署id:{}", deployment.getId());
log.info("流程部署名称:{}", deployment.getName());
}
部署会将该流程的部署信息插入【act_re_deployment】数据表中
并生成 一个流程定义信息插入【act_re_procdef】数据表中
上传的文件存储在【act_ge_bytearray】数据表中
一个deploy可以对应多个procdef信息
建议一个deploy对应一个procdef
部署完成:
zip压缩包部署
可以一次性部署多个流程,png文件名称需要和流程定义文件的id进行一一对应
activiti对于图片文件只支持【png|jpg|gif|svg】四种格式
对于流程定义文件支持【.xml|.bpmn20.xml|.bpmn】三种格式
将流程定义文件和导出的png文件打包成为压缩包上传进行部署
/**
* 将流程文件和图片打包一起部署
*/
@Test
void deploymentsByZip() {
// 定义上传文件流
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/Leave-1.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
// 使用repositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
// 输出部署信息
log.info("流程部署id:{}", deployment.getId());
log.info("流程部署名称:{}", deployment.getName());
}
3、启动流程实例
根据流程文件定义的id进行启动流程实例
注意不是部署id而是流程文件定义的id
/**
* 启动流程实例
*/
@Test
void testStartProcess() {
// 创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根据流程定义id进行启动流程
String key = "Leave-1";
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
// 输出启动信息
log.info("流程定义id:{}", processInstance.getProcessDefinitionId());
log.info("流程实例id:{}", processInstance.getId());
log.info("当前活动id:{}", processInstance.getActivityId());
}
执行之后依次插入以下七张数据表中
历史信息:【ACT_HI_TASKINST】【ACT_HI_PROCINST】【ACT_HI_ACTINST】【ACT_HI_IDENTITYLINK】
运行时:【ACT_RU_EXECUTION】【ACT_RU_TASK】【ACT_RU_IDENTITYLINK】
启动实例后,相对应权限的用户就可以通过该实例提出相对应的流程工单了
4、流程节点任务相关
查询任务列表
private final String processDefinitionKey = "Leave-1";
/**
* 任务负责人 worker 在正式开发中就是查询的用户名
*/
private final String assignee_worker = "worker";
private final String assignee_manager = "manager";
private final String assignee_finance = "financer";
/**
* 查询当前个人待执行任务
*/
@Test
void testFindTaskList() {
// 创建taskService
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
// 根据流程key【流程定义ID】 和任务负责人查询任务列表
TaskQuery taskQuery = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey);
//指定任务负责人
List<Task> workerList = taskQuery.taskAssignee(assignee_worker).list();
List<Task> managerList = taskQuery.taskAssignee(assignee_manager).list();
List<Task> financeList = taskQuery.taskAssignee(assignee_finance).list();
// 输出信息
log.info("=================worker===============");
log.info("worker待执行任务:{}个", workerList.size());
for(Task task : workerList) {
log.info("流程实例id:{}", task.getProcessInstanceId());
log.info("任务id:{}", task.getId());
log.info("任务负责人:{}", task.getAssignee());
log.info("任务名称:{}", task.getName());
}
log.info("=================manager===============");
log.info("manager待执行任务:{}个", managerList.size());
for(Task task : managerList) {
log.info("流程实例id:{}", task.getProcessInstanceId());
log.info("任务id:{}", task.getId());
log.info("任务负责人:{}", task.getAssignee());
log.info("任务名称:{}", task.getName());
}
log.info("=================finance===============");
log.info("finance待执行任务:{}个", financeList.size());
for(Task task : financeList) {
log.info("流程实例id:{}", task.getProcessInstanceId());
log.info("任务id:{}", task.getId());
log.info("任务负责人:{}", task.getAssignee());
log.info("任务名称:{}", task.getName());
}
}
完成任务
private final String processDefinitionKey = "Leave-1";
/**
* 任务负责人 worker 在正式开发中就是查询的用户名
*/
private final String assignee_worker = "worker";
private final String assignee_manager = "manager";
private final String assignee_finance = "financer";
/**
* 根据查询出来的任务id进行完成任务
*/
@Test
void testTaskCompleteByWorker() {
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取TaskService
TaskService taskService = processEngine.getTaskService();
// 根据流程定义key和用户名查询任务,返回一个任务对象
Task task = taskService.createTaskQuery()
.processDefinitionKey(processDefinitionKey)
.taskAssignee(assignee_worker)
.singleResult();
if(task == null) {
log.info("worker无待执行任务");
return;
}
// 根据任务id完成任务
taskService.complete(task.getId());
log.info("worker{}任务完成", task.getId());
}
@Test
void testTaskCompleteByManager() {
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取TaskService
TaskService taskService = processEngine.getTaskService();
// 根据流程定义key和用户名查询任务,返回一个任务对象
Task task = taskService.createTaskQuery()
.processDefinitionKey(processDefinitionKey)
.taskAssignee(assignee_manager)
.singleResult();
if(task == null) {
log.info("manager无待执行任务");
return;
}
// 根据任务id完成任务
taskService.complete(task.getId());
log.info("manager{}任务完成", task.getId());
}
@Test
void testTaskCompleteByFinance() {
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取TaskService
TaskService taskService = processEngine.getTaskService();
// 根据流程定义key和用户名查询任务,返回一个任务对象
Task task = taskService.createTaskQuery()
.processDefinitionKey(processDefinitionKey)
.taskAssignee(assignee_finance)
.singleResult();
if(task == null) {
log.info("finance无待执行任务");
return;
}
// 根据任务id完成任务
taskService.complete(task.getId());
log.info("finance{}任务完成", task.getId());
}
任务会根据流程节点节点指定进行递进
依次执行完之后在进行查询任务
任务执行完毕
5、查询任务
查询流程定义
查询一个文件之中定义了几个流程定义实例
/**
* 查询一个文件中有几个流程定义
*/
@Test
void queryProcessDefinition() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("Leave-1").list();
for(ProcessDefinition processDefinition : processDefinitionList) {
log.info("流程定义id:{}",processDefinition.getId());
log.info("流程定义name:{}",processDefinition.getName());
log.info("流程定义key:{}",processDefinition.getKey());
log.info("流程定义version:{}",processDefinition.getVersion());
log.info("流程部署id:{}",processDefinition.getDeploymentId());
}
}
查询流程实例
查询当前定义流程下有几个流程实例
/**
* 查询当前的流程定义中有几个流程实例运行
*/
@Test
void queryProcessInstance() {
String key = "Leave-1";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processDefinitionKey(key).list();
for(ProcessInstance processInstance : processInstanceList) {
log.info("流程实例id:{}",processInstance.getProcessInstanceId());
log.info("所属流程定义id:{}",processInstance.getProcessDefinitionId());
log.info("是否执行完毕:{}",processInstance.isEnded());
log.info("是否暂停执行:{}",processInstance.isSuspended());
log.info("当前活动标识:{}",processInstance.getActivityId());
log.info("业务关键字:{}",processInstance.getBusinessKey());
}
}
查询历史信息
/**
* 查询当前的流程定义中有几个流程实例运行
*/
@Test
void queryHistoryInfo() {
String key = "Leave-1";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
HistoryService historyService = processEngine.getHistoryService();
//获取actinst的查询对象
HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
//查询act_hi_actinst 表 根据InstanceId 进行查询,查询一个流程的所有历史信息
instanceQuery.processInstanceId("2501");
//查询act_hi_actinst 表 根据DefinitionId进行查询,查询一个流程的所有历史信息
instanceQuery.processDefinitionId("Leave-1:1:4");
//排序 根据开始时间排序
instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//查询所有的list
List<HistoricActivityInstance> historicProcessInstanceList = instanceQuery.list();
//输出信息
for(HistoricActivityInstance instance : historicProcessInstanceList) {
log.info("当前活动标识:{}", instance.getActivityId());
log.info("当前活动名称:{}", instance.getActivityName());
log.info("所属流程定义id:{}", instance.getProcessDefinitionId());
log.info("所属流程实例id:{}", instance.getProcessInstanceId());
System.out.println("==============================================");
}
}
6、其他操作
删除流程部署
/**
* 删除流程部署
*/
@Test
void deleteDeployment() {
String deployId = "1";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
//删除流程定义,如果该部署已有流程实例启动则删除报错
repositoryService.deleteDeployment(deployId);
//删除流程定义,设置true,级联删除即使该部署已有流程实例启动也可以删除,同时删除日志
//repositoryService.deleteDeployment(deployId,true);
}
导出流程定义
/**
* 查询已有的bpmn信息
*
* @throws Exception
*/
@Test
void queryBpmnFiles() throws Exception {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("Leave-1")
.singleResult();
//获取部署id
String deploymentId = processDefinition.getDeploymentId();
// 通过方法读取数据库中的文件信息
InputStream pngInput = repositoryService.getResourceAsStream(deploymentId,
processDefinition.getDiagramResourceName());
InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId,
processDefinition.getResourceName());
// 导出文件
File png = new File("d:/Leave.png");
File bpmn = new File("d:/Leave.bpmn20.xml");
FileOutputStream pngOut = new FileOutputStream(png);
FileOutputStream bpmnOut = new FileOutputStream(bpmn);
//输入流和输出流的转换
IoUtil.copy(pngInput, pngOut);
IoUtil.copy(bpmnInput, bpmnOut);
//关闭流
pngOut.close();
bpmnOut.close();
pngInput.close();
bpmnInput.close();
}