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

简单的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&#xff0c;版本有些老了&#xff0c;然后使用的编辑器都是eclipse的流程编辑器插件&#xff0c;每次编辑流程需要打开eclipse进行编辑&#xff0c;然后再导入到项目里面&#xff0c;不是特…...

【NodeJS】Express写接口的整体流程

前提条件 开发 Node.js&#xff0c;首先就必须要安装 Node.js。推荐使用 nvm&#xff0c;它可以随意切换 node 版本。下载 nvm&#xff0c;具体可以看本人另一篇文章&#xff1a;nvm的作用、下载、使用、以及Mac使用时遇到commond not found:nvm如何解决。 nvm官方&#xff1…...

Oracle 锁表的解决方法及避免锁表问题的最佳实践

背景介绍 在 Oracle 数据库中&#xff0c;锁表或锁超时相信大家都不陌生&#xff0c;是一个常见的问题&#xff0c;尤其是在执行 DML&#xff08;数据操作语言&#xff09;语句时。当一个会话对表或行进行锁定但未提交事务时&#xff0c;其他会话可能会因为等待锁资源而出现超…...

关于 vue+element 日期时间选择器 限制只能选当天以及30天之前的日期

业务需求&#xff0c;需要实现选择当天以及30天之前的日期&#xff0c;于是我想到的是利用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 文件时&#xff0c;开启模块支持 GO111MODULEoff 无模块支持&#xff0c;go会从GOPATH 和 vendor 文件夹寻找包…...

如何在 Ubuntu 22.04 上安装 Metabase 数据可视化分析工具

简介 Metabase 提供了一个简单易用的界面&#xff0c;让你能够轻松地对数据进行探索和分析。通过本文的指导&#xff0c;你将能够在 Ubuntu 22.04 系统上安装并配置 Metabase&#xff0c;并通过 Nginx 进行反向代理以提高安全性。本教程假设你已经拥有了一个非 root 用户&…...

MySQL 用户与权限管理

MySQL 是一种广泛使用的关系型数据库管理系统,支持多用户访问和权限控制。在多用户环境下,数据库安全至关重要,而用户和权限管理是数据库管理中最基础也是最重要的一部分。通过合理地创建和管理用户、分配和管理权限、使用角色权限,可以有效地保护数据库,确保数据的安全性…...

【Web前端】如何构建简单HTML表单?

HTML 表单是 Web 开发中非常重要的组成部分。它们是与用户交互的主要方式&#xff0c;能够收集用户输入的数据。表单的灵活性使它们成为 HTML 中最复杂的结构之一&#xff0c;但若使用正确的结构和元素&#xff0c;可以确保其可用性和无障碍性。 表单的基本结构 HTML 表单使用…...

Spring Boot 3 集成 Spring Security(3)数据管理

文章目录 准备工作新建项目引入MyBatis-Plus依赖创建表结构生成基础代码 逻辑实现application.yml配置SecurityConfig 配置自定义 UserDetailsService创建测试 启动测试 在前面的文章中我们介绍了 《Spring Boot 3 集成 Spring Security&#xff08;1&#xff09;认证》和 《…...

书生大模型实战营第四期-入门岛-4. maas课程任务

书生大模型实战营第四期-入门岛-4. maas课程任务 任务一、模型下载 任务内容 使用Hugging Face平台、魔搭社区平台&#xff08;可选&#xff09;和魔乐社区平台&#xff08;可选&#xff09;下载文档中提到的模型&#xff08;至少需要下载config.json文件、model.safetensor…...

Spring ApplicationListener监听

【JavaWeb】Spring ApplicationListener-CSDN博客 ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现&#xff0c;内部实现原理是观察者设计模式&#xff0c;设计初衷也是为了系统业务逻辑之间的解耦&#xff0c;提高可扩展性以及可维护性。事件发布…...

K8s调度器扩展(scheduler)

1.K8S调度器 筛选插件扩展 为了熟悉 K8S调度器扩展步骤&#xff0c;目前只修改 筛选 插件 准备环境&#xff08;到GitHub直接下载压缩包&#xff0c;然后解压&#xff0c;解压要在Linux系统下完成&#xff09; 2. 编写调度器插件代码 在 Kubernetes 源代码目录下编写调度插件…...

IntelliJ IDEA 中,自动导包功能

