Activiti-流程定义
一、什么是流程定义
流程定义是线下bpmn2.0标椎去描述业务流程,通常使用activiti-explorer(web控制台)或 activiti-eclipse-designer 插件对业务流程进行建模,这两种方式都遵循 bpmn2.0 标准。使用designer 设计器绘制流程,会生成两个文件:.bpmn 和.png
1、.bpmn文件
2、.png文件生成
①首先将.bpmn文件改为.xml文件
②然后右键该xml文件Diagrams--->show BPMN 2.0 Designer就能生成一张流程图,将流程图导出保存到项目对应目录即可
③然后将.xml改回.bpmn即可
注意:
流程图生成前须设置编码格式然后重启IDEA!!!
-Dfile.encoding=UTF-8
二、流程定义部署
1、什么是流程定义部署
将线下定义的流程部署到activiti数据库中,这就是流程定义部署,通过调用activiti的api将流程定义的bpmn和png两个文件一个一个添加部署到activiti中,也可以将两个文件打成ZIP包进行部署;
2、activiti.cfg.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--数据源--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/activiti"/> <property name="username" value="root"/> <property name="password" value="123"/> </bean> <!--配置Activiti使用的processEngine对象 默认命名为processEngineConfiguration--> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <!--注入数据源--> <property name="dataSource" ref="dataSource"/> <!--配置数据源方式二:--> <!--<property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>--> <!--指定数据库生成策略--> <property name="databaseSchemaUpdate" value="true"/> </bean> </beans>
3、单个文件部署方式
分别将bpmn文件和png图片文件部署;
package com.zn; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.junit.Test; public class ActivitiTest { /*流程部署 * `act_ge_bytearray` 流程定义的资源信息,包含bpmn和png流程文件信息 * `act_re_deployment` 流程部署信息 包含流程名称,ID,key等 * `act_re_procdef` 流程定义信息 * */ @Test public void deployment(){ //获取ProcessEngine对象 默认配置文件名称:activiti.cfg.xml 并且configuration的Bean实例ID为processEngineConfiguration ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取RepositoryService对象进行流程部署 RepositoryService repositoryService = processEngine.getRepositoryService(); //进行部署,将对应的流程定义文件生成到数据库当中,作为记录进行保存 Deployment deployment = repositoryService.createDeployment() //加载流程文件 .addClasspathResource("bpmnFiles/holiday.bpmn") .addClasspathResource("bpmnFiles/holiday.png") //设置流程名称 .name("请假流程") .key("holidayKey") //部署 .deploy(); //输出部署信息 System.out.println("流程名称:"+deployment.getName()); System.out.println("流程ID:"+deployment.getId()); System.out.println("流程Key:"+deployment.getKey()); } }
4、压缩包部署方式
将bpmn文件和png图片压缩成zip包;
package com.zn; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.junit.Test; import java.io.InputStream; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 压缩包的方式部署流程 */ @Test public void deploymentByZip(){ //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取一个RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //定义一个输入流,加载Zip文件 InputStream inputStream=this.getClass().getClassLoader().getResourceAsStream("bpmnFiles/holiday.zip"); //定义一个ZIPInputStream对象 ZipInputStream zipInputStream=new ZipInputStream(inputStream); //流程部署 Deployment deploy = repositoryService.createDeployment() .addZipInputStream(zipInputStream) .name("请求审批流程") .key("holidayKey") .deploy(); System.out.println("流程名称:"+deploy.getName()); } }
执行操作控制台效果
数据库展示
5、流程定义查询
查询部署的流程定义;
package com.zn; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.junit.Test; import java.io.InputStream; import java.util.List; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 流程定义信息查看 */ @Test public void getDefaultProcessEngine(){ //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取一个RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //得到流程定义查看对象ProcessDefinitionQuery ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); //指定查看的流程processDefinitionKey()指定流程定义的key值 orderByProcessDefinitionVersion根据流程定义版本号排序 List<ProcessDefinition> holiday = processDefinitionQuery.processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list(); for (ProcessDefinition processDefinition:holiday) { System.out.println("流程定义ID:"+processDefinition.getId()); System.out.println("流程定义的名称:"+processDefinition.getName()); System.out.println("流程定义的Key:"+processDefinition.getKey()); System.out.println("流程定义的版本号:"+processDefinition.getVersion()); } } }
执行操作控制台效果
6、流程定义删除
删除已经部署成功的流程定义;
package com.zn; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.junit.Test; import java.io.InputStream; import java.util.List; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 删除流程: * 假设在删除时,当前正在有该流程实例执行,那么会导致删除失败 * 如果强制要求,则可以使用repositoryService.deleteDeployment("1",true); true代表级联删除 */ @Test public void deleteDeployment(){ //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取一个RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //删除流程 repositoryService.deleteDeployment("10001",true); } }
说明:
1.使用RepositoryService删除流程定义;
2.如果流程定义下没有正在运行的流程,则可以普通删除;
3.如果将流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关级联全部删除;
三、从数据库中读取资源文件到本地
1、导入依赖
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
2、代码实现
package com.zn; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.apache.commons.io.IOUtils; import org.junit.Test; import java.io.*; import java.util.List; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 从数据中读取资源文件到本地 */ @Test public void getResource() throws IOException { //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取一个RepositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //获取到流程查询对象 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); //获取到流程资源 processDefinitionQuery.processDefinitionKey("holiday"); //获取单一结果 ProcessDefinition processDefinition = processDefinitionQuery.singleResult(); //流程部署的ID String deploymentId = processDefinition.getDeploymentId(); //获取到bpmnResource InputStream bpmnStream = repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName()); //获取到png InputStream pngStream = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName()); //构建输出流 OutputStream bpmnOut = new FileOutputStream("E:\\accp\\Y2\\毕设项目\\"+processDefinition.getResourceName()); OutputStream pngOut = new FileOutputStream("E:\\accp\\Y2\\毕设项目\\"+processDefinition.getDiagramResourceName()); //将数据输出到磁盘当中 IOUtils.copy(bpmnStream,bpmnOut); IOUtils.copy(pngStream,pngOut); //关流 pngOut.close(); bpmnOut.close(); pngStream.close(); bpmnStream.close(); } }
3、效果
四、业务系统和流程系统进行关联
通过buessinessKey字段标识业务系统的主键数据ID,进而表名当前业务执行到了哪一个流程
1.代码实现
package com.zn; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.task.Task; import org.apache.commons.io.IOUtils; import org.junit.Test; import java.io.*; import java.util.List; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 启动流程实例和业务系统关联 * 正常应该先添加数据到业务表当中,拿到当前添加数据的主键ID,通过启动流程实例,将主键ID交给BuessniessKkey * 代表和流程系统进行关联 */ @Test public void startInstance() { /** * 让张三在页面提交,然后拿到ID */ /** * 创建张三请假的实例流程 */ //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); //生成流程 runtimeService.startProcessInstanceByKey("holiday","1"); /** * 张三提交请假审批 */ //获取一个TaskService对象 TaskService taskService = processEngine.getTaskService(); //获取张三的任务 Task task = taskService.createTaskQuery().taskAssignee("zhangsan").processDefinitionKey("holiday").singleResult(); //任务审批 taskService.complete(task.getId()); } }
2.数据库
五、流程激活和挂起
1、所有流程
package com.zn; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.io.IOUtils; import org.junit.Test; import java.io.*; import java.util.List; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 所有流程定义的挂起 */ @Test public void allSuspend(){ //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取repositoryService对象 RepositoryService repositoryService = processEngine.getRepositoryService(); //获取流程定义 ProcessDefinition holiday = repositoryService.createProcessDefinitionQuery().processDefinitionKey("holiday").singleResult(); //获取到当前流程定义是否为暂停状态 suspended方法为true代表为暂停 false就是运行的 boolean suspended = holiday.isSuspended(); if(suspended){ repositoryService.activateProcessDefinitionById(holiday.getId(),true,null); System.out.println("该流程定义激活"); }else{ repositoryService.suspendProcessDefinitionById(holiday.getId(),true,null); System.out.println("该流程定义暂停"); } } }
控制台效果:
再次执行效果:
2、单个流程
package com.zn; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.io.IOUtils; import org.junit.Test; import java.io.*; import java.util.List; import java.util.zip.ZipInputStream; public class ActivitiTest { /** * 单个流程实例的挂起 */ @Test public void singleSuspend(){ //获取processEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取RuntimeService对象 RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId("2501").singleResult(); //获取到当前流程定义是否为暂停状态 suspended方法为true代表为暂停 false就是运行的 boolean suspended = processInstance.isSuspended(); if(suspended){ runtimeService.activateProcessInstanceById("2501"); System.out.println("xx的请假流程激活"); }else{ runtimeService.suspendProcessInstanceById("2501"); System.out.println("xx的请假流程挂起"); } } }
控制台效果:
再次执行效果: