Activiti 6中的可插拔持久性

在过去的几年中,我们经常听到(来自社区和我们的客户)关于如何将Activiti的持久性逻辑从关系数据库交换到其他内容的请求。 当我们宣布Activiti 6时, 我们做出的承诺之一就是我们将实现这一目标。

深入研究Activiti引擎代码的人会知道,这是认真的重构,因为持久性代码与常规逻辑紧密结合。 基本上,在Activiti v5中,有:

  • 实体类 :这些实体类包含数据库中的数据。 通常,一个数据库行是一个实体实例
  • EntityManager :这些类将与实体相关的操作分组(查找,删除等)
  • DbSqlSession :使用MyBatis的低级操作(CRUD)。 还包含命令持续时间缓存,并管理数据到数据库的刷新。

版本5中的问题如下:

  • 没有接口。 一切都是一类,因此替换逻辑变得非常困难。
  • 整个代码库中到处都使用了低级DbSqlSession。
  • 很多关于实体的逻辑载的实体类 。 例如,查看TaskEntity complete方法。 您不必是Activiti专家即可了解这不是一个不错的设计:
    • 触发一个事件

现在不要误会我的意思。 v5代码将我们带到了很远的地方,并为世界各地许多出色的功能提供了支持。 但是,当涉及到交换持久层时……这并不值得骄傲。

并且可以肯定,我们可以闯入版本5代码(例如,通过用响应于那里使用的方法/查询名称的自定义东西换出DbSqlSession),但这仍然不是很好的设计方法和非常像关系数据库。 而且这不一定与您可能使用的数据存储技术匹配。

不, 对于版本6,我们希望正确执行 。 而且,天哪……我们知道这将需要大量工作……但是它的工作量超出了我们的想象(只需查看过去几周内v6分支上的提交 )。 但是我们做到了……最终的结果很美 (我有偏见,是的)。 因此,让我们看一下v6中的新架构(请原谅我的powerpoint图片。我是编码人员,而不是设计师!):

屏幕截图-2015-09-17-17.14.00

因此,在v5中没有接口的地方,在v6中到处都有接口。 上面的结构适用于引擎中的所有Entity类型 (当前为25个左右)。 因此,例如对于TaskEntity ,有一个TaskEntityImpl , TaskEntityManager , TaskEntityManagerImpl , TaskDataManager和TaskDataManagerImpl类(是的,我知道,他们仍然需要javadoc)。 这适用于所有实体

让我解释一下上图:

  • EntityManager :这是与数据有关的所有其他代码都可以与之通信的接口。 当涉及特定实体类型的数据时,它是唯一的入口点。
  • EntityManagerImplEntityManager类的实现。这些操作通常是高层的,并且同时执行多项操作。 例如,执行删除可能还会删除任务,作业,identityLinks等并触发相关事件。 每个EntityManager实现都有一个DataManager。 每当需要持久性存储中的数据时,它就使用此DataManager实例获取或写入相关数据。
  • DataManager:此接口包含“低级”操作。 通常包含针对其管理的实体类型的CRUD方法以及需要特定用例数据时的特定查找方法
  • DataManagerImpl :DataManager接口的实现。 包含实际的持久性代码。 在v6中,这是唯一现在使用DbSqlSession类通过MyBatis与数据库进行通信的类。 通常,这是您要换出的班级。
  • 实体 :数据接口。 包含getter和setter。
  • EntityImpl :上述接口的实现。 在Activiti v6中,这是常规的pojo,但是该界面允许您切换到其他技术,例如带有spring-dataj,JPA,…(使用批注)的Neo4。 没有它,如果默认实现在您的持久性技术上不起作用,则需要包装/拆开实体。

合并

将所有操作移入接口可以使我们清楚地了解在代码库中分布了哪些方法。 例如,您是否知道至少有五种不同的方法来删除执行(名为“删除”,“删除”,“销毁”等)? 他们所做的几乎相同,但有细微的差别。 有时甚至一点都不微妙。

过去几周的许多工作包括将所有这些逻辑整合为一种方法。 现在,在当前的代码库中,只有一种方法可以执行某些操作。 对于想使用不同持久性技术的人来说,这非常重要。 使它们实现所有变体和微妙之处将是疯狂的。