在 IntelliJ IDEA 中&#xff0c;自动导包功能可以极大地提高开发效率&#xff0c;减少手动导入包所带来的繁琐和错误。以下是如何在 IntelliJ IDEA 中设置和使用自动导包功能的详细步骤&#xff1a; 一、设置自动导包 打开 IntelliJ IDEA&#xff1a; 启动 IntelliJ IDEA 并打…...

Spring事务笔记

目录 1.Spring 编程式事务 2.Transactional 3.事务隔离级别 4.Spring 事务传播机制 什么是事务? 事务是⼀组操作的集合, 是⼀个不可分割的操作. 事务会把所有的操作作为⼀个整体, ⼀起向数据库提交或者是撤销操作请求. 所以这组操作要么同时成 功, 要么同时失败 1.Spri…...

SQLite 管理工具 SQLiteStudio 3.4.5 发布

SQLiteStudio 3.4.5 版本现已发布&#xff0c;它带来了大量的 bug 修复&#xff0c;并增加了一些小功能。SQLiteStudio 是一个跨平台的 SQLite 数据库的管理工具。 具体更新内容包括&#xff1a; 现在可以使用 Collations Editor 窗口在数据库中注册 Extension-based collatio…...

QT 实现组织树状图

1.实现效果 在Qt中使用QGraphicsItem和QGraphicsScene实现树状图,你需要创建自定义的QGraphicsItem类来表示树的节点,并管理它们的位置和连接,以下是实现效果图。 2.实现思路 可以看见,上图所示,我们需要自定义连线类和节点类。 每个节点类Node,需要绘制矩形框体文字…...

go-学习

文章目录 简介标识符字符串的拼接&#xff0c;关键字数据类型声明变量常量算术运算符关系运算符逻辑运算符位运算赋值运算符其他运算符 简介 Go 语言的基础组成有以下几个部分&#xff1a; 1.包声明 2.引入包 3.函数 4.变量 5.语句 & 表达式 6.注释 package main import &q…...

【面试分享】主流编程语言的内存回收机制及其优缺点

以下是几种主流编程语言的内存回收机制及其优缺点&#xff1a; 一、Java 内存回收机制&#xff1a; Java 使用自动内存管理&#xff0c;主要通过垃圾回收器&#xff08;Garbage Collector&#xff0c;GC&#xff09;来回收不再被使用的对象所占用的内存。Java 的垃圾回收器会定…...

STM32-- 串口发送数据

while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);&#xff1f;&#xff1f; 答&#xff1a; 这行代码&#xff1a; while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) RESET);的作用是等待串口 USART2 的发送数据寄存器&#xff08;TXE&#xff0c;Transmit Dat…...

数据结构 (13)串的应用举例

前言 数据结构中的串&#xff08;String&#xff09;&#xff0c;也称为字符串&#xff0c;是一种常见且重要的数据结构&#xff0c;在计算机科学中被广泛应用于各种场景。 一、文本处理 文本编辑器&#xff1a;在文本编辑器中&#xff0c;字符串被用来表示和存储用户输入的文本…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...

【免杀】C2免杀技术(十五)shellcode混淆uuid/ipv6/mac

针对 shellcode 混淆(Shellcode Obfuscation) 的实战手段还有很多,如下表所示: 类型举例目的编码 / 加密XOR、AES、RC4、Base64、Poly1305、UUID、IP/MAC改变字节特征,避开静态签名或 YARA结构伪装PE Stub、GIF/PNG 嵌入、RTF OLE、UUID、IP/MAC看起来像合法文件/数据,弱…...

论文笔记:Large Language Models for Next Point-of-Interest Recommendation

SIGIR 2024 1 intro 传统的基于数值的POI推荐方法在处理上下文信息时存在两个主要限制 需要将异构的LBSN数据转换为数字&#xff0c;这可能导致上下文信息的固有含义丢失仅依赖于统计和人为设计来理解上下文信息&#xff0c;缺乏对上下文信息提供的语义概念的理解 ——>使用…...

链结构与工作量证明7️⃣:用 Go 实现比特币的核心机制

链结构与工作量证明:用 Go 实现比特币的核心机制 如果你用 Go 写过区块、算过哈希,也大致理解了非对称加密、数据序列化这些“硬核知识”,那么恭喜你,现在我们终于可以把这些拼成一条完整的“区块链”。 不过别急,这一节我们重点搞懂两件事: 区块之间是怎么连接成“链”…...