网站页面设计制作,常德百度推广,建设网站费用评估,网站制作的原因什么是工作流#xff1f;
业务流程。
举个例子:
假设有一个在线博客平台#xff0c;我们要让一篇新的文章从作者的头脑里发表出来。整个过程可以分为以下几个步骤#xff1a;
创建文章草稿
#xff1a;作者登录博客平台#xff0c;点击“写新文章”的按钮#xff0c…什么是工作流
业务流程。
举个例子:
假设有一个在线博客平台我们要让一篇新的文章从作者的头脑里发表出来。整个过程可以分为以下几个步骤
创建文章草稿
作者登录博客平台点击“写新文章”的按钮开始写文章。这篇文章的状态是“草稿”还没有发布。
编辑和审阅
作者写完后可以选择把文章给编辑团队看。编辑们会读文章提供建议和修改意见。文章还是“草稿”状态。
修改文章
作者按照编辑的意见进行修改并再次提交给编辑。这个过程可能需要多轮修改直到编辑满意为止。
审稿
编辑确认文章没有问题后会将文章交给审稿人员。审稿人员会仔细检查文章内容确保没有错误或问题。
发布文章
经过审稿人员的确认文章会被标记为“已发布”并在博客平台上公开展示给读者们。
这样一篇文章就从作者的构思经过编辑和审稿最终发布到博客平台上了。这个过程就是一个简单的工作流。
工作流的实现演变
在没有专门的工作流引擎之前我们之前为了实现流程控制通常的做法就是采用状态字段的值来跟踪流程的变化情况。这样不用角色的用户通过状态字段的取值来决定记录是否显示。
这是一种最为原始的方式。通过状态字段虽然做到了流程控制但是当我们的流程发生变更的时候这种方式所编写的代码也要进行调整。比如提交一个审批一个小组长跟一个小职员的流程是不一样的。那逻辑就复杂了。
Activiti7概述
Activiti是一个工作流引擎 activiti可以将业务系统中复杂的业务流程抽取出来使用专门的建模语言BPMN2.0进行定义业务流程按照预先定义的流程进行执行实现了系统的流程由activiti进行管理减少业务系统由于流程变更进行系统升级改造的工作量从而提高系统的健壮性同时也减少了系统开发维护成本。
官方网站
Open Source Business Automation | Activiti
BPM
BPMBusiness Process Management即业务流程管理是一种规范化的构造端到端的业务流程以持续的提高组织业务效率。
BPMN
BPMN是一种用来描述业务流程的图形化表示方法。它可以帮助企业和组织更好地理解、分析和改进自己的业务流程。 BPMN 是目前被各 BPM 厂商广泛接受的 BPM 标准。Activiti 就是使用 BPMN 2.0 进行流程建模、流程执行管理它包括很多的建模符号比如
Event
用一个圆圈表示、它是流程在运行中发生的事件 活动用圆角矩形表示一个流程由一个活动或多个活动组成 Actviti的使用步骤
1、集成Activiti
Activiti是一个工作流引擎其实就是一堆jar包API业务系统访问(操作)activiti的接口就可以方便的操作流程相关数据这样就可以把工作流环境与业务系统的环境集成在一起。
2、流程定义
使用activiti流程建模工具(activity-designer)定义业务流程(.bpmn文件) 。
.bpmn文件就是业务流程定义文件通过xml定义业务流程。
3、流程定义部署
activiti部署业务流程定义.bpmn文件。
使用activiti提供的api把流程定义内容存储起来在Activiti执行过程中可以查询定义的内容
Activiti执行把流程定义内容存储在数据库中
4、启动一个流程实例
流程实例也叫ProcessInstance
启动一个流程实例表示开始一次业务流程的运行。
在员工请假流程定义部署完成后如果张三要请假就可以启动一个流程实例如果李四要请假也启动一个流程实例两个流程的执行互相不影响。
5、用户查询待办任务(Task)
因为现在系统的业务流程已经交给activiti管理通过activiti就可以查询当前流程执行到哪了当前用户需要办理什么任务了这些activiti帮我们管理了而不需要开发人员自己编写在sql语句查询。
6、用户办理任务
用户查询待办任务后就可以办理某个任务如果这个任务办理完成还需要其它用户办理比如采购单创建后由部门经理审核这个过程也是由activiti帮我们完成了。
7、流程结束
当任务办理完成没有下一个任务结点了这个流程实例就完成了。
创建Activiti需要的表 1 创建一个springboot的工程。
2 导入依赖 maven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetslf4j.version1.6.6/slf4j.versionlog4j.version1.2.12/log4j.versionactiviti.version7.0.0.Beta1/activiti.version
/propertiesdependenciesdependencygroupIdorg.activiti/groupIdartifactIdactiviti-engine/artifactIdversion${activiti.version}/version/dependencydependencygroupIdorg.activiti/groupIdartifactIdactiviti-spring/artifactIdversion${activiti.version}/version/dependency!-- bpmn 模型处理 --dependencygroupIdorg.activiti/groupIdartifactIdactiviti-bpmn-model/artifactIdversion${activiti.version}/version/dependency!-- bpmn 转换 --dependencygroupIdorg.activiti/groupIdartifactIdactiviti-bpmn-converter/artifactIdversion${activiti.version}/version/dependency!-- bpmn json数据转换 --dependencygroupIdorg.activiti/groupIdartifactIdactiviti-json-converter/artifactIdversion${activiti.version}/version/dependency!-- bpmn 布局 --dependencygroupIdorg.activiti/groupIdartifactIdactiviti-bpmn-layout/artifactIdversion${activiti.version}/version/dependency!-- activiti 云支持 --dependencygroupIdorg.activiti.cloud/groupIdartifactIdactiviti-cloud-services-api/artifactIdversion${activiti.version}/version/dependency!-- mysql驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.40/version/dependency!-- mybatis-plus --dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.1/version/dependency!-- 链接池 --dependencygroupIdcommons-dbcp/groupIdartifactIdcommons-dbcp/artifactIdversion1.4/version/dependency
/dependencies
3 新建application.yml
spring:datasource:username: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driver
4 新建activiti.cfg.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://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!-- 这里可以使用 链接池 dbcp--bean iddataSource classorg.apache.commons.dbcp.BasicDataSourceproperty namedriverClassName valuecom.mysql.jdbc.Driver /property nameurl valuejdbc:mysql:///activiti-demo /property nameusername valueroot /property namepassword valueroot /property namemaxActive value3 /property namemaxIdle value1 //beanbean idprocessEngineConfigurationclassorg.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration!-- 引用数据源 上面已经设置好了--property namedataSource refdataSource /!-- activiti数据库表处理策略 --property namedatabaseSchemaUpdate valuetrue//bean/beans
5 创建测试类执行方法
package cn.swj.activiti;import cn.swj.activity.ActivitiDemoApplication;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;/*** Author swj* Date 2023/7/20 11:03* Description: TODO* Version 1.0*/
SpringBootTest(classes ActivitiDemoApplication.class)
RunWith(SpringRunner.class)
public class ActivitiDemoTest {/*** 生成 activiti的数据库表*/Testpublic void testCreateDbTable() {//使用classpath下的activiti.cfg.xml中的配置创建processEngineProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();System.out.println(processEngine);}
}
表结构的介绍
ACT_RE : RE表示 repository。 这个前缀的表包含了流程定义和流程静态资源 图片规则等等。
ACT_RURU表示 runtime。 这些运行时的表包含流程实例任务变量异步任务等运行中的数据。 Activiti 只在流程实例执行过程中保存这些数据 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_HIHI表示 history。 这些表包含历史数据比如历史流程实例 变量任务等等。
ACT_GE GE 表示 general。 通用数据 用于不同场景下 表分类 表名 解释 一般数据 [ACT_GE_BYTEARRAY] 通用的流程定义和流程资源 [ACT_GE_PROPERTY] 系统相关属性 流程历史记录 [ACT_HI_ACTINST] 历史的流程实例 [ACT_HI_ATTACHMENT] 历史的流程附件 [ACT_HI_COMMENT] 历史的说明性信息 [ACT_HI_DETAIL] 历史的流程运行中的细节信息 [ACT_HI_IDENTITYLINK] 历史的流程运行过程中用户关系 [ACT_HI_PROCINST] 历史的流程实例 [ACT_HI_TASKINST] 历史的任务实例 [ACT_HI_VARINST] 历史的流程运行中的变量信息 流程定义表 [ACT_RE_DEPLOYMENT] 部署单元信息 [ACT_RE_MODEL] 模型信息 [ACT_RE_PROCDEF] 已部署的流程定义 运行实例表 [ACT_RU_EVENT_SUBSCR] 运行时事件 [ACT_RU_EXECUTION] 运行时流程执行实例 [ACT_RU_IDENTITYLINK] 运行时用户关系信息存储任务节点与参与者的相关信息 [ACT_RU_JOB] 运行时作业 [ACT_RU_TASK] 运行时任务 [ACT_RU_VARIABLE] 运行时变量表 Activiti的六大Service服务
RepositoryService 仓储服务
Autowired
private RepositoryService repositoryService;
仓储服务可以用来部署我们的流程图还可以创建我们的流程部署查询对象用于查询刚刚部署的流程列表便于我们的管理流程方法如下。
主要操作流程部署、流程定义
Autowired
private RepositoryService repositoryService;/*** 部署流程部署**/
Test
public void createDeployment() {//1、使用RepositoryService进行部署Deployment deployment repositoryService.createDeployment().addClasspathResource(bpmn/test.bpmn20.xml) // 添加bpmn资源.name(出差申请流程).deploy();log.info(DeploymentId ---------- {},deployment.getId());log.info(DeploymentName ---------- {},deployment.getName());}/*** 查询所有流程部署**/
Test
public void list() {DeploymentQuery deploymentQuery repositoryService.createDeploymentQuery();ListDeployment list deploymentQuery.list();list.forEach(System.out::println);
}/*** 根据名字查询流程部署**/
Test
public void listByName() {DeploymentQuery deploymentQuery repositoryService.createDeploymentQuery();deploymentQuery.deploymentNameLike(%出差%);ListDeployment list deploymentQuery.list();list.forEach(System.out::println);
}/*** 删除流程部署**/
Test
public void delete() {//repositoryService.deleteDeployment(15001);repositoryService.deleteDeployment(15001,true);
}/*** 查询所有流程定义**/
Test
public void queryProcessDefinition() {ListProcessDefinition list repositoryService.createProcessDefinitionQuery().list();list.forEach(System.out::println);
}/*** 根据流程部署id查询所有流程定义**/
Test
public void queryProcessDefinitionByDeploymentId() {ListProcessDefinition list repositoryService.createProcessDefinitionQuery().deploymentId(15001).list();list.forEach(System.out::println);
}
RunTimeServce 运行时服务
运⾏时服务主要⽤来开启流程实例⼀个流程实例对应多个任务也就是多个流程节点⽐如请假审批是⼀个流程实例部⻔主管部⻔经理总经理都是节点我们开启服务是通过流程定义key或者流程定义id来开启的⽅法如下
主要操作开启流程实例
Autowired
private RuntimeService runtimeService;Autowired
private RepositoryService repositoryService;/*** 启动流程实例只能根据流程定义id或者流程定义key去启动实例**/
Test
public void startProcessInstance() {ProcessDefinition def repositoryService.createProcessDefinitionQuery().deploymentId(15001).singleResult();ProcessInstance processInstance runtimeService.startProcessInstanceById(def.getId());log.info(processInstanceId ------- {},processInstance.getId());log.info(deploymentId ------- {},processInstance.getProcessDefinitionId());log.info(activityId ------- {},processInstance.getActivityId());
}/*** 查询所有流程实例**/
Test
public void listProcessInstance() {ListProcessInstance processInstanceList runtimeService.createProcessInstanceQuery().processDefinitionId(test:1:15003).list();processInstanceList.forEach(System.out::println);
}/*** 开启流程实例的时候添加我们自己的业务id**/
Test
public void startWithSetBusinessKey() {//获取流程定义idProcessDefinition processDefinition repositoryService.createProcessDefinitionQuery().deploymentId(22501).singleResult();//启动实例ProcessInstance processInstance runtimeService.startProcessInstanceById(processDefinition.getId(), businessId);System.out.println(processInstance.getBusinessKey());
}
当我们⽤仓储服务部署了流程图之后就会产⽣⼀个流程部署id⼀个流程部署id对应⼀个流程定义⼀个流程定义对应多个流程实例流程定义和流程实例之间的关系就好⽐是类和对象的关系。⼀个流程实例对应多个任务节点。
TaskService 任务服务
主要操作 任务
任务服务是⽤来可以⽤来领取完成查询任务列表功能的使⽤⽅法分别如下 /*** //根据任务id和⽤户领取任务* taskService.claim(String taskId, String userId)* //根据任务id完成⾃⼰节点的任务* taskService.complete(String taskId)* //创建任务查询对象之后根据候选⼈也就是任务处理⼈查询⾃⼰的任务列表* taskService.createTaskQuery().taskAssignee(String assignee)*/Autowired
private TaskService taskService;/*** 查询流程实例的所有**/
Test
public void listTask() {ListTask taskList taskService.createTaskQuery().processDefinitionId(test:1:15003).taskAssignee(zhansan).list();taskList.forEach(System.out::println);
}/*** 完成自己的任务**/
Test
public void complete() {Task task taskService.createTaskQuery().taskAssignee(zhansan).processDefinitionId(test:1:15003).singleResult();taskService.complete(task.getId());
}
HistoryService 历史服务
主要操作历史信息
历史服务可以查看审批⼈曾经审批完成了哪些项⽬审批项⽬总共花了多少时间以及在哪个环节⽐较耗费时间等等便于审批⼈查看历史信息⽅法如下。
Autowired
private HistoryService historyService;Test
public void listTaskByAssignee() {ListHistoricTaskInstance list historyService.createHistoricTaskInstanceQuery().taskAssignee(zhansan).finished().list();for (HistoricTaskInstance taskInstance : list) {System.out.println(taskInstance.getId());System.out.println(taskInstance.getName());System.out.println(taskInstance.getProcessDefinitionId());System.out.println(taskInstance.getProcessInstanceId());System.out.println(taskInstance.getWorkTimeInMillis());System.out.println();}
}
DynamicBpmnService 修改流程定义的服务
在Activiti中DynamicBpmnService 是一个用于动态修改和更新流程定义BPMN模型的服务。它允许您在流程部署后通过编程方式对已部署的流程定义进行修改添加或删除流程元素而无需重新部署整个流程。
使用 DynamicBpmnService 可以实现以下功能
修改流程元素
您可以在运行时通过 DynamicBpmnService 修改已部署的流程的各种元素如任务、连接线、条件等。这对于需要根据运行时条件调整流程逻辑的场景非常有用。
动态添加任务
您可以通过 DynamicBpmnService 动态地向流程中添加任务、网关、事件等元素从而在不停机的情况下扩展或调整流程的功能。
删除任务
如果需要您也可以使用 DynamicBpmnService 从已部署的流程定义中删除任务或其他元素以适应业务变化。
流程优化
可以使用该服务来进行流程优化以实现更高效的业务流程。
总之DynamicBpmnService 提供了一种在流程运行时进行动态流程定义修改的机制使您能够根据实际需求对已部署的流程进行灵活调整而无需重新部署整个流程。这对于灵活性和快速响应业务变化是非常有帮助的。需要注意的是虽然这种动态修改流程的能力非常强大但也需要小心使用以确保不会引入意外的问题。
ManagementService 管理和监控引擎运行时状态的服务
在Activiti中ManagementService 是一个用于管理和监控引擎运行时状态的服务。它提供了一些用于管理和监控流程引擎的操作使您能够以编程方式执行一些管理任务而无需直接访问底层的数据库或进行复杂的配置。
ManagementService 提供了一系列方法用于执行以下操作
作业管理
ManagementService 允许您管理作业jobs这些作业用于异步执行一些任务如定时器触发的事件。您可以查询、挂起、恢复、删除和重新执行作业。
流程实例删除
您可以使用 ManagementService 删除特定的流程实例不管其当前的状态。
数据库操作
ManagementService 提供了一些方法来执行数据库操作如执行原生的SQL查询。
清理历史数据
您可以使用 ManagementService 执行一些历史数据的清理操作以便维护数据库性能。
引擎配置
您可以获取和修改引擎的配置信息如数据库表前缀等。
执行异步操作
ManagementService 提供了一些方法来执行一些耗时的操作如数据的导入和导出。
需要注意的是ManagementService 提供的操作通常是对引擎运行时状态进行管理和维护的这些操作可能具有潜在的风险因此需要小心谨慎地使用。
总之ManagementService 是用于管理和监控Activiti引擎运行时状态的服务提供了一些管理操作和功能使您能够在运行时对引擎进行维护和管理。
Activiti入门
创建Activiti工作流主要包含以下几步
1、定义流程按照BPMN的规范使用流程定义工具用流程符号把整个流程描述出来
2、部署流程把画好的流程定义文件加载到数据库中生成表的数据
3、启动流程使用java代码来操作数据库表中的内容
流程符号
事件event 活动 Activity
活动是工作或任务的一个通用术语。一个活动可以是一个任务还可以是一个当前流程的子处理流程 其次你还可以为活动指定不同的类型。常见活动如下 网关 GateWay
网关用来处理决策有几种常用网关需要了解 排他网关 (x)
——只有一条路径会被选择。流程执行到该网关时按照输出流的顺序逐个计算当条件的计算结果为true时继续执行当前网关的输出流
如果多条线路计算结果都是 true则会执行第一个值为 true 的线路。如果所有网关计算结果没有true则引擎会抛出异常。
排他网关需要和条件顺序流结合使用default 属性指定默认顺序流当所有的条件不满足时会执行默认顺序流。
并行网关 ()
——所有路径会被同时选择
拆分 —— 并行执行所有输出顺序流为每一条顺序流创建一个并行执行线路。
合并 —— 所有从并行网关拆分并执行完成的线路均在此等候直到所有的线路都执行完成才继续向下执行。
包容网关 ()
—— 可以同时执行多条线路也可以在网关上设置条件
拆分 —— 计算每条线路上的表达式当表达式计算结果为true时创建一个并行线路并继续执行
合并 —— 所有从并行网关拆分并执行完成的线路均在此等候直到所有的线路都执行完成才继续向下执行。
事件网关 ()
—— 专门为中间捕获事件设置的允许设置多个输出流指向多个不同的中间捕获事件。当流程执行到事件网关后流程处于等待状态需要等待抛出事件才能将等待状态转换为活动状态。
流向 Flow
流是连接两个流程节点的连线。常见的流向包含以下几种 入门程序
安装activiti BPM visualizer 先画一个流程文件 画出来这个 //部署流程定义
//1、创建ProcessEngine
ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();
//2、得到RepositoryService实例
RepositoryService repositoryService processEngine.getRepositoryService();
//3、使用RepositoryService进行部署
Deployment deployment repositoryService.createDeployment().addClasspathResource(bpmn/test.bpmn20.xml) // 添加bpmn资源.name(出差申请流程).deploy();
//4、输出部署信息
System.out.println(流程部署id deployment.getId());
System.out.println(流程部署名称 deployment.getName()); 流程定义部署在activiti后就可以通过工作流管理业务流程了也就是说上边部署的出差申请流程可以使用了。
针对该流程启动一个流程表示发起一个新的出差申请单这就相当于java类与java对象的关系类定义好后需要new创建一个对象使用当然可以new多个对象。对于请出差申请流程张三发起一个出差申请单需要启动一个流程实例出差申请单发起一个出差单也需要启动一个流程实例。
代码如下
/*** 启动流程实例*/
Test
public void testStartProcess(){//1、创建ProcessEngineProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();//2、获取RunTimeServiceRuntimeService runtimeService processEngine.getRuntimeService();//3、根据流程定义Id启动流程ProcessInstance processInstance runtimeService.startProcessInstanceByKey(test);//输出内容System.out.println(流程定义id processInstance.getProcessDefinitionId());System.out.println(流程实例id processInstance.getId());System.out.println(当前活动Id processInstance.getActivityId());
} 流程启动后任务的负责人就可以查询自己当前需要处理的任务查询出来的任务都是该用户的待办任务。
/*** 查询当前个人待执行的任务*/Testpublic void testFindPersonalTaskList() {
// 任务负责人String assignee zhangsan;ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();
// 创建TaskServiceTaskService taskService processEngine.getTaskService();
// 根据流程key 和 任务负责人 查询任务ListTask list taskService.createTaskQuery().processDefinitionKey(test) //流程Key.taskAssignee(assignee)//只查询该任务负责人的任务.list();for (Task task : list) {System.out.println(流程实例id task.getProcessInstanceId());System.out.println(任务id task.getId());System.out.println(任务负责人 task.getAssignee());System.out.println(任务名称 task.getName());}} 任务负责人查询待办任务选择任务进行处理完成任务。
// 完成任务Testpublic void completTask(){
// 获取引擎ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();
// 获取taskServiceTaskService taskService processEngine.getTaskService();// 根据流程key 和 任务的负责人 查询任务
// 返回一个任务对象Task task taskService.createTaskQuery().processDefinitionKey(test) //流程Key.taskAssignee(lishi) //要查询的负责人.singleResult();// 完成任务,参数任务idtaskService.complete(task.getId());}
查询流程相关信息包含流程定义流程部署流程定义版本
/*** 查询流程定义*/Testpublic void queryProcessDefinition(){// 获取引擎ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();
// repositoryServiceRepositoryService repositoryService processEngine.getRepositoryService();
// 得到ProcessDefinitionQuery 对象ProcessDefinitionQuery processDefinitionQuery repositoryService.createProcessDefinitionQuery();
// 查询出当前所有的流程定义
// 条件processDefinitionKey evection
// orderByProcessDefinitionVersion 按照版本排序
// desc倒叙
// list 返回集合ListProcessDefinition definitionList processDefinitionQuery.processDefinitionKey(test).orderByProcessDefinitionVersion().desc().list();
// 输出流程定义信息for (ProcessDefinition processDefinition : definitionList) {System.out.println(流程定义 idprocessDefinition.getId());System.out.println(流程定义 nameprocessDefinition.getName());System.out.println(流程定义 keyprocessDefinition.getKey());System.out.println(流程定义 VersionprocessDefinition.getVersion());System.out.println(流程部署ID processDefinition.getDeploymentId());}} /*** 删除流程**/
Test
public void deleteDeployment() {// 流程部署idString deploymentId 1;ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();// 通过流程引擎获取repositoryServiceRepositoryService repositoryService processEngine.getRepositoryService();//删除流程定义如果该流程定义已有流程实例启动则删除时出错repositoryService.deleteDeployment(deploymentId,true);//设置true 级联删除流程定义即使该流程有流程实例启动也可以删除设置为false非级别删除方式如果流程//repositoryService.deleteDeployment(deploymentId, true);
}
说明
1) 使用repositoryService删除流程定义历史表信息不会被删除
2) 如果该流程定义下没有正在运行的流程则可以用普通删除。
如果该流程定义下存在已经运行的流程使用普通删除报错可用级联删除方法将流程及相关记录全部删除。
先删除没有完成流程节点最后就可以完全删除流程定义信息
项目开发中级联删除操作一般只开放给超级管理员使用. //下载文件Testpublic void queryBpmnFile() throws IOException {
// 1、得到引擎ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();
// 2、获取repositoryServiceRepositoryService repositoryService processEngine.getRepositoryService();
// 3、得到查询器ProcessDefinitionQuery设置查询条件,得到想要的流程定义ProcessDefinition processDefinition repositoryService.createProcessDefinitionQuery().processDefinitionKey(myEvection).singleResult();
// 4、通过流程定义信息得到部署IDString deploymentId processDefinition.getDeploymentId();
// 5、通过repositoryService的方法实现读取图片信息和bpmn信息
// png图片的流InputStream pngInput repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
// bpmn文件的流InputStream bpmnInput repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());
// 6、构造OutputStream流File file_png new File(d:/evectionflow01.png);File file_bpmn new File(d:/evectionflow01.bpmn);FileOutputStream bpmnOut new FileOutputStream(file_bpmn);FileOutputStream pngOut new FileOutputStream(file_png);
// 7、输入流输出流的转换IOUtils.copy(pngInput,pngOut);IOUtils.copy(bpmnInput,bpmnOut);
// 8、关闭流pngOut.close();bpmnOut.close();pngInput.close();bpmnInput.close();} 即使流程定义已经删除了流程执行的历史信息通过前面的分析依然保存在activiti的act_hi_*相关的表中。所以我们还是可以查询流程执行的历史信息可以通过HistoryService来查看相关的历史记录。
/*** 查看历史信息*/Testpublic void findHistoryInfo(){
// 获取引擎ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();
// 获取HistoryServiceHistoryService historyService processEngine.getHistoryService();
// 获取 actinst表的查询对象HistoricActivityInstanceQuery instanceQuery historyService.createHistoricActivityInstanceQuery();
// 查询 actinst表条件根据 InstanceId 查询
// instanceQuery.processInstanceId(2501);
// 查询 actinst表条件根据 查询instanceQuery.processDefinitionId(test:1:3);
// 增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
// 查询所有内容ListHistoricActivityInstance activityInstanceList instanceQuery.list();
// 输出for (HistoricActivityInstance hi : activityInstanceList) {System.out.println(hi.getActivityId());System.out.println(hi.getActivityName());System.out.println(hi.getProcessDefinitionId());System.out.println(hi.getProcessInstanceId());System.out.println();}}
流程实例绑定业务id
Activiti提供的数据是针对于该框架所需要的流程控制维护的数据也就是数据库25张表存放的数据但是在业务系统中业务数据如何与Activiti框架进⾏关联通过流程实例数据的BusinessKey字段来实现关联。在创建流程实例时指明BusinessKey即可。
示例代码 /*** 开启流程实例的时候添加我们自己的业务id**/
Test
public void startWithSetBusinessKey() {//获取流程定义idProcessDefinition processDefinition repositoryService.createProcessDefinitionQuery().deploymentId(22501).singleResult();//启动实例ProcessInstance processInstance runtimeService.startProcessInstanceById(processDefinition.getId(), businessId);System.out.println(processInstance.getBusinessKey());
}
流程实例的挂起跟激活
当因为业务需要将执⾏的流程挂起或者将已被挂起的流程激活可以通过Activiti框架对流程进⾏挂起和激活。
Test
public void processInstanceIsSuspended() {//获取流程定义idProcessDefinition def repositoryService.createProcessDefinitionQuery().deploymentId(22501).singleResult();//1、获取流程实例ProcessInstance processInstance runtimeService.createProcessInstanceQuery().processDefinitionId(def.getId()).singleResult();boolean suspended processInstance.isSuspended();//如果激活if(!suspended) {//挂起实例runtimeService.suspendProcessInstanceById(processInstance.getId());}//如果挂起if(suspended) {//激活实例runtimeService.activateProcessInstanceById(processInstance.getId());}}
使⽤变量设置Assignee
1、在画流程图的时候需要在assignee那边写一个插值表达式
${assginee0}
2、在创建实例的时候new一个Map在值存到里面并将map作为值传入创建实例的方法中
示例代码 Test
public void createProcessInstanceWithCustomAssignee() {//1、获取流程定义idProcessDefinition def repositoryService.createProcessDefinitionQuery().deploymentId(30001).singleResult();//2、新建一个流程实例MapString, Object map new HashMap();map.put(assignee0,zhangsan);map.put(assignee1,lishi);map.put(assignee2,wangwu);ProcessInstance processInstance runtimeService.startProcessInstanceById(def.getId(), map);System.out.println(processInstance.getId());}
使⽤变量驱动流程⾛向 一样使用插值表达式
Test
public void createProcessInstanceWithCustomAssignee() {//1、获取流程定义idProcessDefinition def repositoryService.createProcessDefinitionQuery().deploymentId(30001).singleResult();//2、新建一个流程实例MapString, Object map new HashMap();map.put(assignee0,zhangsan);map.put(assignee1,lishi);map.put(assignee2,wangwu);map.put(days,3);ProcessInstance processInstance runtimeService.startProcessInstanceById(def.getId(), map);System.out.println(processInstance.getId());}
使⽤Local局部变量
有的变量只是在某个节点会使用到这样子就可以直接使用局部变量
Test
public void localVariable() {taskService.setVariableLocal(123,day,3);taskService.complete(123);
}
组任务
如果任务负责⼈是单⼀存在的且任务负责⼈因为默写原因没有办法完成任务那么流程就没办法执⾏下去了。此时可以为任务设置候选⼈通过候选⼈拾取、执⾏、归还等操作完成组任务相关的操作
任务候选⼈
创建任务候选⼈允许⼀个任务可以被多个负责⼈领取。通过流程图或者程序来指明任务的候选⼈。查询候选⼈查询任务的代码如下 可以通过去候选人去查询任务
ListTask list taskService.createTaskQuery().processDefinitionId(defId).taskCandidateOrAssigned(候选人或者责任人).list();
候选⼈拾取任务
任务候选⼈先拾取任务才能执⾏任务
Task task taskService.createTaskQuery().processDefinitionId(defId).taskCandidateUser(候选人).singleResult();taskService.claim(task.getId(),候选人);
候选⼈归还任务
候选⼈拾取任务后在没执⾏任务之前可以归还任务
Task task taskService.createTaskQuery().processDefinitionId(defId).taskCandidateUser(候选人).singleResult();taskService.setAssignee(task.getId(),null);
任务转交
任务候选⼈拾取完任务后可以选择归还任务也可以选择把任务转交给其他候选⼈。
Task task taskService.createTaskQuery().processDefinitionId(defId).taskCandidateUser(候选人).singleResult();taskService.setAssignee(task.getId(),otherUser);
SpringBoot整合Activiti7入门案例
1、创建一个SpringBoot工程
parentartifactIdspring-boot-starter-parent/artifactIdgroupIdorg.springframework.boot/groupIdversion2.3.9.RELEASE/versionrelativePath/
/parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.8.14/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency
/dependencies
2、导入依赖
propertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetactiviti.version7.0.0.Beta1/activiti.version
/propertiesdependenciesdependencygroupIdorg.activiti/groupIdartifactIdactiviti-spring-boot-starter/artifactIdversion${activiti.version}/version/dependency!-- mysql驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.40/version/dependency!-- mybatis-plus --dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.1/version/dependency!-- 链接池 --dependencygroupIdcommons-dbcp/groupIdartifactIdcommons-dbcp/artifactIdversion1.4/version/dependency
/dependencies
3、新建俩个配置文件
数据库连接信息根据自己的信息进行修改
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://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!-- 这里可以使用 链接池 dbcp--bean iddataSource classorg.apache.commons.dbcp.BasicDataSourceproperty namedriverClassName valuecom.mysql.jdbc.Driver /property nameurl valuejdbc:mysql:///activiti-demo /property nameusername valueroot /property namepassword valueroot /property namemaxActive value3 /property namemaxIdle value1 //beanbean idprocessEngineConfigurationclassorg.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration!-- 引用数据源 上面已经设置好了--property namedataSource refdataSource /!-- activiti数据库表处理策略 --property namedatabaseSchemaUpdate valuetrue//bean/beans
spring:datasource:username: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driveractiviti:database-schema-update: truedb-history-used: truehistory-level: full
4、在resource下新建一个processes目录 5、初始化bean
package cn.swj.activity.config;import org.activiti.engine.*;
import org.activiti.engine.test.ActivitiRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Author swj* Date 2023/8/5 16:22* Description: TODO* Version 1.0*/
Configuration
public class ActivitiConfig {//创建ProcessEngineprivate ProcessEngine processEngine ProcessEngines.getDefaultProcessEngine();Beanpublic RepositoryService repositoryService() {//1、得到RepositoryService实例RepositoryService repositoryService processEngine.getRepositoryService();return repositoryService;}Beanpublic RuntimeService runtimeService() {//1、得到 RuntimeService 实例RuntimeService runtimeService processEngine.getRuntimeService();return runtimeService;}Beanpublic TaskService taskService() {//1、得到 TaskService 实例TaskService taskService processEngine.getTaskService();return taskService;}Beanpublic HistoryService historyService() {//1、得到 TaskService 实例HistoryService historyService processEngine.getHistoryService();return historyService;}Beanpublic DynamicBpmnService dynamicBpmnService() {//1、得到 DynamicBpmnService 实例DynamicBpmnService dynamicBpmnService processEngine.getDynamicBpmnService();return dynamicBpmnService;}Beanpublic ManagementService managementService() {//1、得到 ManagementService 实例ManagementService managementService processEngine.getManagementService();return managementService;}}
6、安装插件 7、画一个流程图
在resource\processes下新建一个流程图 ?xml version1.0 encodingUTF-8?
definitions xmlnshttp://www.omg.org/spec/BPMN/20100524/MODEL xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:xsdhttp://www.w3.org/2001/XMLSchema xmlns:activitihttp://activiti.org/bpmn xmlns:bpmndihttp://www.omg.org/spec/BPMN/20100524/DI xmlns:omgdchttp://www.omg.org/spec/DD/20100524/DC xmlns:omgdihttp://www.omg.org/spec/DD/20100524/DI typeLanguagehttp://www.w3.org/2001/XMLSchema expressionLanguagehttp://www.w3.org/1999/XPath targetNamespacehttp://www.activiti.org/processdefprocess idleave nameleave isExecutabletruestartEvent idsid-b2417e62-b70b-4f06-90b4-4a9c453e7ebc/endEvent idsid-a25bc48b-1191-413d-a0ab-263c2d27793b/userTask idsid-37861cb6-80d2-45dc-9b50-375ad320a01f name员工提交请假申请 activiti:assignee${assignee0}/userTask idsid-b6df96ad-44df-4295-bbe6-c74ab4cf7f7e name上级领导审批 activiti:assignee${assignee1}/userTask idsid-204ae414-37c9-47e2-a84b-bd34dcb7463a name人事记录 activiti:assignee${assignee2}/sequenceFlow idsid-effa22e4-daaa-4508-9628-7906e9bfd274 sourceRefsid-b2417e62-b70b-4f06-90b4-4a9c453e7ebc targetRefsid-37861cb6-80d2-45dc-9b50-375ad320a01f/sequenceFlow idsid-2a2c5aa6-2f52-4963-9ca4-f63412cd8b67 sourceRefsid-37861cb6-80d2-45dc-9b50-375ad320a01f targetRefsid-b6df96ad-44df-4295-bbe6-c74ab4cf7f7e/sequenceFlow idsid-24db9d32-2541-41a3-84e4-1228f1b1e806 sourceRefsid-b6df96ad-44df-4295-bbe6-c74ab4cf7f7e targetRefsid-204ae414-37c9-47e2-a84b-bd34dcb7463a/sequenceFlow idsid-fda019e5-a786-441a-b226-22993b36c82a sourceRefsid-204ae414-37c9-47e2-a84b-bd34dcb7463a targetRefsid-a25bc48b-1191-413d-a0ab-263c2d27793b//processbpmndi:BPMNDiagram idBPMNDiagram_leavebpmndi:BPMNPlane bpmnElementleave idBPMNPlane_leavebpmndi:BPMNShape idshape-27b24655-a3d8-4cb6-b1e2-d94f9382dfc9 bpmnElementsid-b2417e62-b70b-4f06-90b4-4a9c453e7ebcomgdc:Bounds x-70.0 y-145.0 width30.0 height30.0//bpmndi:BPMNShapebpmndi:BPMNShape idshape-f86c2c60-9f01-4430-943e-ea5232d724df bpmnElementsid-a25bc48b-1191-413d-a0ab-263c2d27793bomgdc:Bounds x-75.0 y200.0 width30.0 height30.0//bpmndi:BPMNShapebpmndi:BPMNShape idshape-ac9635c3-16cb-42e3-a5dc-ed54f96a2d47 bpmnElementsid-37861cb6-80d2-45dc-9b50-375ad320a01fomgdc:Bounds x-110.0 y-95.0 width100.0 height80.0//bpmndi:BPMNShapebpmndi:BPMNShape idsid-b8b9d748-c04f-4624-b13b-5ad6367d5f84 bpmnElementsid-b6df96ad-44df-4295-bbe6-c74ab4cf7f7eomgdc:Bounds x-110.0 y0.95951843 width100.0 height80.0//bpmndi:BPMNShapebpmndi:BPMNShape idsid-9a68376e-da4c-464a-be4e-c2d48feaf397 bpmnElementsid-204ae414-37c9-47e2-a84b-bd34dcb7463aomgdc:Bounds x-110.0 y94.34161 width100.0 height80.0//bpmndi:BPMNShapebpmndi:BPMNEdge idedge-3dc5ee67-24c6-475f-9fb9-dbffa94892f7 bpmnElementsid-effa22e4-daaa-4508-9628-7906e9bfd274omgdi:waypoint x-62.5 y-115.0/omgdi:waypoint x-60.0 y-95.0//bpmndi:BPMNEdgebpmndi:BPMNEdge idedge-ddc9236c-49bd-410b-b40b-a99899d08eef bpmnElementsid-2a2c5aa6-2f52-4963-9ca4-f63412cd8b67omgdi:waypoint x-60.0 y-15.0/omgdi:waypoint x-60.0 y0.95951843//bpmndi:BPMNEdgebpmndi:BPMNEdge idedge-002614a7-62e7-4307-b60e-855b2863b828 bpmnElementsid-24db9d32-2541-41a3-84e4-1228f1b1e806omgdi:waypoint x-60.0 y80.95952/omgdi:waypoint x-60.0 y94.34161//bpmndi:BPMNEdgebpmndi:BPMNEdge idedge-afc8140f-3ffc-403e-9bbb-b62819df498b bpmnElementsid-fda019e5-a786-441a-b226-22993b36c82aomgdi:waypoint x-60.0 y174.34161/omgdi:waypoint x-60.0 y200.0//bpmndi:BPMNEdge/bpmndi:BPMNPlane/bpmndi:BPMNDiagram
/definitions
8、启动项目
9、编写测试用例
package cn.swj.activiti;import cn.hutool.core.util.ObjectUtil;
import cn.swj.activity.ActivitiDemoApplication;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.HashMap;/*** Author swj* Date 2023/8/6 16:12* Description: TODO* Version 1.0*/
Slf4j
SpringBootTest(classes ActivitiDemoApplication.class)
RunWith(SpringRunner.class)
public class SubmitLeaveTest {Autowiredprivate RepositoryService repositoryService;Autowiredprivate RuntimeService runtimeService;Autowiredprivate TaskService taskService;/*** 1、员工提交请假申请* 2、上级领导审批* 3、人事记录*//*** 员工提交请假申请**/Testpublic void submitLeave() {//1、创建流程实例//初始化流程里面的负责人信息HashMapString, Object map new HashMap();map.put(assignee0, zhangsan);map.put(assignee1, lishi);map.put(assignee2, wangwu);//创建实例ProcessDefinition def repositoryService.createProcessDefinitionQuery().deploymentId(d0d0f7c2-3439-11ee-83a8-cec84ba31bc7).singleResult();ProcessInstance processInstance runtimeService.startProcessInstanceById(def.getId(), map);//2、完成张三任务Task task taskService.createTaskQuery().deploymentId(d0d0f7c2-3439-11ee-83a8-cec84ba31bc7).taskAssignee(zhangsan).singleResult();if (ObjectUtil.isEmpty(task)) {return;}taskService.complete(task.getId());log.info(张三请假申请已经提交~);//3、完成李四的任务//查询李四的任务Task lishiTask taskService.createTaskQuery().deploymentId(d0d0f7c2-3439-11ee-83a8-cec84ba31bc7).taskAssignee(lishi).singleResult();if(ObjectUtil.isEmpty(lishiTask)) {return;}log.info(查询李四的任务 {}, lishiTask.getName());//完成taskService.complete(lishiTask.getId());//4、完成王五的任务//查询王五的任务Task wangwuTask taskService.createTaskQuery().deploymentId(d0d0f7c2-3439-11ee-83a8-cec84ba31bc7).taskAssignee(wangwu).singleResult();//完成if(ObjectUtil.isEmpty(wangwuTask)) {return;}log.info(查询王五的任务 {}, wangwuTask.getName());taskService.complete(wangwuTask.getId());log.info(流程结束~);}
}