当前位置: 首页 > news >正文

做网站就用建站之星网站seo查询站长之家

做网站就用建站之星,网站seo查询站长之家,wordpress 微网站,国外有哪做交互设计网站简单的Activiti Modoler 流程在线编辑器 1.需求 我们公司使用的流程是activiti5.22.0,版本有些老了,然后使用的编辑器都是eclipse的流程编辑器插件,每次编辑流程需要打开eclipse进行编辑,然后再导入到项目里面,不是特…

简单的Activiti Modoler 流程在线编辑器

1.需求

我们公司使用的流程是activiti5.22.0,版本有些老了,然后使用的编辑器都是eclipse的流程编辑器插件,每次编辑流程需要打开eclipse进行编辑,然后再导入到项目里面,不是特别方便,所以我们决定使用官方提供的 Activiti Modoler,实现项目集成在线编辑器,方便流程的发布编辑以及部署。

2.具体实现步骤

整体的实现步骤就是从官网下载对应的activiti5.22.0 或者版本相近的包,然后找到对应的前端需要集成的文件以及controller等文件,添加到自己的项目中,我使用的springboot项目,然后需要配置静态资源的对应的地址信息,便可以进行简单的使用了。

2.1 添加pom需要jar包

我们此处就只列举了流程所需包,其他包简略

	<!-- activiti 5.22.0启动器,排除mybatis依赖 --><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter-basic</artifactId><version>5.22.0</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-diagram-rest</artifactId><version>5.22.0</version></dependency><!-- Activiti在线设计 --><dependency><groupId>org.activiti</groupId><artifactId>activiti-modeler</artifactId><version>5.22.0</version></dependency>

2.2 下载包

我们下载的地址为 activiti5.x.x 官方包
在这里插入图片描述

2.3 解压复制文件到项目中

替换文件主要是两部分,一部分为java文件,一部分为静态资源文件,首先替换java文件
activiti-webexplore\Activiti-5.x\modules\activiti-modeler\src\main\java\org\activiti\rest\editor 向下的所有java文件到自己项目中
在这里插入图片描述

注意,ModelSaveRestResource 对应的请求方式修改为 POST。

