Activiti中的高级脚本:自定义配置注入

脚本任务可能是Activiti代码库中“最古老的”类之一,但我认为它仍然未被许多人使用。 (可以理解的?)缺点当然是性能(解释还是编译),并且从IDE角度来看支持较少。

但是,好处(imo)超过了这一点:

  • 脚本在流程xml本身中定义。 无需担心版本控制和类路径上的库问题。
  • 过去我们看到的是,技术水平较低的人不敢尝试脚本。 但是从来没有Java。

无论如何,很少有人知道或已经意识到的是,您可以在Activiti中的脚本中做得很棒,并可以进行一些高级工作。 由于此类脚本是在流程引擎中执行的,因此您可以访问该引擎的所有功能。 是的...一切...这使其既非常强大,又(潜在)危险(如果您不知道自己在做什么)。

让我为您讲解这样的例子。 我喜欢将其称为“定制配置注入”的概念 ,因为它有效地使您可以在运行时添加定制逻辑,从而显着改变流程的执行。 如果您的名字更酷,请告诉我。

所有代码都可以在我的Github页面上找到: https : //github.com/jbarrez/activiti-advanced-scripting

很棒的代码648x303

用例

现在我想做什么。 好吧,我想有一个流程,执行时

  • 向执行的每个用户任务添加“任务完成事件处理程序”
  • 此事件处理程序必须向远程URL触发自定义事件,在该URL上事件处理器可能正在执行其工作

因此,基本上,我们希望在任务完成时将自定义事件触发到某个远程URL。 一个很好的用例是商业智能报告/复杂事件处理,例如使用Esper之类的东西。

Screen-Shot-2013-07-23-at-10.03.112

第一个版本

可以在https://github.com/jbarrez/activit-advanced-scripting/blob/master/src/test/resources/org/activiti/test/my-process.bpmn20.xml中找到该功能的第一版 。 执行此过程时,将发生以下情况:

var config = Context.getProcessEngineConfiguration();
var bpmnParser = config.getBpmnParser();

我们仅获取当前的ProcessEngineConfiguration实例。 我们将从此配置中获取BpmnParser实例,因为我们想更改整个引擎的常规用户任务解析。

接下来,我们构建脚本:

var script = "";
script = script + "importPackage(java.net);";
script = script + "importPackage(java.io);";
script = script + "var url = new URL('http://localhost:8182/echo');";
script = script + "var connection = url.openConnection();";
script = script + "connection.setRequestMethod('POST');";
script = script + "connection.setDoOutput(true);";
script = script + "var outputStream = new BufferedOutputStream(connection.getOutputStream());";
script = script + "outputStream.write(new java.lang.String(\"{'eventType':'task-complete'}\").bytes);";
script = script + "outputStream.flush();";
script = script + "connection.connect();";
script = script + "var respCode = connection.getResponseCode();";
script = script + "if (respCode != 200) ";
script = script + "println('Response code : ' + respCode);";
script = script + "outputStream.close();";
script = script + "connection.disconnect();";

显然,这不是执行此操作的最有效方法,但可以肯定地说明了发生的情况。 消息'eventType:task-complete'通过标准java.net和java.io类发送到localhost:8182 url。

接下来是棘手的部分:

var handler = new ExecuteScriptOnTaskCompleteBpmnParseHandler("JavaScript");
handler.setUserTaskCompleteScript(script);
bpmnParser.getBpmnParserHandlers().addHandler(handler);// reset the deployment cache such that the new listener gets picked up on a new redeploy
config.getProcessDefinitionCache().clear();

在这里,我们将BpmnParseHandler类添加到引擎配置中。 解析处理程序会将上面定义的脚本的执行添加到引擎发出的“任务完成事件”的每次接收中。 每次对用户任务进行解析时,该解析处理程序都会启动,从而有效地将我们的“将事件发送到远程服务”添加到您的Activiti环境中现在发生的每个用户任务中!

有一个单元测试以了解其工作原理: https : //github.com/jbarrez/activiti-advanced-scripting/blob/master/src/test/java/org/activiti/test/ExecuteScriptInProcessTest.java 。 在测试中,我们设置了一个非常简单的“回显服务”,只要接收到这样的事件,它就会简单地打印出来。 如果在IDE中运行它,您将看到类似以下内容:

Screen-Shot-2013-07-23-at-09.53.00

但是我们可以做得更好

但是我们可以做得更好。 检查以下代码。

var handler = new ExecuteScriptOnTaskCompleteBpmnParseHandler("JavaScript");
handler.setUserTaskCompleteScript("http://localhost:8182/scripts/task-complete.js");
handler.setExecuteScriptInJob(true);
bpmnParser.getBpmnParserHandlers().addHandler(handler);// Update the configuration to use the correct job handler
var jobHandler = new ExecuteScriptJobHandler();
config.getJobHandlers().put(jobHandler.type,jobHandler);