内存中实现

为了证明持久层的可插入性,我制作了一个小的“内存中”原型。 这意味着,我们使用普通的旧式HashMaps代替关系数据库来将实体存储为{entityId,Entitys}。 然后查询成为if子句。

  • 可以在Github上找到代码: https : //github.com/jbarrez/activiti-in-mem-prototype

(有时在论坛上,人们问到仅在内存中运行Activiti会有多困难,对于那些不要求使用数据库的简单用例来说。现在,这不再困难了!谁知道……这个小原型如果人们喜欢,它可能会变成东西!)

  • 如预期的那样,我们用内存中的版本换出了DataManager实现,请参阅InMemoryProcessEngineConfiguration
@Overrideprotected void initDataManagers() {this.deploymentDataManager = new InMemoryDeploymentDataManager(this);this.resourceDataManager = new InMemoryResourceDataManager(this);this.processDefinitionDataManager = new InMemoryProcessDefinitionDataManager(this);this.jobDataManager = new InMemoryJobDataManager(this);this.executionDataManager = new InMemoryExecutionDataManager(this);this.historicProcessInstanceDataManager = new InMemoryHistoricProcessInstanceDataManager(this);this.historicActivityInstanceDataManager = new InMemoryHistoricActivityInstanceDataManager(this);this.taskDataManager = new InMemoryTaskDataManager(this);this.historicTaskInstanceDataManager = new InMemoryHistoricTaskInstanceDataManager(this);this.identityLinkDataManager = new InMemoryIdentityLinkDataManager(this);this.variableInstanceDataManager = new InMemoryVariableInstanceDataManager(this);this.eventSubscriptionDataManager = new InMemoryEventSubscriptionDataManager(this);}

这样的DataManager实现非常简单。 例如,请参阅InMemoryTaskDataManager ,它需要为TaskEntity实现数据检索/写入方法

public List<TaskEntity> findTasksByExecutionId(String executionId) {List<TaskEntity> results = new ArrayList<TaskEntity>();for (TaskEntity taskEntity : entities.values()) {if (taskEntity.getExecutionId() != null && taskEntity.getExecutionId().equals(executionId)) {results.add(taskEntity);}}return results;}

为了证明它是可行的,让我们进行部署,启动一个简单的流程实例,进行一些小任务查询并检查一些历史记录。 此代码与“常规” Activiti用法完全相同。

