集成Activiti-Modeler流程设计器

集成Activiti-Modeler流程设计器

Activiti Modeler 是 Activiti 官方提供的一款在线流程设计的前端插件,可以方便流程设计与开发人员绘制流程图,保存流程模型,部署至流程定义等等。

1、材料准备
首先我们需要获取activiti-explorer.zip,这个是activiti-5.22.0才有的。

链接:https://pan.baidu.com/s/1zZ8vcjR63_hgzcLl6soiDw
提取码:1e8a

2、集成
2.1 集成静态资源

在这里插入图片描述
其中的editor-app就是编辑器,modeler.html是编辑器的入口页面。
diagram-viewer是流程跟踪插件,虽然这次用不着,但之后会用到。

还有一个界面组件文件,在resource下,名称叫stencilset.json。本身是英文的,可以通过替换它来达到汉化的效果。但现在还是先把它放到项目中去。
在这里插入图片描述
在editor-app/app-cfg.js中配置一下项目url。这个url是编辑器相关的后台服务的url。

ACTIVITI.CONFIG = {'contextRoot' : '/service',
};

我去掉了项目名。

3.后端部分
先引入两个activiti的模块,因为编辑器会用到这两个模块。

  <dependency><groupId>org.activiti</groupId><artifactId>activiti-modeler</artifactId><version>${activiti.version}</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-diagram-rest</artifactId><version>${activiti.version}</version></dependency>

其中需要将modeler模块的源代码放到src中,因为需要在其中做部分修改,主要是url的映射。

源码:
https://github.com/Activiti/Activiti/tree/master/modules/activiti-modeler

其中有3个类,都是Controller:

StencilsetRestResource #获取编辑器组件及配置项信息。
ModelEditorJsonRestResource #根据modelId获取model的节点信息,编辑器根据返回的json进行绘图。
ModelSaveRestResource #编辑器制图之后,将节点信息以json的形式提交给这个Controller,然后由其进行持久化操作。

需要修改的地方就三个,在每个Controller类上加上@RequestMapping注解,并指定值为"service"(对应前台app-cfg.js中配置的url)。