此代码与上一节中的代码相同。 将“完成”事件的侦听器附加到每个用户任务。 但是,此实现:

  • 异步执行脚本
  • 没有在流程xml中定义脚本,但是它是从远程URL获取的
  • 更新作业处理程序配置

如果您问我,那太棒了! 因此,这意味着向远程服务实际发送消息不会影响流程实例的执行性能 。 显然,从这里您可以发疯,添加持久队列和所有这些幻想。 最重要的是,脚本始终是从远程服务器获取的。 如果要更新执行的逻辑,只需更改返回的脚本。 这意味着您可以在不影响实际流程的情况下影响运行时的流程执行。

在https://github.com/jbarrez/activiti-advanced-scripting/blob/master/src/test/java/org/activiti/test/ExecuteScriptWithJobTest.java有一个单元测试

如果运行此测试,则会看到以下内容。 请注意,我们在测试服务器上将完成脚本托管为名为“ task-complete.js”的静态文件。

Screen-Shot-2013-07-23-at-09.50.362-1024x171

在测试中,您可以看到我们必须专门执行异步作业才能查看测试的输出。

警告

需要注意的是:当流程引擎重新启动时,将从配置文件中重新加载配置。 因此,不添加从上方插入自定义逻辑的过程。 但是,这可以通过使用ProcessEngineLifeCycleListener实现轻松完成,该实现在引擎启动后执行特定类别的流程定义。 例如,如果将所有这些进程的“ config-processes”都设为类别,则可以轻松地在启动时执行它们。

结论

BPMN 2.0流程中的脚本编写是一项非常强大的功能。 它使您可以在几行之内更改整个引擎的流程执行。 当然,以上所有代码都可以使用Java完成。 但是以上示例仅使用标准BPMN 2.0和每次JDK安装中捆绑的javascript引擎。

谢谢阅读。 编码愉快!

参考: Activiti中的高级脚本: JCG合作伙伴 Joram Barrez在“ 小脚走路”博客上的自定义配置注入 。

翻译自: https://www.javacodegeeks.com/2013/07/advanced-scripting-in-activiti-custom-configuration-injection.html

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

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

相关文章

帆软决策报表嵌入html,在决策报表中使用网页框控件

假设决策报表里有一个网页框控件,控件名为rHIframe0;同时有三个按钮控件,分别给按钮控件添加下面的点击事件:3.1 setValue(String)设置并刷新网页框控件的地址(保留原参数)1)模板路径var Widget this.options.form.getWidgetByNa…

【前端轶事】Chrome 小恐龙背后的故事

本文转自 FEPulse 公众号(微信搜索 FEPulse,精选国内外最新前端资讯,为你把握前端脉搏)。 如果你是 Chrome 用户,一定对那萌萌哒的小恐龙不陌生,每当互联网连接断开时,你便能看到那只小恐龙&am…

《React源码解析》系列完结!

前言 距离第一篇《React源码解析(一)》已经过去将近4个月的时间,由于是我第一次进行源码解析相关的写作,思路和文笔还不够成熟。一百多天以来,我基于读者反馈反思这几篇文章中的不足,同时也在不断学习借鉴其他优秀作者的写作方法…

html5 css 字体加粗,HTML和CSS实现字体加粗的三种方法

大家在浏览网站时有没有注意到,页面中有些文字或字体加粗了,正在学习HTML和CSS的小伙伴,你知道HTML如何给文字加粗吗?CSS怎么设置字体加粗呢?这篇文章给大家总结了给字体和文字加粗的三种方法,包括HTML中的…

虾扯蛋之函数防抖和节流

背景 今天在coding的时候,做了一个搜索框,也正是这个搜索框,让我和后台小伙伴直接由铁磁变为塑料兄弟。那到底发生啥了呢?其实很简单,其实很无奈,就是我用王者的手速把他的接口访问崩了! 我们在…

四川省内二本计算机公立好的大学排名,四川有哪些二本院校是公立的?附四川省公立二本大学排名及分数线...

选择科目测一测我能上哪些大学选择科目领取你的专属报告>选择省份关闭请选择科目确定v>四川省内的公办大学一直以来都是历年高考生及家长关注的重点,本篇文章我将针对“四川省有多少所二本公立大学?有哪四川省内的公办大学一直以来都是历年高考生及…

NetBeans 7.4 Beta提示警告无效的异常处理

有许多例子说明Java异常处理可能比首次出现时要困难得多,Josh Bloch专门将一整章的《 Effective Java》 (两个版本)专门用于异常处理。 Java中的检查异常模型 仍然 “ 有争议” 。 我很高兴看到我最近下载的NetBeans 7.4 beta有一些提示&…

mysql5.7.17解压版安装_Windows中 MySQL5.7.17解压版安装步骤

1、先去MySQL官网下载。当前最新版是5.7.19,可能安装方法不同了,本人测试没有安装成功,若有安装成功的朋友,希望分享一下安装步骤。2、将下载的压缩包解压出来,然后在“MySQL解压目录”中新建“data”文件夹。如下图&a…

