Activiti6详细教程
一、为什么选择Activiti
activiti介绍 Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理,工作流,服务协作等领域的一个开源,灵活的,易扩展的可执行流程语言框架。
解决方案 | 优点 | 缺点 | 选型结果 | 选型原因 | |
---|---|---|---|---|---|
开源 |
Activiti JBPM Flowable |
开源 免费 |
开发工作量大 开发难度大 中文支持不好 |
Activiti |
相对JBPM上手容易 原生支持Spring 与 Spring boot 集成较好 Flowable新出的,使用人数少教程资源少 |
商用 |
炎黄盈动 普元 慧正 天翎 宏天 |
开发工作量小 开发难度小 符合中国国情 |
闭源 价格高 |
二、核心7大接口、28张表
(一)7大接口
- RepositoryService:提供一系列管理流程部署和流程定义的API。
- RuntimeService:在流程运行时对流程实例进行管理与控制。
- TaskService:对流程任务进行管理,例如任务提醒、任务完成和创建任务等。
- IdentityService:提供对流程角色数据进行管理的API,这些角色数据包括用户组、用户及它们之间的关系。
- ManagementService:提供对流程引擎进行管理和维护的服务。
- HistoryService:对流程的历史数据进行操作,包括查询、删除这些历史数据。
- FormService:表单服务。
(二)28张表
- act_ge_ 通用数据表,ge是general的缩写
- act_hi_ 历史数据表,hi是history的缩写,对应HistoryService接口
- act_id_ 身份数据表,id是identity的缩写,对应IdentityService接口
- act_re_ 流程存储表,re是repository的缩写,对应RepositoryService接口,存储流程部署和流程定义等静态数据
- act_ru_ 运行时数据表,ru是runtime的缩写,对应RuntimeService接口和TaskService接口,存储流程实例和用户任务等动态数据
表结构操作:
3.3.1:资源库流程规则表
- 1) act_re_deployment 部署信息表
- 2) act_re_model 流程设计模型部署表
- 3) act_re_procdef 流程定义数据表
3.3.2:运行时数据库表
- 1) act_ru_execution 运行时流程执行实例表
- 2) act_ru_identitylink 运行时流程人员表,主要存储任务节点与参与者的相关信息
- 3) act_ru_task 运行时任务节点表
- 4) act_ru_variable 运行时流程变量数据表
3.3.3:历史数据库表
- 1) act_hi_actinst 历史节点表
- 2) act_hi_attachment 历史附件表
- 3) act_ih_comment 历史意见表
- 4) act_hi_identitylink 历史流程人员表
- 5) act_hi_detail 历史详情表,提供历史变量的查询
- 6) act_hi_procinst 历史流程实例表
- 7) act_hi_taskinst 历史任务实例表
- 8) act_hi_varinst 历史变量表
3.3.4:组织机构表
- 1) act_id_group 用户组信息表
- 2) act_id_info 用户扩展信息表
- 3) act_id_membership 用户与用户组对应信息表
- 4) act_id_user 用户信息表
这四张表很常见,基本的组织机构管理,关于用户认证方面建议还是自己开发一套,组件自带的功能太简单,使用中有很多需求难以满足
3.3.5:通用数据表
- 1) act_ge_bytearray 二进制数据表
- 2) act_ge_property 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录,
- 3.4:activiti.cfg.xml(activiti的配置文件)
Activiti核心配置文件,配置流程引擎创建工具的基本参数和数据库连接池参数。
定义数据库配置参数:
- jdbcUrl: 数据库的JDBC URL。
- jdbcDriver: 对应不同数据库类型的驱动。
- jdbcUsername: 连接数据库的用户名。
- jdbcPassword: 连接数据库的密码。
基于JDBC参数配置的数据库连接 会使用默认的MyBatis连接池。 下面的参数可以用来配置连接池(来自MyBatis参数):
- jdbcMaxActiveConnections: 连接池中处于被使用状态的连接的最大值。默认为10。
- jdbcMaxIdleConnections: 连接池中处于空闲状态的连接的最大值。
- jdbcMaxCheckoutTime: 连接被取出使用的最长时间,超过时间会被强制回收。 默认为20000(20秒)。
- jdbcMaxWaitTime: 这是一个底层配置,让连接池可以在长时间无法获得连接时, 打印一条日志,并重新尝试获取一个连接。(避免因为错误配置导致沉默的操作失败)。 默认为20000(20秒)。
流程部署相关表
- act_re_deployement 部署对象表
- act_rep_procdef 流程定义表
- act_ge_bytearray 资源文件表
- act_ge_prperty 主键生成策略表(对于部署对象表的主键ID)
流程实例相关表
- act_ru_execution 正在执行的执行对象表(包含执行对象ID和流程实例ID,如果有多个线程可能流程实例ID不一样)
- act_hi_procinst 流程实例历史表
- act_hi_actinst 存放历史所有完成的任务
Task 任务相关表
- act_ru_task 代办任务表 (只对应节点是UserTask的)
- act_hi_taskinst 代办任务历史表 (只对应节点是UserTask的)
- act_hi_actinst 所有节点活动历史表 (对应流程的所有节点的活动历史,从开始节点一直到结束节点中间的所有节点的活动都会被记录)
流程变量表
- act_ru_variable 正在执行的流程变量表
- act_hi_variable 流程变量历史表
三、创建BPMN业务流程模型
1.将Activiti提供的流程设计器应用activiti-app.war部署到Tomcat的webapps目录。
2.创建新的MySql数据库。修改activiti-app\WEB-INF\classes\META-INF\activiti-app目录下的activiti-app.properties配置文件,默认使用H2内存数据库,创建的模型重启后会丢失,改成使用MySql数据库。
3.浏览器访问http://localhost:8080/activiti-app,登录账户:admin:test
4.创建一个请假审批流程图
给每个用户任务指派候选组(有权限执行当前任务的角色)
指派候选组
排他网关设置条件分支表达式
5.导出流程图为.bpmn20.xml文件
导出xml文件
四、Spring Boot与Activiti 6.0整合
1.在POM文件中添加依赖
<dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter-basic</artifactId><version>6.0.0</version>
</dependency>
2.将导出的.bpmn20.xml文件拷贝到项目文件夹/resources/processes下
3.application.properties文件添加配置项
spring.activiti.database-schema-update=true
databaseSchemaUpdate配置项可以设置流程引擎启动和关闭时数据库执行的策略。 databaseSchemaUpdate有以下四个值:
- false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配时,将在启动时抛出异常。
- true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。
- create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。
- drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。
4.启动应用,会在数据库里创建28张表,表创建好之后停止应用。application.properties文件修改配置项
#每次应用启动不检查Activiti数据表是否存在及版本号是否匹配,提升应用启动速度
spring.activiti.database-schema-update=false
5.application.properties文件增加配置项
#保存历史数据级别设置为full最高级别,便于历史数据的追溯
spring.activiti.history-level=full
对于历史数据,保存到何种粒度,Activiti提供了history-level属性对其进行配置。history-level属性有点像log4j的日志输出级别,该属性有以下四个值:
- none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
- activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
- audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
- full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
6.完成以上步骤,就可以在程序中使用自动注入的方式,使用Activiti的7大接口。
@Autowired
private RuntimeService runtimeService;@Autowired
private TaskService taskService;@Autowired
private IdentityService identityService;@Autowired
private RepositoryService repositoryService;@Autowired
private ProcessEngine processEngine;@Autowired
private HistoryService historyService;
5:核心API
5.1:ProcessEngine
说明:
1) 在Activiti中最核心的类,其他的类都是由他而来。
2) 产生方式:在前面看到了两种创建ProcessEngine(流程引擎)的方式,而这里要简化很多,调用ProcessEngines的getDefaultProceeEngine方法时会自动加载classpath下名为activiti.cfg.xml文件。
3) 可以产生RepositoryService4) 可以产生RuntimeService5) 可以产生TaskService各个Service的作用:
RepositoryService 管理流程定义
RuntimeService 执行管理,包括启动、推进、删除流程实例等操作
TaskService 任务管理
HistoryService 历史管理(执行完的数据的管理)
IdentityService 组织机构管理
FormService 一个可选服务,任务表单管理
ManagerService5.2:RepositoryService
是Activiti的仓库服务类。所谓的仓库指流程定义文档的两个文件:bpmn文件和流程图片。
1) 产生方式2) 可以产生DeploymentBuilder,用来定义流程部署的相关参数3) 删除流程定义5.3:RuntimeService
是activiti的流程执行服务类。可以从这个服务类中获取很多关于流程执行相关的信息。
5.4:TaskService
是activiti的任务服务类。可以从这个类中获取任务的信息。
5.5:HistoryService
是activiti的查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息。
5.6:ProcessDefinition
流程定义类。可以从这里获得资源文件等。
5.7:ProcessInstance
代表流程定义的执行实例。如范冰冰请了一天的假,她就必须发出一个流程实例的申请。一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。流程实例就表示一个流程从开始到结束的最大的流程分支,即一个流程中流程实例只有一个。
5.8:Execution
Activiti用这个对象去描述流程执行的每一个节点。在没有并发的情况下,Execution就是同ProcessInstance。流程按照流程定义的规则执行一次的过程,就可以表示执行对象Execution。
RepositoryService:管理流程定义RuntimeService:执行管理,包括启动、推进、删除流程实例等操作TaskService:任务管理HistoryService:历史管理(执行完的数据的管理)IdentityService:组织机构管理FormService:一个可选服务,任务表单管理ManagerService5.2:RepositoryService
是Activiti的仓库服务类。所谓的仓库指流程定义文档的两个文件:bpmn文件和流程图片。1) 产生方式2) 可以产生DeploymentBuilder,用来定义流程部署的相关参数3) 删除流程定义5.3:RuntimeService
是activiti的流程执行服务类。可以从这个服务类中获取很多关于流程执行相关的信息。5.4:TaskService
是activiti的任务服务类。可以从这个类中获取任务的信息。5.5:HistoryService
是activiti的查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息。5.6:ProcessDefinition
流程定义类。可以从这里获得资源文件等。5.7:ProcessInstance
代表流程定义的执行实例。如范冰冰请了一天的假,她就必须发出一个流程实例的申请。一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。流程实例就表示一个流程从开始到结束的最大的流程分支,即一个流程中流程实例只有一个。5.8:Execution
Activiti用这个对象去描述流程执行的每一个节点。在没有并发的情况下,Execution就是同ProcessInstance。流程按照流程定义的规则执行一次的过程,就可以表示执行对象Execution。
五、项目中的用户、角色与Activiti中的用户、用户组整合
每个项目都有自己的用户、角色表,Activiti也有自己的用户、用户组表。因此项目中的用户、角色与Activiti中的用户、用户组要做整合。
//项目中每创建一个新用户,对应的要创建一个Activiti用户
//两者的userId和userName一致
User admin=identityService.newUser("1");
admin.setLastName("admin");
identityService.saveUser(admin);//项目中每创建一个角色,对应的要创建一个Activiti用户组
Group adminGroup=identityService.newGroup("1");
adminGroup.setName("admin");
identityService.saveGroup(adminGroup);//用户与用户组关系绑定
identityService.createMembership("1","1");
六、请假审批流程
1.请假申请和请假审批数据库表设计
表设计原则:流程数据和业务数据相分离。Activiti相关表只负责流程的跳转、走向等。流程中产生的业务表单数据、审批意见、附件等存储在开发人员定义的业务表中。流程数据和业务数据之间通过processInstanceId(流程实例ID)和业务数据主键相互关联。
为什么不使用Activiti相关表来存储表单数据和附件?
activiti参数表
Activiti为了应用的灵活性和通用性采用了纵表的方式存储表单数据。假设一条请假申请表单数据有10个字段,那就需要10条记录存储原本横表只需要一条记录存储的数据。采用纵表的方式会有如下问题:
会有大量的冗余数据并且数据量会急剧的增长
查询语句复杂,查询效率低
尤其不适合做后期的统计报表分析
activiti附件表
Activiti存储附件使用Blob数据格式,文件存储在数据库里,数据库的数据文件会变得超大,不利于数据库备份和迁移。
请假申请表结构
请假申请表
请假审批表结构
请假审批表
2.填写请假申请表单,启动流程实例
填写请假申请
//启动流程实例,字符串"vacation"是BPMN模型文件里process元素的id
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacation");
//流程实例启动后,流程会跳转到请假申请节点
Task vacationApply = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
//设置请假申请任务的执行人
taskService.setAssignee(vacationApply.getId(), req.getUserId().toString());//设置流程参数:请假天数和表单ID
//流程引擎会根据请假天数days>3判断流程走向
//formId是用来将流程数据和表单数据关联起来
Map<String, Object> args = new HashMap<>();
args.put("days", req.getDays());
args.put("formId", formId);//完成请假申请任务
taskService.complete(vacationApply.getId(), args);
3.待审批列表
//查出当前登录用户所在的用户组
List<Group> groups = identityService.createGroupQuery().groupMember(String.valueOf(userId)).list();
List<String> groupNames = groups.stream().map(group -> group.getName()).collect(Collectors.toList());//查询用户组的待审批请假流程列表
List<Task> tasks = taskService.createTaskQuery().processDefinitionKey("vacation").taskCandidateGroupIn(groupNames).listPage(pageNum - 1, pageSize);//根据流程实例ID查询请假申请表单数据
List<String> processInstanceIds = tasks.stream().map(task -> task.getProcessInstanceId()).collect(Collectors.toList());
List<VacationApplyBasicPO> vacationApplyList = vacationRepository.getVacationApplyList(processInstanceIds);
4.请假审批功能
//查询当前审批节点
Task vacationAudit = taskService.createTaskQuery().taskId(req.getTaskId()).singleResult();if (req.getAuditResult() == 1) {//审批通过//设置流程参数:审批IDMap<String, Object> args = new HashMap<>();args.put("auditId", auditId);//设置审批任务的执行人taskService.claim(vacationAudit.getId(), req.getUserId().toString());//完成审批任务taskService.complete(vacationAudit.getId(), args);
} else {//审批不通过,结束流程runtimeService.deleteProcessInstance(vacationAudit.getProcessInstanceId(), auditId);
}
5.查看流程图功能
//controller层代码
@RequestMapping(value = "/image", method = RequestMethod.GET)
public void image(HttpServletResponse response,@RequestParam String processInstanceId) {try {InputStream is = vacationService.getDiagram(processInstanceId);if (is == null)return;response.setContentType("image/png");BufferedImage image = ImageIO.read(is);OutputStream out = response.getOutputStream();ImageIO.write(image, "png", out);is.close();out.close();} catch (Exception ex) {logger.error("查看流程图失败", ex);}
}//service层代码
@Override
public InputStream getDiagram(String processInstanceId) {//获得流程实例ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();String processDefinitionId = StringUtils.EMPTY;if (processInstance == null) {//查询已经结束的流程实例HistoricProcessInstance processInstanceHistory =historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();if (processInstanceHistory == null)return null;elseprocessDefinitionId = processInstanceHistory.getProcessDefinitionId();} else {processDefinitionId = processInstance.getProcessDefinitionId();}//使用宋体String fontName = "宋体";//获取BPMN模型对象BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);//获取流程实例当前的节点,需要高亮显示List<String> currentActs = Collections.EMPTY_LIST;if (processInstance != null)currentActs = runtimeService.getActiveActivityIds(processInstance.getId());return processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator().generateDiagram(model, "png", currentActs, new ArrayList<String>(),fontName, fontName, fontName, null, 1.0);
}
参照教程:https://blog.csdn.net/qq877507054/article/details/60143099
Activiti6详细教程相关推荐
- Activiti6.0教程 Eclipse安装Activiti Diagram插件(一)
最近这段时间打算出一个Activiti6.0的详细教程,Activiti作为一个流行的开源工作流引擎,正在不断发展,其6.0版本以API形式提供服务,而之前版本基本都是要求我们的应用以JDK方式与其交 ...
- 手把手从零开始搭建k8s集群超详细教程
本教程根据B站课程云原生Java架构师的第一课K8s+Docker+KubeSphere+DevOps同步所做笔记教程 k8s集群搭建超详细教程 1. 基本环境搭建 1. 创建私有网络 2. 创建服务 ...
- win10系统优化计算机,全面优化win10电脑系统详细教程 | 专业网吧维护
全面优化win10电脑系统详细教程 以下针对win10系统的电脑全面优化的步骤: 步骤1:禁止开机启动项 1.首先我们先来优化开机速度,拖慢开机速度的首先是开机自启动项,Ctrl + Shift + ...
- GPU运行Tensorflow详细教程及错误解决
GPU运行Tensorflow详细教程及错误解决 前提条件 配置GPU运行 确认是否成功配置 出现的错误及解决方案 前提条件 最重要的一点:CUDA与tensorflow的版本一点要对应,不然用不了! ...
- VMware虚拟机安装黑苹果MacOS Mojave系统详细教程
更多资源请百度搜索:前端资源网 欢迎关注我的博客:www.w3h5.com 最近遇到一个H5页面的 iPhone X 刘海兼容问题.查到一个 XCode 编辑器,可以模拟 iPhone X 环境运行. ...
- [分享] 从定制Win7母盘到封装详细教程 By BILL ( 10月23日补充说明 )
[分享] 从定制Win7母盘到封装详细教程 By BILL ( 10月23日补充说明 ) billcheung 发表于 2011-10-23 00:07:49 https://www.itsk.com ...
- win七系统如何卸载MySQL_win7系统卸载SQL2008R2数据库的详细教程
用过SQL2008R2数据库的朋友都知道,安装起来容易卸起来麻烦,可是在win7 32位旗舰版系统就不知道怎么卸载SQL2008R2数据库了.其实卸载SQL2008R2数据库的方法也很简单,可直接通过 ...
- Ubuntu系统安装搜狗输入法详细教程
Ubuntu16.04系统安装搜狗输入法详细教程 解决Ubuntu 18.04中文输入法的问题,安装搜狗拼音
- PHP7Grafika,PHP图片处理库Grafika详细教程(3):图像属性处理
该文章是接着上篇文章,<PHP极其强大的图片处理库Grafika详细教程(2):图像特效处理模块>,由于grafika功能太多,所以分开写,其他的点击这里 该文章主要写grafika的图像 ...
- mysql.msi卸载_MySql安装与卸载的详细教程
本文为大家分享了MySql安装与卸载的教程,供大家参考,具体内容如下 一.MYSQL的安装 1.打开下载的mysql安装文件,双击运行mysql-5.5.40-win32.msi. 2.选择安装类型, ...
最新文章
- align 的用法(u-boot源代码分析)
- mysql fabric安装使用测试
- Summer Tree 第六期完成
- CF296B dp\容斥
- python编译反编译,你不知道的心机与陷阱
- 牛津美女硕士放弃百万年薪,用废弃物做轻奢包,马斯克妈妈也来捧场
- 刘作虎:今年一加9系列不会送测DxO
- golang——channel笔记
- python按位处理二进制文件_对如何在python shell中对16位二进制数执行按位运算感到困惑...
- java验证码 验证
- VirtualBox下配置 Ubantu18.4 总纲领
- iOS/Android 微信及浏览器中唤起本地APP
- 5G室内覆盖面临四大挑战,如何破?
- CSS3精选内容通俗易懂
- docx4j操作word文档之生成页码、合并多个文档
- 关于FACEBOOK 的 REACT 专利许可证
- (附源码)springboot 房产中介系统 毕业设计 312341
- 《概率论与数理统计》-第二章 随机变量及其分布-第一节 离散型随机变量及其分布-笔记
- java sdk完整单机下载地址_Java SDK下载方法
- 下载 RealPlayer 失败
热门文章
- 学习爬虫的第三天 (bs4 \ urllib \ xlwt \ re 的练习爬取豆瓣top250保存成excel格式)
- 小智慧81:你和谁睡在一起
- 30 岁的超级玛丽怎样改变了游戏行业?
- 修改监视器驱动为大显示器来提高屏幕分辨率
- Android基础入门教程——7.6.3 基于TCP协议的Socket通信(2)
- 华为网络安全工程师:HCNA-Security(H12-711)题型解析(第一部分)-马青-专题视频课程...
- 湖南大学 离散数学 2018年期末考试 参考答案
- ​我国首个5G消息平台标准发布;华为拿下支付牌照;工业富联、酷派发布2020年业绩报告...
- 常用UCI数据集(已处理)
- vivo手机刷鸿蒙教程,vivo手机怎么刷机_vivo手机刷机全教程