由于工作需要,新接到一个小项目,什么?项目,ofbiz走起!项目中需要用到两个小流程,什么?流程 activiti5走起~
activiti5 是原生支持spring 的,可是怎么能让它与ofbiz整合到一块呢,ofbiz确实有自己的sharp 啥的,可是弄不懂啊,资料太少了。可是ofbiz与activiti5整合的资料更少啊,没办法,面对activii5的流程编辑器的诱惑,自己想招吧!
其实整合起来并不复杂,代码量也不多,我就来一步一步说具体操作
1.下载activiti5,我是从官网下的最新版 下载下来解压,我了个去这么些jar ,其实用到的也不多,主要用的有
activiti-bpmn-converter-5.17.0.jar
activiti-bpmn-layout-5.17.0.jar
activiti-bpmn-model-5.17.0.jar
activiti-common-rest-5.17.0.jar
activiti-crystalball-5.17.0.jar
activiti-diagram-rest-5.17.0.jar
activiti-engine-5.17.0.jar
activiti-explorer-5.17.0.jar
activiti-image-generator-5.17.0.jar
activiti-json-converter-5.17.0.jar
activiti-modeler-5.17.0.jar
activiti-process-validation-5.17.0.jar
activiti-simple-workflow-5.17.0.jar
commons-lang3-3.3.2.jar
jackson-annotations-2.2.3.jar
jackson-core-2.2.3.jar
jackson-databind-2.2.3.jar
javaGeom-0.11.1.jar
joda-time-2.6.jar
mybatis-3.2.5.jar
2.我使用的是ofbiz13就是最新版本那个,下一步就是新建一个component 叫做workflow模块
我是建在了framework 下面的,架构级么哈哈,新建component 我就不多介绍了,很多资料可以参考,我新建的component 包含了一下内容:
3 导入jar 包 并且添加classpath中(也就是说在ofbiz-component.xml中包含workflow的lib文件夹),如果component创建的配置都对的话,把你新建的component 加入到component-loader中,启动一下不报错说明你添加jar包成功了。
4.我的整合思路是通过ofbiz 启动加载 acitiviti 的processEngine 并且提供一个processEngineFactory 来获取activiti 的主要接口,那么在我们业务中随时都可以调用工作流引擎了.所以第一步要正确的加载ProcessEngine
ofbiz 强大之处就体现出来了,可以使用它的container 来加载我们的processEngine,我们创建一个workflowcontainer,并实现ofbiz 的container 接口:
package com.ly.workflow; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.ofbiz.base.container.Container; import org.ofbiz.base.container.ContainerException; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilProperties; import java.util.Properties; /** * Created by bo on 15/4/14. */ public class WorkflowContainer implements Container { private String name; private String dbFile= "workflow.db.properties"; @Override public void init(String[] args, String name, String configFile) throws ContainerException { this.name = name; Debug.log("---启动工作流模块---"); //获取工作流数据库配置文件 Properties jdbc=UtilProperties.getProperties(dbFile); //配置工作流引擎 ProcessEngineConfiguration pecfg = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration(); pecfg.setJdbcUsername(jdbc.getProperty("username")); pecfg.setJdbcPassword(jdbc.getProperty("password")); pecfg.setJdbcUrl(jdbc.getProperty("url")); pecfg.setJdbcDriver(jdbc.getProperty("driver")); //连接池设置 pecfg.setJdbcMaxActiveConnections(Integer.valueOf(jdbc.getProperty("jdbcMaxActiveConnections"))); pecfg.setJdbcMaxIdleConnections(Integer.valueOf(jdbc.getProperty("jdbcMaxIdleConnections"))); pecfg.setJdbcMaxCheckoutTime(Integer.valueOf(jdbc.getProperty("jdbcMaxCheckoutTime"))); pecfg.setJdbcMaxWaitTime(Integer.valueOf(jdbc.getProperty("jdbcMaxWaitTime"))); //设置启动检查数据表 pecfg.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); //创建表并获取流程引擎 ProcessEngine pe = pecfg.buildProcessEngine(); //todo 加载初始化流程 //初始化工作流引擎工厂 WorkflowProcessEngineFactory.init(pe,"default"); Debug.log("---工作流引擎加载成功---"); } @Override public boolean start() throws ContainerException { Debug.log("workflow-start"); return false; } @Override public void stop() throws ContainerException { Debug.log("workflow-stop"); } @Override public String getName() { return null; } }
这里需要注意的是我们要写一个配置文件来配置工作流引擎的数据库, activiti 是有自己的一套数据库框架的,也不是他的就是ibatis。。我们就创建一个配置文件来保存工作流引擎的数据库配置,其实也可以用ofbiz自己的连接池的,如果你需要可以自己配置,我是想把ofbiz本身的业务和工作流分开放不同的数据里。
之后我们就新建一个工厂类来保存我们创建的 processEngine:
package com.ly.workflow; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.RepositoryService; import org.activiti.workflow.simple.converter.WorkflowDefinitionConversionFactory; import org.activiti.workflow.simple.converter.json.SimpleWorkflowJsonConverter; import org.ofbiz.base.lang.Factory; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilObject; import org.ofbiz.entity.Delegator; import java.util.concurrent.ConcurrentHashMap; /** * Created by bo on 15/4/14. */ public abstract class WorkflowProcessEngineFactory implements Factory<ProcessEngine,String> { public static final String module = WorkflowProcessEngineFactory.class.getName(); private static ProcessEngineConfiguration pecfg = null; private static final ConcurrentHashMap<String, ProcessEngine> processEngineCache = new ConcurrentHashMap<String, ProcessEngine>(); public static ProcessEngine getProcessEngine(String processEngineName){ if (processEngineName == null) { processEngineName = "default"; } ProcessEngine processEngine = processEngineCache.get(processEngineName); if (processEngine == null) { Debug.logInfo("没有找到工作流引擎", module); } return processEngine; } public static ProcessEngine getProcessEngine(){ return getProcessEngine("default"); } public static RepositoryService getRepositoryService(String processEngineName){ return getProcessEngine(processEngineName).getRepositoryService(); } public static RepositoryService getRepositoryService(){ return getRepositoryService("default"); } public static void init(ProcessEngine pe,String name){ WorkflowProcessEngineFactory.processEngineCache.put(name,pe); } }
如果你有对acitiviti 的借口需求的话,可以在工厂类中添加不同的获取方法,静态方法么,那块你想用取一下就行了,当然你也可以把processEngine 放到Context 里面方便获取。
4.之后你就可以把container 放在ofbiz 启动配置里面了,我觉得ofbiz的container 就相当于spring 一样,都是容器么,但是我觉得spring把简单的东西复杂化了,用的这个费劲,ofbiz 这点要强不少哦。
启动配置的位置在framework/base/config/ofbiz-containers.xml 中,添加一条你的工作流container:
<container name="workflow-container" loaders="main" class="com.ly.workflow.WorkflowContainer"/>
这样的话你启动ofbiz 就会帮你检查是否有activiti 的数据库和表,没有的话会帮你创建出来
如果没抱错,你现在的工作流引擎就可以使用了。。。
5.当然了,光有这些远远不够,activiti 的modeler 流程编辑器才是重点,它可以让你在线定义流程,图形化,可拖动,用户不就是喜欢这种傻瓜式的么,那么我们也吧流程编辑器也整合过来
其实acitiviti 的流程编辑器就是一大堆html 和js 啥的,通过ajax 请求与后台通讯,我们可以用ofbiz自己些逻辑,而前台交给他的编辑器,首先把activiti 的流程编辑器加进来,解压下载的activiti中 的activiti-explorer.war
编辑器其实就是上图的editor-app文件夹,把它拷贝到framwork/images/web-app/images下面
之后我们需要写一个screen 用来包含编辑器需要的js css 啥的,还有要给编辑器一个流程定义ID,
其实这个页面acitivity 中也有,就是上面那个modeler.html,那简单了拷~~~
新建 一个controller
<request-map uri="ProcessDefineModeler"> <security https="true" auth="true"/> <response name="success" type="view" value="ProcessDefineModeler"/> </request-map>
放在你能访问的WEB-INF/controller.xml中
之后建一个screen 来显示我们要的编辑器
<view-map name="ProcessDefineModeler" type="screen" page="component://workflow/widget/CommonScreens.xml#ProcessDefineModeler"/>
<screen name="ProcessDefineModeler"> <section> <actions> <set field="titleProperty" value="cache"/> <set field="headerItem" value="define"/> <set field="tabButtonItem" value="ProcessDefineEditor"/> </actions> <widgets> <platform-specific> <html> <html-template location="component://workflow/templates/processDefine/ProcessDefineModeler.ftl"/> </html> </platform-specific> </widgets> </section> </screen>
把ftl 创建出来,然后把modeler.html的内容拷贝进去(注意要把引用的js 还有css 还有 angelar js 的东西改成images/editor-app路径,确保里面的文件都能通过你的ofbiz服务器找到)
<div id="main" class="wrapper full clearfix" ng-style="{height: window.height + 'px'}" ng-app="activitiModeler" ng-include="'<@ofbizContentUrl>/images/editor-app/editor.html</@ofbizContentUrl>'"> </div>
主要是个,这个其实才是真正的编辑器。。这里可能要改的东西比较多,慢慢来吧,改到你看到的页面没有错误位置, 还有就是这里要有一个必要参数传进来,就是你的流程定义ID,修改引用路径使用ofbizcontenturl
like this:
<script src="<@ofbizContentUrl>/images/editor-app/libs/es5-shim-15.3.4.5/es5-shim.js</@ofbizContentUrl>"></script>
这里做完之后我们需要一个已有流程定义ID 来进入这个页面,这样才不会抱错,所以我们先来做一个流程管理页面
用semantic ui 加上w2ui 做了一个哈。左侧读出流程定义列表,右边显示流程具体信息和对流程定义的操作
这里的一些东西可以参考 activiti 自带的explore,其实说白了就是把他的explore 给弄成ofbiz版本的了,我的方法比较笨吧。。。但是集成度比较高
让编辑流程按钮 导向我们 流程定义页面跳转
哈哈流程定义图出来了,都是应文的,现在还没空翻译它讲究看吧
现在其实你们显示的还是一堆错误,是因为流程编辑器显示出来需要我们后台提供几个服务接口的,都是ajax json 调用,我们可以用ofbiz 来写后台返回个json 数据给他
修改 editor-app/config.js 把它请求服务的路径改为我们自己的
KISBPM.URL = { getModel: function(modelId) { return ACTIVITI.CONFIG.contextRoot + '/GetProcessModelById?modelId=' + modelId; }, getStencilSet: function() { //return ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now(); return '/images/editor-app/stencilset.json'; }, putModel: function(modelId) { return ACTIVITI.CONFIG.contextRoot + '/SaveProcessModelById?modelId=' + modelId+"&" ; } };
还有app-cfg,js
'use strict'; var ACTIVITI = ACTIVITI || {}; ACTIVITI.CONFIG = { 'contextRoot' : '/workflow/control' };
你可能注意到了,编辑器还有保存功能,上面配置的一个路径就是保存功能的路径
之后你可以写一个service 还是别的什么,来处理保存逻辑
我的是这样的
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.node.ObjectNode import com.ly.workflow.WorkflowProcessEngineFactory import org.activiti.engine.ActivitiException import org.activiti.engine.RepositoryService import org.activiti.engine.repository.Model import org.apache.batik.transcoder.TranscoderInput import org.apache.batik.transcoder.TranscoderOutput import org.apache.batik.transcoder.image.PNGTranscoder import org.ofbiz.base.util.Debug String modelId = parameters.modelId; String name = parameters.name; String des = parameters.description; String svgXml = parameters.svg_xml; String jsonXml = parameters.json_xml; RepositoryService repositoryService = WorkflowProcessEngineFactory.getRepositoryService(); ObjectMapper objectMapper = new ObjectMapper(); try { Model model = repositoryService.getModel(modelId); ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo()); modelJson.put("name", name); modelJson.put("description", des); model.setMetaInfo(modelJson.toString()); model.setName(name); repositoryService.saveModel(model); repositoryService.addModelEditorSource(model.getId(), jsonXml.getBytes("utf-8")); InputStream svgStream = new ByteArrayInputStream(svgXml.getBytes("utf-8")); TranscoderInput input = new TranscoderInput(svgStream); PNGTranscoder transcoder = new PNGTranscoder(); // Setup output ByteArrayOutputStream outStream = new ByteArrayOutputStream(); TranscoderOutput output = new TranscoderOutput(outStream); // Do the transformation transcoder.transcode(input, output); final byte[] result = outStream.toByteArray(); repositoryService.addModelEditorSourceExtra(model.getId(), result); outStream.close(); } catch (Exception e) { Debug.logError(e.getMessage(),"SaveProcessModelById.groovy"); }
因为流程图是生成出来的,所以调用activiti的接口比较多,具体的查一下activiti 的官方文档 或者是 看看一个叫咖啡兔的微博,很简单。
至此 整合完毕,其实还可以进一步进行封装与优化,并且把activiti explore 中的相关功能完善进去,这是一个整合其他框架的一个思路而已,其实spring 能整合的,ofbiz都能整合。这里不得不感叹ofbiz的强大。
相关推荐
这项工作主要目的在于利用Spring良好的系统集成能力,实现OFBiz与任意目标系统的整合与集成。在此项目中,OFBiz版本为11.04,而Activiti工作流引擎版本为5.9,Spring框架版本为3.1.1。何增耀在该文档中详细描述了...
主要目的是利用Spring的出色集成能力,使OFBiz能够与各种目标系统,特别是Activiti 5.9版本,进行无缝整合。这有助于扩展OFBiz的功能,使其能够支持复杂的业务流程管理。 2. **系统版本** - OFBiz版本为11.04,但...
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
cmd-bat-批处理-脚本-MakeToolWindow.zip
“华为杯”第十八届中国研究生数学建模竞赛是一项全国性赛事,致力于提升研究生的数学建模与创新实践能力。数学建模是将实际问题转化为数学模型,并运用数学方法求解以解决实际问题的科学方法。该竞赛为参赛者提供了展示学术水平和团队协作精神的平台。 论文模板通常包含以下内容:封面需涵盖比赛名称、学校参赛队号、队员姓名以及“华为杯”和中国研究生创新实践系列大赛的标志;摘要部分应简洁明了地概括研究工作,包括研究问题、方法、主要结果和结论,使读者无需阅读全文即可了解核心内容;目录则列出各章节标题,便于读者快速查找;问题重述部分需详细重新阐述比赛中的实际问题,涵盖背景、原因及重要性;问题分析部分要深入探讨每个问题的内在联系与解决思路,分析各个子问题的特点、难点及可能的解决方案;模型假设与符号说明部分需列出合理假设以简化问题,并清晰定义模型中的变量和符号;模型建立与求解部分是核心,详细阐述将实际问题转化为数学模型的过程,以及采用的数学工具和求解步骤;结果验证与讨论部分展示模型求解结果,评估模型的有效性和局限性,并对结果进行解释;结论部分总结研究工作,强调模型的意义和对未来研究的建议;参考文献部分列出引用文献,遵循规范格式。 在准备竞赛论文时,参赛者需注重逻辑清晰、论述严谨,确保模型科学实用。良好的团队协作和时间管理也是成功的关键。通过竞赛,研究生们不仅锻炼了数学应用能力,还提升了团队合作、问题解决和科研写作能力。
希望这会对大家有用,共同发挥互联网精神!
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
cmd-bat-批处理-脚本-Run python script.zip
内容概要:本文详细介绍了利用Matlab/Simulink平台,通过无迹扩展卡尔曼滤波(UKF/EKF)进行路面附着系数估计的方法及其仿真功能。文中首先阐述了Dugoff轮胎模型的构建方法,强调了避免代数环的重要性,并提供了具体的模块连接方式。接着,描述了7自由度整车模型的搭建步骤,特别是质心加速度和轮速之间的耦合关系。最后,深入探讨了UKF和EKF滤波器的配置细节,包括状态变量选择、观测值设定以及协方差矩阵的初始化等关键参数调整。仿真结果显示,在80km/h的速度下,UKF相比EKF的均方误差降低了18%,但CPU耗时增加了40%。 适合人群:从事车辆控制系统研究的专业人士,尤其是对卡尔曼滤波有一定了解的研究人员和技术人员。 使用场景及目标:适用于需要精确估计路面附着系数的应用场合,如汽车电子稳定程序(ESP)的设计与优化。通过提高附着系数估计的准确性,可以有效提升车辆行驶的安全性和稳定性。 其他说明:文章不仅提供了理论指导,还给出了实际操作的具体步骤和注意事项,帮助读者更好地理解和应用相关技术。
实体建模技术研究进展.zip
基于4G通信的高负载电动汽车远程监控平台软件设计与开发.zip
IMG_20250521_201207.jpg
cmd-bat-批处理-脚本-数学-isInteger.zip
基于改进DeepLabv3+的高分辨率遥感影像屋顶提取方法.pdf
cmd-bat-批处理-脚本-post-install.zip
遗传算法优化BP神经网络(GABP)是一种结合了遗传算法(GA)和BP神经网络的优化预测方法。BP神经网络是一种多层前馈神经网络,常用于模式识别和预测问题,但其容易陷入局部最优。而遗传算法是一种模拟自然选择和遗传机制的全局优化方法,能够有效避免局部最优 。GABP算法通过遗传算法优化BP神经网络的权重和阈值,从而提高网络的学习效率和预测精度 。 种群:遗传算法中个体的集合,每个个体代表一种可能的解决方案。 编码:将解决方案转化为适合遗传操作的形式,如二进制编码。 适应度函数:用于评估个体解的质量,通常与目标函数相反,目标函数值越小,适应度越高。 选择:根据适应度保留优秀个体,常见方法有轮盘赌选择、锦标赛选择等。 交叉:两个父代个体交换部分基因生成子代。 变异:随机改变个体的部分基因,增加种群多样性。 终止条件:当迭代次数或适应度阈值达到预设值时停止算法 。 初始化种群:随机生成一组神经网络参数(权重和阈值)作为初始种群 。 计算适应度:使用神经网络模型进行训练和预测,根据预测误差计算适应度 。 选择操作:根据适应度选择优秀个体 。 交叉操作:对选择的个体进行交叉,生成新的子代个体 。 变异操作:对子代进行随机变异 。 替换操作:用新生成的子代替换掉一部分旧种群 。 重复步骤2-6,直到满足终止条件 。 适应度函数通常以预测误差为基础,误差越小,适应度越高。常用的误差指标包括均方根误差(RMSE)或平均绝对误差(MAE)等 。 GABP代码中包含了适应度函数的定义、种群的生成、选择、交叉、变异以及训练过程。代码注释详尽,便于理解每个步骤的作用 。 GABP算法适用于多种领域,如时间序列预测、经济预测、工程问题的优化等。它特别适合解决多峰优化问题,能够有效提高预测的准确性和稳定性 。
太阳高度角和方位角建模及核桃树阴影变化分析.pdf
cmd-bat-批处理-脚本-param2.zip
Uniapp原生适配日期时间选择器,可动态设置分钟显示间隔
cmd-bat-批处理-脚本-日期-W32DOW.zip