public class Main {public static void main(String[] args) {InMemoryProcessEngineConfiguration config = new InMemoryProcessEngineConfiguration();ProcessEngine processEngine = config.buildProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();RuntimeService runtimeService = processEngine.getRuntimeService();TaskService taskService = processEngine.getTaskService();HistoryService historyService = processEngine.getHistoryService();Deployment deployment = repositoryService.createDeployment().addClasspathResource("oneTaskProcess.bpmn20.xml").deploy();System.out.println("Process deployed! Deployment id is " + deployment.getId());ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess");List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();System.out.println("Got " + tasks.size() + " tasks!");taskService.complete(tasks.get(0).getId());System.out.println("Number of process instances = " + historyService.createHistoricProcessInstanceQuery().count());System.out.println("Number of active process instances = " + historyService.createHistoricProcessInstanceQuery().finished().count());System.out.println("Number of finished process instances = " + historyService.createHistoricProcessInstanceQuery().unfinished().count());}}

如果运行它,它可以为您提供这一切(非常快,因为它们全部在内存中!):

Process deployed! Deployment id is 27073df8-5d54-11e5-973b-a8206642f7c5Got 1 tasks!Number of process instances = 1Number of active process instances = 0Number of finished process instances = 1

在这个原型中,我没有添加事务语义。 这意味着,如果两个用户将同时完成同一用户任务,那么结果将是不确定的。 当然,您可能希望从Activiti API获得类似内存中事务的逻辑,但是我尚未实现。 基本上,您需要将所有接触的对象保留在一个小的缓存中,直到刷新/提交时间,然后在该位置进行一些锁定/同步。 当然,我确实接受拉取请求:)

下一步是什么?

好吧,这完全取决于您。 让我们知道您对此有何想法,请尝试一下!

我们与计划很快试用的社区成员/客户之一保持着密切联系。 但是我们当然也想自己玩这个游戏,我们正在寻找一个很酷的首选(我自己在Neo4j的心中仍然占有特殊的位置 ……这很适合交易)。

但是最重​​要的一点是:在Activiti v6中,现在可以干净地交换持久层。 我们为现在的外观感到自豪。 我们希望您也喜欢它!

翻译自: https://www.javacodegeeks.com/2015/09/pluggable-persistence-in-activiti-6.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

src漏洞类型总结

本文转载于https://blog.csdn.net/qq_33942040/article/details/111831536 这三类存在漏洞可能更大 越他娘丑的站&#xff0c;越有可能存在洞。 Asp aspx 存在漏洞的可能更大 登陆口没得验证码的可能存在一,未授权访问 常见28种服务器或者中间协议未授权访问 易出现处 ①照片…

【APICloud系列|19】上架APPStore需要准备哪些材料?

前端时间用敏捷式开发平台开发了一款APP应用,应用名称我就不说啦,这篇文章主要讲述一下上架苹果应用商店APPStore需要准备哪些材料,有相关的困扰欢迎私信我。 一、上架流程 1. 注册苹果企业账号 2. 创建测试证书,发布证书 (使用Mac) 3. 使用xcode 上传应用到APP Store (…

Json注入

一、Json简介 JSON 是存储和交换文本信息的语法&#xff0c;是轻量级的文本数据交换格式。类似xml&#xff0c;但JSON 比 XML 更小、更快&#xff0c;更易解析。所以现在接口数据传输都采用json方式进行。JSON 文本的 MIME 类型是 “application/json”。 json语法 数据在名…

国行 lg g3 D858 刷 lg g3 D858hk 教程(备忘)

纯手打&#xff0c;转载请注明出处~ 刷机有风险&#xff0c;出现问题概不负责&#xff01; 本着自娱自乐的宗旨 &#xff0c;分享一下&#xff0c;出了问题不负责&#xff01; 准备的材料&#xff1a; 1&#xff0c;手机一枚&#xff08;废话&#xff09;国行lg g3 d858 2&am…

渗透测试-验证码的爆破与绕过

【验证码机制原理】 客户端发起请求->服务端响应并创建一个新的SessionID同时生成随机验证码&#xff0c;将验证码和SessionID一并返回给客户端->客户端提交验证码连同SessionID给服务端->服务端验证验证码同时销毁当前会话&#xff0c;返回给客户端结果。 【客户端可…

最近对项目代码做的一些更改和感想

最近对项目代码做了一些更改&#xff0c;主要的改动是对整个界面框架的改变&#xff0c;因为以前写代码的时候&#xff0c;为了完成功能&#xff0c;没有从上帝视角来思考软件的界面设计&#xff0c;完全是需要这个功能了&#xff0c;怎么可以做到&#xff1f;好&#xff0c;就…

CSS常见的四种垂直居中的方法

面试中不管是笔试题还是面试题,一般很容易被问到如何实现垂直水平居中,这里总结四种方法作为参考 (1)margin:auto法 css: div{ width: 400px; height: 400px; position: relative; border: 1px solid #465468; } img{ position: absolute; margin: auto; top: 0; left: 0; …

对安卓应用进行加固签名,为上架各大应用市场做准备

上架安卓各大应用市场之前需要对自己的应用进行签名加固&#xff0c;签名是为了证明你是这个应用的开发者&#xff0c;软著也是一种方式&#xff0c;这是不做介绍&#xff0c;加固是为了从安全角度给安装包加一个保护层&#xff0c;防止被恶意破解及攻击。下面简单介绍一下签名…

大前端最强vscode教程(基础篇)

这段时间入职了一家外包公司的前端工程师岗位,前端编辑器用起来,前端一般会用到几个编译器,VScode、sublime text3、webstorm、Hbuid等,这里主要介绍VScode. 初次使用vscode时各种不适应,所有需要用到的功能貌似都需要单独安装插件才能用。这让很多初次使用vscode的朋友有…

edusrc0day挖掘技巧

网瑞达web资源管理系统0day ps&#xff1a; 作为在edusrc的小白&#xff0c;经常看见大师傅们的刷屏&#xff0c;我也很向往能像大师们一样有一次刷屏的机会&#xff0c;于是有了这一次的渗透之旅。 思路&#xff1a;要想刷屏上分&#xff0c;就得找系统来挖掘&#xff0c;对…

个人或者公司如何写版权认证的证明文件?

项目场景&#xff1a; 现在好多平台都在做知识付费&#xff0c;比如百度文库、CSDN、微博、头条、知乎等等&#xff0c;因此我想给大家做一些付费文档&#xff0c;想上传到百度文库的知识店铺 问题描述&#xff1a; 一般人不知道这个版权认证文件怎么写&#xff0c;怎么弄&am…

Bypass WAF实战总结

0X00前言 上个月刷了一波洞&#xff0c;然后这个月初远程支持了一个HW&#xff0c;在文件上传getshell的时候&#xff0c;碰到个各式各样的云waf&#xff0c;通过一个月的实战&#xff0c;总结了几个比较实用的技巧&#xff0c;文章总结的不全&#xff0c;只是基于我实战中用到…

Git教程学习总结(分享给热爱学习的你,团队的协作离不开你呀)

目录 Git 教程 Git 安装配置 Git 工作流程 Git 工作区、暂存区和版本库 Git 创建仓库 Git 基本操作 Git 分支管理 Git 查看提交历史 git log git blame Git 标签 Git 远程仓库(Github) Git Gitee Git 服务器搭建 Git 教程 Git 是一个开源的分布式版本控制系统&…

Linux的shell编写

-eq //等于 -ne //不等于 -gt //大于 -lt //小于 ge //大于等于 le //小于等于实验中遇到的问题&#xff1a; 1.NAMEuser1 中间不能有空格 2.[ xxx ] xxx前面和后面要有空格 任务1&#xff1a;使用case语句编…

为啥这么多程序员大佬学习Cortex-M3

Cortex-M3是一个32位处理器内核。内部的数据路径是32位的&#xff0c;寄存器是32位的&#xff0c;存储器接口也是32位的。CM3采用了哈佛结构&#xff0c;拥有独立的指令总线和数据总线&#xff0c;可以让取指与数据访问并行不悖。这样一来数据访问不再占用指令总线&#xff0c;…

Ffuf使用教程

kali安装教程链接&#xff1a;https://www.iculture.cc/cybersecurity/pig210 该工具用途广泛&#xff0c;可用于多种用途。一些用途&#xff1a; • 目录发现&#xff0c;可选择在 URL 中的任何位置进行模糊测试。 • 子域名发现 • 使用各种 HTTP 方法进行模糊测试。 安装 …

Burp Collaborator 使用总结

0x00&#xff1a;使用原因 我们在做渗透测试的时候&#xff0c;经常会遇到这种情况&#xff0c;测试跨站可能有些功能插入恶意脚本后无法立即触发&#xff0c;例如提交反馈表单&#xff0c;需要等管理员打开查看提交信息时才会触发&#xff0c;或者是盲注跨站&#xff0c;盲打 …

jrockit_1.6下载_Oracle JRockit Mission Control 4.1发布

jrockit_1.6下载Oracle发布了以前的仅JRockit专用工具Mission Control Suite&#xff08;JRMC&#xff09;的新版本。 4.1版本是次要版本升级&#xff0c;直接遵循4.0.1&#xff08;该版本发布于2010年中期&#xff09;。 但是&#xff0c;即使版本号表明是次要的升级&#xff…

dnslog盲注原理

Dnslog盲注原理 布尔盲注和时间盲注相当于猜单词的游戏&#xff0c;我们需要对每一位逐步的猜测&#xff0c;效率很低&#xff0c;需要发送很多的请求进行判断&#xff0c;很可能会触发安全设备的防护 我们需要一种方式能够减少请求&#xff0c;直接回显数据——Dnslog注入 Dn…

[学习笔记]批次需求计划系统-简要

一、该系统的目的二、系统特色(1)来源根据 如上图(2)仅仅补充需求来源的最大值&#xff0c;避免料件多买而造成浪费(3)可透过[发放LRP工单]将生产计划发放成正式工单(4)可透过[发放LRP採购单]将採购计划发放成正式的请购单或者採购单(5)系统会记录计划的来源单据&#xff0c;方…