···
@RequestMapping("service")
public class StencilsetRestResource {
···
···
@RequestMapping("service")
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
···
···
@RequestMapping("service")
public class ModelSaveRestResource implements ModelDataJsonConstants {
···

最后别忘了添加包扫描,扫描activiti提供的这些controller。

@SpringBootApplication
@ComponentScan({"org.activiti","com.jerryl"})
public class SpringBootWithActivitiApplication {
···

这样整合部分就基本结束了,此时编辑器已经可以使用了。

至于界面的汉化,界面上各个组件,各个标签上的文字都是在resource下的stencilset.json文件中设置的,可以在网上找一个汉化后的stencilset.json文件替换掉,就能看到中文界面了。

modeler相关方法的封装
主要需要封装4个方法:1.新建一个空的模型;2.所有模型列表;3.发布模型;4.删除模型;(activiti已提供了保存和获取模型节点信息的方法,就是上面的那3个类)
由于这里涉及前后端交互,实现方式随意,主要是activiti的api的调用。

参考代码:

/*** Created by liuruijie on 2017/2/21.* 模型管理*/
@RestController
@RequestMapping("models")
public class ModelerController {@AutowiredProcessEngine processEngine;@AutowiredObjectMapper objectMapper;/*** 新建一个空模型* @return* @throws UnsupportedEncodingException*/@PostMappingpublic Object newModel() throws UnsupportedEncodingException {RepositoryService repositoryService = processEngine.getRepositoryService();//初始化一个空模型Model model = repositoryService.newModel();//设置一些默认信息String name = "new-process";String description = "";int revision = 1;String key = "process";ObjectNode modelNode = objectMapper.createObjectNode();modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);model.setName(name);model.setKey(key);model.setMetaInfo(modelNode.toString());repositoryService.saveModel(model);String id = model.getId();//完善ModelEditorSourceObjectNode editorNode = objectMapper.createObjectNode();editorNode.put("id", "canvas");editorNode.put("resourceId", "canvas");ObjectNode stencilSetNode = objectMapper.createObjectNode();stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#");editorNode.put("stencilset", stencilSetNode);repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));return ToWeb.buildResult().redirectUrl("/modeler.html?modelId="+id);}/*** 获取所有模型* @return*/@GetMappingpublic Object modelList(){RepositoryService repositoryService = processEngine.getRepositoryService();List<Model> models = repositoryService.createModelQuery().list();return ToWeb.buildResult().putData("models", models);}/*** 删除模型* @param id* @return*/@DeleteMapping("{id}")public Object deleteModel(@PathVariable("id")String id){RepositoryService repositoryService = processEngine.getRepositoryService();repositoryService.deleteModel(id);return ToWeb.buildResult().refresh();}/*** 发布模型为流程定义* @param id* @return* @throws Exception*/@PostMapping("{id}/deployment")public Object deploy(@PathVariable("id")String id) throws Exception {//获取模型RepositoryService repositoryService = processEngine.getRepositoryService();Model modelData = repositoryService.getModel(id);byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());if (bytes == null) {return ToWeb.buildResult().status(Config.FAIL).msg("模型数据为空,请先设计流程并成功保存,再进行发布。");}JsonNode modelNode = new ObjectMapper().readTree(bytes);BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);if(model.getProcesses().size()==0){return ToWeb.buildResult().status(Config.FAIL).msg("数据模型不符要求,请至少设计一条主线流程。");}byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);//发布流程String processName = modelData.getName() + ".bpmn20.xml";Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes, "UTF-8")).deploy();modelData.setDeploymentId(deployment.getId());repositoryService.saveModel(modelData);return ToWeb.buildResult().refresh();}
}

springboot静态文件处理

@Configuration
public  class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry){registry.addResourceHandler("/html/**").addResourceLocations("classpath:/html/");registry.addResourceHandler("/diagram-viewer/**").addResourceLocations("classpath:/html/");registry.addResourceHandler("/editor-app/**").addResourceLocations("classpath:/html/");registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/");registry.addResourceHandler("/css/**").addResourceLocations("classpath:/css/");}
}

获取json数据的请求

@RestController
public class Test01Controller {@RequestMapping("/editor/stencilset")public String test01(){InputStream stream=this.getClass().getClassLoader().getResourceAsStream("stencilset.json");try{return IOUtils.toString(stream,"utf-8");}catch (Exception e){}return null;}
}

在线设计流程新建model

@Controller
@RequestMapping("model")
public class ModelTest {@RequestMapping("create")public void createModel(HttpServletRequest request, HttpServletResponse response){try{String modelName = "modelName6";String modelKey = "modelKey66";String description = "modelKey666";ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();ObjectMapper objectMapper = new ObjectMapper();ObjectNode editorNode = objectMapper.createObjectNode();editorNode.put("id", "canvas");editorNode.put("resourceId", "canvas");ObjectNode stencilSetNode = objectMapper.createObjectNode();stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");editorNode.put("stencilset", stencilSetNode);Model modelData = repositoryService.newModel();ObjectNode modelObjectNode = objectMapper.createObjectNode();modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, modelName);modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);modelData.setMetaInfo(modelObjectNode.toString());modelData.setName(modelName);modelData.setKey(modelKey);//保存模型repositoryService.saveModel(modelData);repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));response.sendRedirect(request.getContextPath() + "/html/modeler.html?modelId=" + modelData.getId());}catch (Exception e){}}}

画流程图保存请求

@RequestMapping("/model/{modelId}/save")@ResponseStatus(HttpStatus.OK)public void saveModel(@PathVariable String modelId, HttpServletRequest req, HttpServletResponse resp) {try {Model model = this.repositoryService.getModel(modelId);ObjectNode modelJson = (ObjectNode)this.objectMapper.readTree(model.getMetaInfo());modelJson.put("name", req.getParameter("name"));modelJson.put("description",req.getParameter("description"));model.setMetaInfo(modelJson.toString());model.setName(req.getParameter("name"));this.repositoryService.saveModel(model);this.repositoryService.addModelEditorSource(model.getId(), (req.getParameter("json_xml")).getBytes("utf-8"));InputStream svgStream = new ByteArrayInputStream((req.getParameter("svg_xml")).getBytes("utf-8"));TranscoderInput input = new TranscoderInput(svgStream);PNGTranscoder transcoder = new PNGTranscoder();ByteArrayOutputStream outStream = new ByteArrayOutputStream();TranscoderOutput output = new TranscoderOutput(outStream);transcoder.transcode(input, output);byte[] result = outStream.toByteArray();System.out.println(new String(result,"utf-8"));this.repositoryService.addModelEditorSourceExtra(model.getId(), result);outStream.close();} catch (Exception var11) {LOGGER.error("Error saving model", var11);throw new ActivitiException("Error saving model", var11);}}

流程图查看的请求

@RequestMapping(value = {"/model/{modelId}/json"},method = {RequestMethod.GET},produces = {"application/json"})public ObjectNode getEditorJson(@PathVariable String modelId) {ObjectNode modelNode = null;Model model = this.repositoryService.getModel(modelId);if (model != null) {try {if (StringUtils.isNotEmpty(model.getMetaInfo())) {modelNode = (ObjectNode)this.objectMapper.readTree(model.getMetaInfo());} else {modelNode = this.objectMapper.createObjectNode();modelNode.put("name", model.getName());}modelNode.put("modelId", model.getId());ObjectNode editorJsonNode = (ObjectNode)this.objectMapper.readTree(new String(this.repositoryService.getModelEditorSource(model.getId()), "utf-8"));modelNode.put("model", editorJsonNode);} catch (Exception var5) {LOGGER.error("Error creating model JSON", var5);throw new ActivitiException("Error creating model JSON", var5);}}return modelNode;}

流程图保存成功以后ACT_RE_MODEL这张表会有数据

在这里插入图片描述

程图部署以后ACT_GE_BYTEARRAY会出现bomn结尾的文件
在这里插入图片描述

部署流程的请求,根据modelId

@RequestMapping("/model/test02")public void test02(Object obj) throws Exception {Model modelData = repositoryService.getModel("40001");ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));byte[] bpmnBytes = null;BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);bpmnBytes = new BpmnXMLConverter().convertToXML(model);String processName = modelData.getName() + ".bpmn";Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes,"UTF-8")).deploy();}

根据这个表的key进行流程启动,指定审批人
在这里插入图片描述

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

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

相关文章

zabbix监控平台部署(二)

目录 一、自定义监控 二、Nginx监控 三、监控mysql 四、钉钉告警 五、163邮箱报警 总结 zabbix5.0 一、自定义监控 zabbix-agent&#xff08;147&#xff09; agent端操作 vim /etc/zabbix/zabbix_agentd.conf 在配置未文件末尾添加 UserParametermemory_userd,free…

vue修改node_modules打补丁步骤和注意事项

当我们使用 npm 上的第三方依赖包&#xff0c;如果发现 bug 时&#xff0c;怎么办呢&#xff1f; 想想我们在使用第三方依赖包时如果遇到了bug&#xff0c;通常解决的方式都是绕过这个问题&#xff0c;使用其他方式解决&#xff0c;较为麻烦。或者给作者提个issue&#xff0c;然…

【Java 基础篇】Java后台线程和守护线程详解

在Java多线程编程中&#xff0c;有两种特殊类型的线程&#xff1a;后台线程&#xff08;Daemon Thread&#xff09;和守护线程&#xff08;Daemon Thread&#xff09;。这两种线程在一些特定的场景下非常有用&#xff0c;但也需要谨慎使用。本文将详细介绍后台线程和守护线程的…

(JavaEE)(多线程案例)线程池 (简单介绍了工厂模式)(含经典面试题ThreadPoolExector构造方法)

线程诞生的意义&#xff0c;是因为进程的创建/销毁&#xff0c;太重了&#xff08;比较慢&#xff09;&#xff0c;虽然和进程比&#xff0c;线程更快了&#xff0c;但是如果进一步提高线程创建销毁的频率&#xff0c;线程的开销就不能忽视了。 这时候我们就要找一些其他的办法…

Ansible之Playbook的任务控制

一&#xff09;Ansible 任务控制基本介绍 这⾥主要来介绍PlayBook中的任务控制。 任务控制类似于编程语⾔中的if … 、for … 等逻辑控制语句。 这⾥我们给出⼀个实际场景应⽤案例去说明在PlayBook中&#xff0c;任务控制如何应⽤。 在下⾯的PlayBook中&#xff0c;我们创建了…

pnpm入门教程

一、概述 1、更小 使用 npm 时&#xff0c;依赖每次被不同的项目使用&#xff0c;都会重复安装一次。 而在使用 pnpm 时&#xff0c;依赖会被存储在内容可寻址的存储中。 2、更快 依赖解析。 仓库中没有的依赖都被识别并获取到仓库。目录结构计算。 node_modules 目录结构是…

什么是GPT磁盘?介绍GPT(GUID 分区表)磁盘及其优势!

GPT概述 GPT磁盘是什么意思&#xff1f;GPT是全局唯一标识符分区表&#xff08;GUID Partition Table&#xff09;的简称&#xff0c;它是硬盘分区表结构的一个标准模式。在我们深入了解GPT磁盘的特性之前须知&#xff0c;MBR磁盘的分区信息直接保存在主引导记录&#xff0…

【探索C语言中VS调试技巧】:提高效率和准确性

文章目录 前言1. 什么是bug&#xff1f;2. 调试是什么&#xff1f;有多重要&#xff1f;2.1 调试是什么&#xff1f;2.2 调试的基本步骤2.3 Debug和Release的介绍 3. Windows环境调试介绍3.1 调试环境的准备3.2 学会快捷键3.3 调试的时候查看程序当前信息3.3.1 查看临时变量的值…

【C++】动态内存管理 ③ ( C++ 对象的动态创建和释放 | new 运算符 为类对象 分配内存 | delete 运算符 释放对象内存 )

文章目录 一、C 对象的动态创建和释放1、C 语言 对象的动态创建和释放 的方式2、C 语言 对象的动态创建和释放 的方式 二、代码示例 - 对象的动态创建和释放 一、C 对象的动态创建和释放 使用 C 语言中的 malloc 函数 可以为 类对象 分配内存 ; 使用 free 函数可以释放上述分配…

Android 富文本SpannableString

一、认识SpannableString 为什么要使用富文本 在Android开发中&#xff0c;有很多UI会画出一些特别炫酷的界面出来&#xff0c;比如一个字符串里有特殊的字会有其他颜色并加粗、变大变小、插入小图片、给某几个文字添加边框&#xff0c;如果我们使用笨办法用几个TextView或者Im…

单片机第三季-第三课:STM32开发板原理图、配置、浮点运算单元

目录 1&#xff0c;开发板原理图 2&#xff0c;浮点运算单元&#xff08;FPU&#xff09; 1&#xff0c;开发板原理图 课程视频比较早&#xff0c;介绍了三款开发板。观看视频时用的开发板说和51单片机共板的STM32核心板&#xff0c;将51单片机从底座拆下来后&#xff0c;安…

avi怎么转换成视频?

avi怎么转换成视频&#xff1f;在我们日常使用的视频格式中&#xff0c;AVI是一种常见且经常被使用的音频视频交叉格式之一。它的优点之一是占用的存储空间相对较小&#xff0c;但也明显存在着画质损失的缺点。虽然AVI格式的视频在某种程度上也很常见&#xff0c;但与最常见的M…

zabbix的原理与安装

一、Zabbix介绍 1、zabbix 是什么&#xff1f; zabbix是一个开源的IT基础监控软件&#xff0c;能实时监控网络服务&#xff0c;服务器和网络设备的状态&#xff0c;如网络使用&#xff0c;CPU负载、磁盘空间等&#xff0c;主要是包括数据的收集、报警和通知的可视化界面zabbi…

VHOST-SCSI代码分析(1)VHOST SCSI设备模拟

VHOST SCSI设备的模拟是由QEMU和HOST共同实现的&#xff0c;QEMU模拟VHOST SCSI设备配置空间等&#xff0c;而对于虚拟机通知HOST和HOST通知虚拟机机制由HOST内核实现。 在QEMU中VHOST SCSI设备继承关系如下&#xff1a; 其它设备以及对应class_init函数和realize具现化实现与V…

LLM微调(一)| 单GPU使用QLoRA微调Llama 2.0实战

最近LLaMA 2在LLaMA1 的基础上做了很多优化&#xff0c;比如上下文从2048扩展到4096&#xff0c;使用了Grouped-Query Attention&#xff08;GQA&#xff09;共享多头注意力的key 和value矩阵&#xff0c;具体可以参考&#xff1a; 关于LLaMA 2 的细节&#xff0c;可以参考如下…

zotero通过DOI快速导入文献

之前我经常采用两种方式导入文献&#xff1a; &#xff08;1&#xff09;下载PDF&#xff0c;然后拖入zotero 这种方法比较费时间&#xff0c;有些文献无法下载pdf &#xff08;2&#xff09;通过google scholar检索文献&#xff0c;然后点击引用——EndNote&#xff0c;chorme…

Kotlin中函数的基本用法以及函数类型

函数的基本用法 1、函数的基本格式 2、函数的缺省值 可以为函数设置指定的初始值&#xff0c;而不必要传入值 private fun fix(name: String,age: Int 2){println(name age) }fun main(args: Array<String>) {fix("张三") }输出结果为&#xff1a;张三2 …

WebGL层次模型——多节点模型

目录 多节点模型 MultiJointModel中的层次结构 控制各部件旋转角度的变量 示例程序——共用顶点数据&#xff0c;通过模型矩阵缩放实现&#xff08;MultiJointModel.js&#xff09; MultiJointModel.js&#xff08;按键响应部分&#xff09; MultiJointModel.js&#x…

刷题日记——将x减到0的最小操作数

将x减到0的最小操作数 题目链接&#xff1a;https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/ 题目解读 题目要求移除元素总和等于参数x&#xff0c;这道题给我的第一感觉就是从数组的两边入手&#xff0c;对数据进行加和删除&#xff0c;但是这里有一…

滚雪球学Java(24):Java反射

&#x1f3c6;本文收录于「滚雪球学Java」专栏&#xff0c;专业攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎大家关注&&收藏&#xff01;持续更新中&#xff0c;up&#xff01;up&#xff01;up&#xff01;&#xf…