关于Java和Scala同步的五件事你不知道

实际上,所有服务器应用程序都需要在多个线程之间进行某种同步。 大多数同步工作是在框架级别为我们完成的,例如通过我们的Web服务器,数据库客户端或消息传递框架。 Java和Scala提供了许多组件来编写可靠的多线程应用程序。 这些包括对象池&am…

精读《你不知道的javascript》中卷

前言 《你不知道的 javascript》是一个前端学习必读的系列,让不求甚解的JavaScript开发者迎难而上,深入语言内部,弄清楚JavaScript每一个零部件的用途。本书《你不知道的javascript》中卷介绍了该系列的两个主题:“类型和语法”以…

撸个微信小程序的省市区选择器

起因 微信小程序虽然已经有现成的封装好的省市区选择器给开发者使用,然鹅不幸的是,微信地址库的数据和公司用的地址库数据很难一一对上,那就只能撸起袖子自己写个组件了。 最终效果 思维导图 主要代码 组件 region-picker.js /* region-pic…

python之路_day6

本节内容&#xff1a;面向对象编程介绍为什么要用面向对象进行开发&#xff1f;面向对象的特性&#xff1a;封装、继承、多态类、方法、引子 你现在是一家游戏公司的开发人员&#xff0c;现在需要你开发一款叫做<人狗大战>的游戏&#xff0c;你就思考呀&#xff0c;人狗作…

MUI调用原生自定义方法实现计算缓存与清空缓存

由于项目需要最近在做webapp开发用的是MUI框架&#xff0c;自己本来是做原生开发的&#xff0c;在开发的时候有一个需求是实现计算缓存和清除缓存的功能&#xff0c;原生java方法实现轻轻松松&#xff0c;网上代码一大把&#xff0c;不过是webapp倒是不好搞&#xff0c;MUI自己…

Java中的多重继承与组合vs继承

有时我写了几篇有关Java 继承 &#xff0c; 接口和组成的文章。 在这篇文章中&#xff0c;我们将研究多重继承&#xff0c;然后学习组成优于继承的好处。 Java中的多重继承 多重继承是创建具有多个超类的单个类的能力。 与其他一些流行的面向对象的编程语言&#xff08;例如C …

开源|蚂蚁金服开源AntV F2:一个专注于移动,开箱即用的可视

小蚂蚁说&#xff1a;AntV 是蚂蚁金服全新一代数据可视化解决方案&#xff0c;主要子产品包括 G2、G6、F2。此前我们已经相继发布过AntV的相关开源消息与版本迭代&#xff0c;包括《蚂蚁金服开源&#xff1a;数据驱动的高交互可视化图形语法G2》&#xff0c;《开源 | 蚂蚁金服开…

Puppeteer入门初探

本文来自网易云社区作者&#xff1a;唐钊最近在看 node 爬虫相关的一些东西&#xff0c;我记得还是很久以前常用的 node 爬虫工具还是 superagengtcherrio,他们的思路是通过发起 http 请求然后截取 respone 的内容&#xff0c;但是随着前端mvvm等框架的盛行&#xff0c;现在更多…

访问量大如何增加服务器,服务器流量过大原因及解决方法

造成网站服务器流量过大的原因&#xff1a;1.网站规模较大(比如门户网站、网络商城等)&#xff0c;即网站本身访问量需求大&#xff0c;查看网站的Page View值、Hits值、日流量都很高。2.网站页面设计不合理&#xff0c;页面中包含大图片或音频、视频文件等文件&#xff0c;导致…

关于VUE项目地图开发中大量点标记绘制一些总结

问题说明 在地图开发中&#xff0c;当地图中绘制大量的标记点后&#xff0c;无论是拖动或者缩放&#xff0c;都会感觉到明显的卡顿现象。&#xff08;一般超过800个点后就比较明显了&#xff09;.在平时的工作业务中&#xff0c;由于公司的实时监控页面需要展现5000-20000车辆…

如何使用Java 5 Executor框架创建线程池

Java 5以Executor框架的形式在Java中引入了线程池&#xff0c;它允许Java程序员将任务提交与任务执行分离。 如果要使用Java进行服务器端编程&#xff0c;则线程池是维护系统可伸缩性&#xff0c;鲁棒性和稳定性的重要概念。 对于那些不熟悉Java中的线程池或这里的线程池的概念…

使用NetBeans 7.4 beta提示进行更好的基于JUnit的单元测试

在上一篇文章中 &#xff0c;我写了NetBeans 7.4 beta中提供的提示 &#xff0c;这些提示提高了开发人员避免Java异常处理带来的讨厌的运行时问题的能力。 在本文中&#xff0c;我将研究如何使用NetBeans 7.4 beta提供的另外两个提示使单元测试在执行单元测试期间更加正确和清晰…