在之后我们需要添加一个发起流程图编辑或新增的入口 ModelerController,发起以及修改全部从此方法进入,最后导入后台文件效果如下
在这里插入图片描述
最后添加的几个controller代码如下:

  • ModelEditorJsonRestResource

    package cn.git.workflow.modeler;import cn.git.common.exception.ServiceException;
    import cn.git.common.util.LogUtil;
    import cn.hutool.core.util.ObjectUtil;
    import cn.hutool.core.util.StrUtil;
    import com.alibaba.fastjson.JSONObject;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.activiti.editor.constants.ModelDataJsonConstants;
    import org.activiti.engine.RepositoryService;
    import org.activiti.engine.repository.Model;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;import java.nio.charset.StandardCharsets;/*** @description: 通过modelId获取流程model json数据* @program: bank-credit-sy* @author: lixuchun* @create: 2024-11-21*/
    @Api(value = "model流程设计器获取json数据", tags = "model流程设计器获取json数据")
    @Slf4j
    @RestController
    public class ModelEditorJsonRestResource implements ModelDataJsonConstants {@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate ObjectMapper objectMapper;/*** 获取流程图json数据** @param modelId* @return*/@ApiOperation(value = "获取流程图json数据", notes = "获取流程图json数据")@RequestMapping(value = "/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")public Object getEditorJson(@PathVariable String modelId) {// 最终响应数据ObjectNode modelNode = null;Model model = repositoryService.getModel(modelId);// 获取流程定义if (ObjectUtil.isNotNull(model)) {try {// 获取流程定义的JSON数据if (StrUtil.isNotBlank(model.getMetaInfo())) {modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());} else {modelNode = objectMapper.createObjectNode();modelNode.put(MODEL_NAME, model.getName());}// 设置流程定义的IDmodelNode.put(MODEL_ID, model.getId());// 获取流程定义的JSON数据ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(new String(repositoryService.getModelEditorSource(model.getId()), StandardCharsets.UTF_8));modelNode.put("model", editorJsonNode);} catch (Exception e) {log.error(StrUtil.format("通过modelId获取model对应json数据失败,失败信息为[{}]", LogUtil.getStackTraceInfo(e)));throw new ServiceException("通过modelId获取model对应json数据失败!");}}return JSONObject.parseObject(modelNode.toString());}
    }
  • ModelerController

    package cn.git.workflow.modeler;import cn.hutool.core.util.ObjectUtil;
    import cn.hutool.core.util.StrUtil;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.activiti.editor.constants.ModelDataJsonConstants;
    import org.activiti.engine.RepositoryService;
    import org.activiti.engine.repository.Model;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;import javax.annotation.Resource;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    import java.rmi.ServerException;/** * @description: model流程设计器保存* @program: bank-credit-sy* @author: lixuchun* @create: 2024-11-21*/
    @Api(value = "model流程设计器保存", tags = "model流程图画图模块保存")
    @Controller
    @RequestMapping("/modeler")
    public class ModelerController {@Resourceprivate RepositoryService repositoryService;@Resourceprivate ObjectMapper objectMapper;/*** 初始化流程设计器方法,跳转至流程设计器** @param modelName      模型名称* @param modelKey       模型key* @param modelDescription 模型描述* @param modelId        模型id* @return*/@ApiOperation(value = "初始化流程设计器方法,跳转至流程设计器", notes = "初始化流程设计器方法,跳转至流程设计器")@GetMapping("/save")public void save(HttpServletResponse response,@RequestParam(value = "modelName", required = false) String modelName,@RequestParam(value = "modelKey", required = false) String modelKey,@RequestParam(value = "modelDescription", required = false) String modelDescription,@RequestParam(value = "modelId", required = false) String modelId) throws IOException {// 如果有modelId,则直接跳转if (StrUtil.isNotBlank(modelId)) {Model model = repositoryService.getModel(modelId);if (ObjectUtil.isNotNull(model)) {response.sendRedirect("/static/activiti/modeler.html?modelId=" + model.getId());} else {throw new ServerException(StrUtil.format("模型不存在,请检查modelId[{}]", modelId));}} else {// modelId为空,则表示请求为新建一个模型,则进行必填参数校验if (StrUtil.isBlank(modelName) ||StrUtil.isBlank(modelKey) || StrUtil.isBlank(modelDescription)) {throw new ServerException("参数[modelName, modelKey, modelDescription]不能为空,请确认!");}// 创建模型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, modelDescription);// 以字符串信息存储进信息属性中modelData.setMetaInfo(modelObjectNode.toString());// 模型名称modelData.setName(modelName);// 模型keymodelData.setKey(modelKey);// 初始化json数据ObjectNode editorNode = objectMapper.createObjectNode();editorNode.put("id", "canvas");editorNode.put("resourceId", "canvas");// 创建一个stencilset节点ObjectNode stencilSetNode = objectMapper.createObjectNode();stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");editorNode.set("stencilset", stencilSetNode);// 添加模型repositoryService.saveModel(modelData);repositoryService.addModelEditorSource(modelData.getId(),editorNode.toString().getBytes(StandardCharsets.UTF_8));response.sendRedirect("/static/activiti/modeler.html?modelId=" + modelData.getId());}}}
    
  • ModelSaveRestResource

    注意:此方法,请求方式修改为POST

    package cn.git.workflow.modeler;import cn.git.common.exception.ServiceException;
    import cn.git.common.result.Result;
    import cn.git.common.util.LogUtil;
    import cn.hutool.core.util.StrUtil;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.activiti.editor.constants.ModelDataJsonConstants;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.*;import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import java.nio.charset.StandardCharsets;/** * @description: 控制器类用于保存activiti模型* @program: bank-credit-sy* @author: lixuchun* @create: 2024-11-21*/
    @Api(value = "model流程设计器编辑保存", tags = "model流程设计器编辑保存")
    @RestController
    public class ModelSaveRestResource implements ModelDataJsonConstants {protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);@Autowiredprivate RepositoryService repositoryService;/*** Jackson ObjectMapper*/@Autowiredprivate ObjectMapper objectMapper;/*** 模型修改,通过jsno格式保存信息** @param modelId 模型 ID* @param name 模型名称* @param description 模型描述* @param json_xml JSON 格式的模型数据* @param svg_xml SVG 格式的模型数据*/@ApiOperation(value = "模型修改,通过jsno格式保存信息", notes = "模型修改,通过jsno格式保存信息")@RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.POST)@ResponseStatus(value = HttpStatus.OK)public Result<String> saveModel(@PathVariable String modelId, String name, String description, String json_xml, String svg_xml) {// 创建一个 ByteArrayOutputStream 对象,用于存储转换后的 PNG 图像try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) {// 获取指定 ID 的模型Model model = repositoryService.getModel(modelId);// 将模型的元数据转换为 JSON 对象ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());// 更新模型的名称和描述modelJson.put(MODEL_NAME, name);modelJson.put(MODEL_DESCRIPTION, description);model.setMetaInfo(modelJson.toString());model.setName(name);// 保存更新后的模型repositoryService.saveModel(model);// 将 JSON 格式的模型数据保存到模型编辑源repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes(StandardCharsets.UTF_8));// 将 SVG 格式的模型数据转换为 PNG 图像InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes(StandardCharsets.UTF_8));TranscoderInput input = new TranscoderInput(svgStream);PNGTranscoder transcoder = new PNGTranscoder();// 设置输出流TranscoderOutput output = new TranscoderOutput(outStream);// 执行转换transcoder.transcode(input, output);final byte[] result = outStream.toByteArray();// 将转换后的 PNG 图像保存到模型编辑源额外数据repositoryService.addModelEditorSourceExtra(model.getId(), result);return Result.ok("保存成功!");} catch (Exception e) {throw new ServiceException(StrUtil.format("模型保存失败,具体失败原因为[{}]", LogUtil.getStackTraceInfo(e)));}}
    }
  • StencilsetRestResource

    package cn.git.workflow.modeler;import java.io.InputStream;import com.alibaba.fastjson.JSONObject;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.activiti.engine.ActivitiException;
    import org.apache.commons.io.IOUtils;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;/*** @description: 在线模板中文转义文件获取* @program: bank-credit-sy* @author: lixuchun* @create: 2024-11-20*/
    @Api(value = "model流程设计器加载中文模板文件", tags = "model流程设计器加载中文模板文件")
    @RestController
    public class StencilsetRestResource {/*** 在线编辑器中文模板文件*/public static final String EDITOR_CH_FILE = "stencilset.json";/*** 获取在线编辑器中文模板文件** @return*/@ApiOperation(value = "加载stencilset.json中文文件", notes = "加载stencilset.json中文文件")@RequestMapping(value = "/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")public @ResponseBody Object getStencilset() {InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(EDITOR_CH_FILE);try {assert inputStream != null;return JSONObject.parseObject(IOUtils.toString(inputStream, "utf-8"));} catch (Exception e) {throw new ActivitiException("获取流程在线编辑器中文模板失败!", e);}}
    }

我们的项目是springboot前后端分离项目,我们整合的流程在线编辑器与前端项目需要进行 iframe 嵌套,所以有跨域问题。需要开放允许跨域。具体代码如下:

  • GlobalCrossConfig
    package cn.git.workflow.config;import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;/*** 通用跨域设置,允许跨域访问本项目* @program: bank-credit-sy* @author: lixuchun* @create: 2021-06-01*/
    @Configuration
    public class GlobalCrossConfig {/*** 设置跨域配置信息*/@Beanpublic CorsFilter corsFilter() {CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*");corsConfiguration.setAllowCredentials(true);corsConfiguration.addAllowedMethod("*");corsConfiguration.addAllowedHeader("*");corsConfiguration.addExposedHeader("*");UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();configSource.registerCorsConfiguration("/**", corsConfiguration);return new CorsFilter(configSource);}}

除此之外,还需要开启允许进行iframe嵌套,需要禁用X-Frame-Options头。X-Frame-Options是一个HTTP响应头,用于控制浏览器是否允许在一个 <frame>, <iframe>, 或 <object> 中加载页面。默认情况下,这个头会设置为 DENY 或 SAMEORIGIN,以防止点击劫持(Clickjacking)攻击。

调用 disable() 方法会禁用 X-Frame-Options 头,即不在响应中发送这个头。这样,页面可以在任何域的 <frame><iframe> 中加载,具体操作代码如下

  • SecurityConfig
    package cn.git.workflow.config;import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** @description: 禁用activiti-rest引入后的security主动校验功能* @program: bank-credit-sy* @author: lixuchun* @create: 2024-06-11*/
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 禁用activiti-rest引入后的security主动校验功能* @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {// 关闭securityhttp.httpBasic().disable().csrf().disable()// 允许iframe嵌套.headers().frameOptions().disable();http.authorizeRequests().anyRequest().permitAll();}
    }
    

我们还需要设置静态资源信息,提供我们在线编辑器的再跳转功能,具体设置如下:

  • WebMvcConfig

    package cn.git.workflow.config;import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** @description: 添加fastjson转换器* @program: bank-credit-sy* @author: lixuchun* @create: 2024-11-21*/
    @Configuration
    class WebMvcConfig implements WebMvcConfigurer {/*** 添加静态资源文件,外部可以直接访问地址** @param registry*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 添加外部静态资源registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");// 添加模板信息registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");}
    }
    

2.4 前端文件设置

具体替换文件 activiti-webexplore\Activiti-5.x\modules\activiti-webapp-explorer2\src\main\webapp下的是哪个文件
在这里插入图片描述
以及 activiti-webexplore\Activiti-5.x\modules\activiti-webapp-explorer2\src\main\resource目录下的文件标签文件
在这里插入图片描述
最终复制文件到项目中,目录格式如下
在这里插入图片描述

注意:我们也可以替换 stencilset.json,将流程页面展示信息变更为中文提示信息,此为中文文件地址

修改 app-cfg.js文件,将contextRoot 修改为空

var ACTIVITI = ACTIVITI || {};
ACTIVITI.CONFIG = {'contextRoot' : '',
};

修改 /editor-app/configuration/toolbar-default-actions.js,update方法修改请求方式为POST,对应前面ModelSaveRestResource请求方式修改为POST
在这里插入图片描述

3. 进行测试

测试分为两个部分,一个是流程服务自己测试,一个是使用iframe嵌套到前端项目中,进行测试

3.1 流程项目自己测试

启动服务,我们便可以进行简单测试了,访问 http://3.1.19.13:11203/modeler/save?modelName=测试啦999&modelKey=jackAoteMan&modelDescription=杰克奥特曼 进行新增
在这里插入图片描述
在这里插入图片描述
访问 http://3.1.19.13:11203/modeler/save?modelId=9fb167fa2434422697090a8ea56467e8 可以进行修改编辑
在这里插入图片描述

3.2 前端嵌入iframe测试

我们公司则是将其嵌入到了公司的前端项目中,我们通过公司前端进行访问,访问我们新增的流程model信息
在这里插入图片描述
点击修改按钮,进行简单修改
在这里插入图片描述
点击部署按钮,进行部署,之后此流程便可以正常使用了
在这里插入图片描述
在这里插入图片描述

除了部署修改,还有移除,下载xml文件等操作,此处便不多赘述,部署之后,可以在已部署目录中查看已部署信息,包含历史全部部署文件信息,可以分版本下载查看
在这里插入图片描述

本文参考此篇博文

http://www.qdjiajiao.com/news/3196.html

相关文章:

  • 有专门做预算的网站没广州seo招聘信息
  • 新手怎么做自己网站广告北京seo邢云涛
  • 用凡科做网站好弄吗我想做电商怎么加入
  • 各大网站什么时候恢复彩色seo怎么做最佳
  • 响应式网站建设策划市场营销教材电子版
  • 手机触屏网站制作软件技能培训有哪些
  • 网站开发用户需求seo小白入门教学
  • 桂林两江四湖象山景区简介杭州网站seo价格
  • 合肥建设银行官网招聘网站市场营销模式有哪些
  • 如何抄袭网站百度站内搜索提升关键词排名
  • 深圳有名的做公司网站安卓优化大师旧版本下载
  • 建设网站考虑因素湛江seo网站管理
  • 网站建设com百度网盘官方下载
  • 文化厅加强网站建设2022年百度seo
  • 有名的网站制作电话新闻软文发布平台
  • 阿里云 oss做网站关键词seo服务
  • 手表网站推荐深圳网站搜索优化
  • 无锡网络公司网站建设谷歌seo优化怎么做
  • 专业建站公司费用赣州seo培训
  • 个人做网站的好处体验营销
  • 绵阳公司网站建设seo搜索引擎优化技术教程
  • 厦门网站代理学生个人网页制作
  • wordpress网站搬家换域名bt搜索引擎
  • 网站gbk 和utf8宁德市人口
  • 网站建设怎么谈竞价系统
  • excel做公司的小网站大连百度seo
  • 婚恋网注册超级优化大师
  • 纯静态做企业网站精准客户软件
  • 怎么找网站站长国际新闻快报
  • 做甜品网站seo外链网