简单的Activiti Modoler 流程在线编辑器
简单的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文件等操作,此处便不多赘述,部署之后,可以在已部署目录中查看已部署信息,包含历史全部部署文件信息,可以分版本下载查看
本文参考此篇博文
相关文章:
简单的Activiti Modoler 流程在线编辑器
简单的Activiti Modoler 流程在线编辑器 1.需求 我们公司使用的流程是activiti5.22.0,版本有些老了,然后使用的编辑器都是eclipse的流程编辑器插件,每次编辑流程需要打开eclipse进行编辑,然后再导入到项目里面,不是特…...
【NodeJS】Express写接口的整体流程
前提条件 开发 Node.js,首先就必须要安装 Node.js。推荐使用 nvm,它可以随意切换 node 版本。下载 nvm,具体可以看本人另一篇文章:nvm的作用、下载、使用、以及Mac使用时遇到commond not found:nvm如何解决。 nvm官方࿱…...
Oracle 锁表的解决方法及避免锁表问题的最佳实践
背景介绍 在 Oracle 数据库中,锁表或锁超时相信大家都不陌生,是一个常见的问题,尤其是在执行 DML(数据操作语言)语句时。当一个会话对表或行进行锁定但未提交事务时,其他会话可能会因为等待锁资源而出现超…...
关于 vue+element 日期时间选择器 限制只能选当天以及30天之前的日期
业务需求,需要实现选择当天以及30天之前的日期,于是我想到的是利用picker-options去限制可选范围 代码如下 <el-date-pickerv-model"searchData.acceptTime"type"datetimerange"value-format"yyyy-MM-dd hh:mm:ss"styl…...
租辆酷车小程序开发(二)—— 接入微服务GRPC
vscode中golang的配置 设置依赖管理 go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct GO111MODULEauto 在$GOPATH/src 外面且根目录有go.mod 文件时,开启模块支持 GO111MODULEoff 无模块支持,go会从GOPATH 和 vendor 文件夹寻找包…...
如何在 Ubuntu 22.04 上安装 Metabase 数据可视化分析工具
简介 Metabase 提供了一个简单易用的界面,让你能够轻松地对数据进行探索和分析。通过本文的指导,你将能够在 Ubuntu 22.04 系统上安装并配置 Metabase,并通过 Nginx 进行反向代理以提高安全性。本教程假设你已经拥有了一个非 root 用户&…...
MySQL 用户与权限管理
MySQL 是一种广泛使用的关系型数据库管理系统,支持多用户访问和权限控制。在多用户环境下,数据库安全至关重要,而用户和权限管理是数据库管理中最基础也是最重要的一部分。通过合理地创建和管理用户、分配和管理权限、使用角色权限,可以有效地保护数据库,确保数据的安全性…...
【Web前端】如何构建简单HTML表单?
HTML 表单是 Web 开发中非常重要的组成部分。它们是与用户交互的主要方式,能够收集用户输入的数据。表单的灵活性使它们成为 HTML 中最复杂的结构之一,但若使用正确的结构和元素,可以确保其可用性和无障碍性。 表单的基本结构 HTML 表单使用…...
Spring Boot 3 集成 Spring Security(3)数据管理
文章目录 准备工作新建项目引入MyBatis-Plus依赖创建表结构生成基础代码 逻辑实现application.yml配置SecurityConfig 配置自定义 UserDetailsService创建测试 启动测试 在前面的文章中我们介绍了 《Spring Boot 3 集成 Spring Security(1)认证》和 《…...
书生大模型实战营第四期-入门岛-4. maas课程任务
书生大模型实战营第四期-入门岛-4. maas课程任务 任务一、模型下载 任务内容 使用Hugging Face平台、魔搭社区平台(可选)和魔乐社区平台(可选)下载文档中提到的模型(至少需要下载config.json文件、model.safetensor…...
Spring ApplicationListener监听
【JavaWeb】Spring ApplicationListener-CSDN博客 ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布…...
K8s调度器扩展(scheduler)
1.K8S调度器 筛选插件扩展 为了熟悉 K8S调度器扩展步骤,目前只修改 筛选 插件 准备环境(到GitHub直接下载压缩包,然后解压,解压要在Linux系统下完成) 2. 编写调度器插件代码 在 Kubernetes 源代码目录下编写调度插件…...
IntelliJ IDEA 中,自动导包功能
在 IntelliJ IDEA 中,自动导包功能可以极大地提高开发效率,减少手动导入包所带来的繁琐和错误。以下是如何在 IntelliJ IDEA 中设置和使用自动导包功能的详细步骤: 一、设置自动导包 打开 IntelliJ IDEA: 启动 IntelliJ IDEA 并打…...
Spring事务笔记
目录 1.Spring 编程式事务 2.Transactional 3.事务隔离级别 4.Spring 事务传播机制 什么是事务? 事务是⼀组操作的集合, 是⼀个不可分割的操作. 事务会把所有的操作作为⼀个整体, ⼀起向数据库提交或者是撤销操作请求. 所以这组操作要么同时成 功, 要么同时失败 1.Spri…...
SQLite 管理工具 SQLiteStudio 3.4.5 发布
SQLiteStudio 3.4.5 版本现已发布,它带来了大量的 bug 修复,并增加了一些小功能。SQLiteStudio 是一个跨平台的 SQLite 数据库的管理工具。 具体更新内容包括: 现在可以使用 Collations Editor 窗口在数据库中注册 Extension-based collatio…...
QT 实现组织树状图
1.实现效果 在Qt中使用QGraphicsItem和QGraphicsScene实现树状图,你需要创建自定义的QGraphicsItem类来表示树的节点,并管理它们的位置和连接,以下是实现效果图。 2.实现思路 可以看见,上图所示,我们需要自定义连线类和节点类。 每个节点类Node,需要绘制矩形框体文字…...
go-学习
文章目录 简介标识符字符串的拼接,关键字数据类型声明变量常量算术运算符关系运算符逻辑运算符位运算赋值运算符其他运算符 简介 Go 语言的基础组成有以下几个部分: 1.包声明 2.引入包 3.函数 4.变量 5.语句 & 表达式 6.注释 package main import &q…...
【面试分享】主流编程语言的内存回收机制及其优缺点
以下是几种主流编程语言的内存回收机制及其优缺点: 一、Java 内存回收机制: Java 使用自动内存管理,主要通过垃圾回收器(Garbage Collector,GC)来回收不再被使用的对象所占用的内存。Java 的垃圾回收器会定…...
STM32-- 串口发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);?? 答: 这行代码: while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) RESET);的作用是等待串口 USART2 的发送数据寄存器(TXE,Transmit Dat…...
数据结构 (13)串的应用举例
前言 数据结构中的串(String),也称为字符串,是一种常见且重要的数据结构,在计算机科学中被广泛应用于各种场景。 一、文本处理 文本编辑器:在文本编辑器中,字符串被用来表示和存储用户输入的文本…...
qt-- - 版本和下载介绍
qt版本很多,每个大版本都有几个版本是长期支持的(LTS),最好使用长期支持的。 例如qt5.15 qt6.2 qt6.8 都是LTS版本的。 qt在线安装需要提供账号,之前安装qt6.8因为账号问题试了很长时间,密码错了。 …...
解锁 Vue 项目中 TSX 配置与应用简单攻略
在 Vue 项目中配置 TSX 写法 在 Vue 项目中使用 TSX 可以为我们带来更灵活、高效的开发体验,特别是在处理复杂组件逻辑和动态渲染时。以下是详细的配置步骤: 一、安装相关依赖 首先,我们需要在命令行中输入以下命令来安装 vitejs/plugin-v…...
ShuffleNet:一种为移动设备设计的极致高效的卷积神经网络
摘要 https://arxiv.org/pdf/1707.01083 我们介绍了一种名为ShuffleNet的计算效率极高的卷积神经网络(CNN)架构,该架构专为计算能力非常有限的移动设备(例如10-150 MFLOPs)而设计。新架构利用两种新操作:逐…...
yum源问题的解决方案
linux课堂作业 问题描述 yum 直接安装tree的问题截图 这个错误表明你的系统没有正确注册到 Red Hat Subscription Management(这个问题不用管),也没有配置有效的 YUM 软件仓库,因此无法安装或更新软件包。 解决方案(…...
在Linux中备份msyql数据库和表的详细操作
目录 前情提要 一、备份mysql数据库 原库展示 (一)新建一个数据库 (二)在linux根目录下找个位置暂时存放 (三)临时sql还原真正存放到库中 (四)查看是否备份成功 备份库成功展示 二、备份表的操作 编辑 原表emp展示 (一)快速新建一个原结构相同的表 (二)原表所…...
实时数仓Kappa架构:从入门到实战
引言 随着大数据技术的不断发展,企业对实时数据处理和分析的需求日益增长。实时数仓(Real-Time Data Warehouse, RTDW)应运而生,其中Kappa架构作为一种简化的数据处理架构,通过统一的流处理框架,解决了传统…...
【老白学 Java】Warship v2.0(四)
Warship v2.0(四) 文章来源:《Head First Java》修炼感悟。 上一篇文章中,老白仔细分析了 v2.0 的设计思路以及实现手段,如果大家有好的设计方案也可以自行尝试。 本篇文章的主要内容是对 Warship 类进行最后的修改&a…...
LLM之学习笔记(一)
前言 记录一下自己的学习历程,也怕自己忘掉了某些知识点 Prefix LM 和 Causal LM区别是什么? Prefix LM (前缀语⾔模型)和 Causal LM(因果语言模型)是两者不同类型的语言模型,它们的区别在于生…...
C# 反射详解
反射是C#中的一个强大特性,允许程序在运行时检查和操作类型和对象的信息。 通过反射,你可以获取类型的属性、方法、构造函数等信息,并可以动态创建对象、调用方法或访问属性,甚至可以实现某些框架或库的核心功能。 反射的基本概念…...
pgadmin安装后运行不能启动界面的问题
在本人机器上安装了pgsql10后,自带的pgadmin安装后运行时能打开edge并显示数据库server和数据库的,后来又安装了pgsql17,结果安装后想打开pgadmin,结果一直在等待最后,爆出类似于下面的错误。 pgAdmin Runtime Enviro…...
35公司做的网站漏洞/如何做好关键词的优化
基本类型,或者叫做内置类型,是JAVA中不同于类的特殊类型。它们是我们编程中使用最频繁的类型。java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量的初始化。 1、基本类型及其封装器类 Java基本类型共有…...
网络科技公司网站建设策划/百度热搜榜排名今日p2p
Java技术栈www.javastack.cn关注阅读更多优质文章作者:稻草叔叔来源:juejin.im/post/6844903635533594632Git 是目前最流行的源代码管理工具。为规范开发,保持代码提交记录以及 git 分支结构清晰,方便后续维护,现规范 …...
如何设置网站关键词/自媒体135网站
更正:我使用这种方式制作了完整安装包9.4.3,9.4.3安装好以后更新到9.4.4没有问题,然后从9.4.4更新到这个月的9.4.5时需要安装包中的.msi文件。这可能会给IT管理员带来不便,出现此问题时需要把Adobe Reader卸载,再重新安…...
wordpress 被镜像/汕头seo排名公司
1. 学好学通c语言的许多种理由单片机需要C语言Java及C#和C语言很像Python是C语言的封装嵌入式Linux编程和开发需要C语言Javascript语言和C语言很像C和C语言很像C语言比汇编容易学……C语言可以引导人们开启编程的大门,教给人们计算机编程的套路,更加彻底…...
浙江做铁塔的公司网站/非企户百度推广
This tutorial is highly referenced from Emmanuel Henri’s LinkedIn Learning tutorial released 11/5/2019.本教程由Emmanuel Henri于2019年11月5日发布的LinkedIn学习教程高度引用。 It took me a long time to find a resource to help me on my journey of building a …...
wordpress 网店/软件培训机构排名
增删节点 数据迁移一、所有事情开始之前,先要备份好cloudera manager的数据库,以及hadoop集群中的一些组件带的数据库。这里保存了很多元数据,像hive这种丢了很麻烦的。二、如果需要换nameNode的存储目录1、备份nameNode原始数据cp -r /ddhom…...