环境运行时Jar版本控制

环境运行时Jar版本控制

前景

为了避免基于低代码定义产生的元数据错乱。因此产生了运行时Jar版本检查功能。

现象

如果当前运行时依赖的Ja版本低于已安装版本,启动时会有如下类似信息提示:
环境运行时Jar版本控制

解决

  1. 按照提示升级依赖Jar版本
  2. 通过启动参数 -PgoBack=true 强制覆盖安装当前运行时版本
    • java -jar 方式
      java -jar xxx.jar -PgoBack=true [其他参数]
    • mvn spring-boot run 方式
      mvn clean compile spring-boot:run -Dspring-boot.run.arguments="-PgoBack=true [其他参数]"

Oinone社区 作者:yakir原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/20619.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
yakir's avataryakir数式员工
Previous 2025年3月6日 pm3:48
Next 2025年3月11日 pm6:47

相关推荐

  • EIP开放接口使用MD5验签发起请求(v5.x)

    验签工具类 PS:该验签方法仅在pamirs-core的5.0.16版本以上可正常使用 public class EipSignUtils { public static final String SIGN_METHOD_MD5 = "md5"; private static final String SIGN_METHOD_HMAC = "hmac"; private static final String SECRET_KEY_ALGORITHM = "HmacMD5"; private static final String MESSAGE_DIGEST_MD5 = "MD5"; public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException { // 第一步:检查参数是否已经排序 String[] keys = params.keySet().toArray(new String[0]); Arrays.sort(keys); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); if (SIGN_METHOD_MD5.equals(signMethod)) { query.append(secret); } for (String key : keys) { String value = params.get(key); if (StringUtils.isNoneBlank(key, value)) { query.append(key).append(value); } } // 第三步:使用MD5/HMAC加密 byte[] bytes; if (SIGN_METHOD_HMAC.equals(signMethod)) { bytes = encryptHMAC(query.toString(), secret); } else { query.append(secret); bytes = encryptMD5(query.toString()); } // 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用) return byte2hex(bytes); } private static byte[] encryptHMAC(String data, String secret) throws IOException { byte[] bytes; try { SecretKey secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), SECRET_KEY_ALGORITHM); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); } catch (GeneralSecurityException e) { throw new IOException(e.toString(), e); } return bytes; } private static byte[] encryptMD5(String data) throws IOException { return encryptMD5(data.getBytes(StandardCharsets.UTF_8)); } private static byte[] encryptMD5(byte[] data) throws IOException { try { MessageDigest md = MessageDigest.getInstance(MESSAGE_DIGEST_MD5); return md.digest(data); } catch (NoSuchAlgorithmException e)…

    2024年6月29日
    2.1K00
  • 函数之触发与定时配置和示例

    异步任务总体介绍 函数的触发和定时在很多场景中会用到,也是一个oinone的基础能力。比如我们的流程产品中在定义流程触发时就会让用户选择模型触发还是时间触发,就是用到了函数的触发与定时能力。 触发任务TriggerTaskAction 触发任务的创建,使用sql-record模块监听mysql的binlog事件,通过rocketmq发送变更数据消息,收到MQ消息后,创建TriggerAutoTask。 触发任务的执行,使用TBSchedule拉取触发任务后,执行相应函数。 项目中引入依赖 1、项目的API工程引入依赖pamirs-core-trigger模块 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-api</artifactId> </dependency> 2、DemoModule在模块依赖定义中增加@Module(dependencies={TriggerModule.MODULE_MODULE}) @Component @Module( name = DemoModule.MODULE_NAME, displayName = "oinoneDemo工程", version = "1.0.0", dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, UserModule.MODULE_MODULE, TriggerModule.MODULE_MODULE} ) @Module.module(DemoModule.MODULE_MODULE) @Module.Advanced(selfBuilt = true, application = true) @UxHomepage(PetShopProxy.MODEL_MODEL) public class DemoModule implements PamirsModule { ……其他代码 } 3、项目的boot工程引入依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-trigger-bridge-tbschedule</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-sql-record-core</artifactId> </dependency> yml文件修改(applcation-xxx.yml) a. 修改pamris.event.enabled和pamris.event.schedule.enabled为trueb. pamirs_boot_modules增加启动模块:trigger、sql_record pamirs: record: sql: #改成自己路径 store: /opt/pamirs/logs … event: enabled: true schedule: enabled: true rocket-mq: namesrv-addr: 127.0.0.1:9876 boot: init: true sync: true modules: – base -…… – trigger – sql_record -…… 新建触发任务 新建PetTalentTrigger类,当PetTalent模型的数据记录被新建时触发系统做一些事情 package pro.shushi.pamirs.demo.core.trigger; import pro.shushi.pamirs.demo.api.model.PetTalent; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.trigger.annotation.Trigger; import pro.shushi.pamirs.trigger.enmu.TriggerConditionEnum; @Fun(PetTalent.MODEL_MODEL) @Slf4j public class PetTalentTrigger { @Function @Trigger(displayName = “PetTalent创建时触发”,name = “PetTalent#Trigger#onCreate”,condition = TriggerConditionEnum.ON_CREATE) public PetTalent onCreate(PetTalent data){ log.info(data.getName() + “,被创建”); //可以增加逻辑 return data; } } 定时任务 定时任务是一种非常常见的模式,这里就不介绍概念了,直接进入示例环节 新建PetTalentAutoTask实现ScheduleAction getInterfaceName()需要跟taskAction.setExecuteNamespace定义保持一致,都是函数的命名空间 taskAction.setExecuteFun("execute");跟执行函数名“execute”一致 TaskType需配置为CYCLE_SCHEDULE_NO_TRANSACTION_TASK,把定时任务的schedule线程分开,要不然有一个时间长的任务会导致普通异步或触发任务全部延时。 package pro.shushi.pamirs.demo.core.task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import pro.shushi.pamirs.core.common.enmu.TimeUnitEnum; import pro.shushi.pamirs.demo.api.model.PetTalent; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.domain.fun.FunctionDefinition; import pro.shushi.pamirs.middleware.schedule.api.ScheduleAction; import pro.shushi.pamirs.middleware.schedule.common.Result; import pro.shushi.pamirs.middleware.schedule.domain.ScheduleItem; import pro.shushi.pamirs.middleware.schedule.eunmeration.TaskType; import pro.shushi.pamirs.trigger.enmu.TriggerTimeAnchorEnum; import pro.shushi.pamirs.trigger.model.ScheduleTaskAction; import pro.shushi.pamirs.trigger.service.ScheduleTaskActionService; @Slf4j @Component @Fun(PetTalent.MODEL_MODEL) public class PetTalentAutoTask implements…

    2024年5月25日
    1.8K00
  • 模型字段之序列化方式

    本文核心是带大家全面了解oinone的序列方式,包括支持的序列化类型、注意点、如果新增客户化序列化方式以及字段默认值的反序列化。 字段序列化方式说明 序列化方式 说明 备注 JSON JSON序列化 主要用于模型相关类型字段的序列化,是@Field.serialize默认选项 DOT 点拼接集合元素 COMMA 逗号拼接集合元素 BIT 按位与,2次幂数求和 非@Field.serialize可选项列表,用于二进制枚举序列化不需要配置,由oinone自动推断 字段序列化方式举例 1、给模型PetItemDetail 增加两个字段:petItemDetails类型为List 和 tags类型为List,并设置为不同的序列化方式,petItemDetails为JSON(缺省就是JSON,可不配),tags为COMMA。2、同时设置 @Field.Advanced(columnDefinition = "varchar(1024)"),防止序列化后存储过长。 @Model.model(PetItem.MODEL_MODEL) @Model(displayName = "宠物商品",summary="宠物商品",labelFields = {"itemName"}) public class PetItem extends AbstractDemoCodeModel{ public static final String MODEL_MODEL="demo.PetItem"; @Field(displayName = "品种") @Field.many2one @Field.Relation(relationFields = {"typeId"},referenceFields = {"id"}) private PetType type; @Field(displayName = "品种类型",invisible = true) private Long typeId; @Field(displayName = "详情", serialize = Field.serialize.JSON, store = NullableBoolEnum.TRUE) @Field.Advanced(columnDefinition = "varchar(1024)") private List<PetItemDetail> petItemDetails; @Field(displayName = "商品标签",serialize = Field.serialize.COMMA,store = NullableBoolEnum.TRUE,multi = true) @Field.Advanced(columnDefinition = "varchar(1024)") private List<String> tags; } 字段序列化注意点 必须使用Field#store属性将字段存储设置为NullableBoolEnum.TRUE。 使用Field#serialize属性指定序列化方式,默认为JSON。 如把PetItemDetail设置为存储模型,须在PetItem的petItemDetails字段上使用Field.Relation#store属性将关联关系存储设置为false。不然会同时存储petItemDetails字段和对应的PetItemDetail表记录 注册自己的序列化器 注册自己的序列化器(实现pro.shushi.pamirs.meta.api.core.orm.serialize.Serializer接口), 如oinone的DOT的序列化方式,用type()方法返回值做匹配,serialize和deserialize分别对应序列化和反序列化方法。 package pro.shushi.pamirs.framework.compute.serialize; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.api.core.orm.serialize.Serializer; import pro.shushi.pamirs.meta.common.constants.CharacterConstants; import pro.shushi.pamirs.meta.enmu.SerializeEnum; import pro.shushi.pamirs.meta.util.TypeUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 点表达式序列生成处理器实现 * @author shushi@shushi.pro * @version 1.0.0 */ @SuppressWarnings("rawtypes") @Slf4j @Component public class DotSerializeProcessor implements Serializer<Object, String> { @Override public String serialize(String ltype, Object value) { if (null == value) { return null; } if (List.class.isAssignableFrom(value.getClass())) { return StringUtils.join((List) value, CharacterConstants.SEPARATOR_DOT); } else { return StringUtils.join(Collections.singletonList(value), CharacterConstants.SEPARATOR_DOT); } } @SuppressWarnings("unchecked") @Override public Object deserialize(String ltype, String ltypeT, String value,…

    2024年5月24日
    2.4K00
  • GQL GET 请求生成图片文件流 — 技术实现方案

    GQL GET 请求生成图片文件流 — 技术实现方案 基于 Oinone/Pamirs GQL GET 文件流机制,参考 FileAction#downloadFormData(查询型)与 ExcelExportTaskAction#createExportTask(同步写流),实现「按业务 ID 动态生成图片并输出文件流」的通用指南。 1. 背景与目标 1.1 需求 在业务场景中,需要根据业务 ID(如订单 ID、模板 ID、单据 ID)在后端动态渲染图片(条码、标签、证书、预览图等),并将结果以文件流形式返回给前端。 1.2 约束 复用 Oinone 既有鉴权、会话、模块路由体系,不新增独立 REST 下载接口。 与 Excel 同步导出保持一致的调用方式:通过 GET 访问 /pamirs/{module}?query=…&variables=…。 前端仅两种消费方式: 页面预览:<img :src="imageUrl" /> 触发下载:window.open(imageUrl, '_blank') 2. 参考实现 2.1 查询型文件流(图片查看应对齐此模式) 图片查看属于只读查询,应使用 query + @Function(type = QUERY),与 CDN 文件下载一致: // @oinone/kunlun-vue-ui-common/…/UploadService.ts const gql = `query{resourceFileFormQuery{downloadFormData(resourceFileForm:{downloadUrl:"${url}"}){filename}}}`; window.open(UrlHelper.appendBasePath(`/pamirs/file?query=${encodeURIComponent(gql)}`), '_blank'); // pamirs-core/pamirs-file2/…/FileAction.java @Function.Advanced(displayName = "前端下载数据", type = FunctionTypeEnum.QUERY) public ResourceFileForm downloadFormData(ResourceFileForm resourceFileForm) { // 直接写 HttpServletResponse 输出流 response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=" + …); IOUtils.copy(inputStream, response.getOutputStream()); return new ResourceFileForm(); } 图片查看用 GQL.query,不用 GQL.mutation。 2.2 同步写流机制(共用) 无论 query 还是 mutation,文件流输出的底层机制相同:在 Function/Action 执行过程中直接写 HttpServletResponse。 2.2.1 HTTP 网关:RequestController GET /pamirs/{moduleName}?query={gql}&variables={json} POST /pamirs/{moduleName} body: { query, variables } GET 与 POST 走同一执行链路: // pamirs-framework/pamirs-gateways-graph-java/…/RequestController.java @RequestMapping(value = "/pamirs/{moduleName}", method = RequestMethod.GET) public DeferredResult<String> pamirsGet( @PathVariable("moduleName") String moduleName, @RequestParam("query") String gql, @RequestParam(value = "variables", required = false) String variables, …) { PamirsClientRequestParam gqlRequest = new PamirsClientRequestParam(); gqlRequest.setQuery(gql); if (!StringUtils.isBlank(variables)) { gqlRequest.setVariables(JsonUtils.parseMap(variables)); } return pamirsPost(moduleName, gqlRequest, request, response); } variables.path 在 RequestHelper.preparePamirsRequestParam 中经 SessionPrepareApi.prepare 注入会话上下文,与前端 getSessionPath() 对应。 2.2.2 Excel 导出对照:ExcelFileServiceImpl#doExportSync Excel 同步导出使用 mutation(createExportTask),因为会创建导出任务记录;图片查看无此副作用,故用 query。 同步导出的关键:劫持 FileClient.upload,将字节直接写入当前…

    2026年7月2日
    40600
  • 灵活敏捷开发,高效交付项目的6个关键

    项目工程管理 项目工程顶层分层 项目分层设计,划分出 CDM层、 标准业务层 、定制业务层; 沉淀领域业务模型至CDM层; 沉底业内通用功能至标准业务层; 客户定制化功能在定制业务层; 项目内部的层级划分 项目包结构管理及规范 pamirs-demo-api constant【常量的包路径】 enums【枚举类的包路径】 model【该领域核⼼模型的包路径】 pmodel【该领域代理模型的包路径】 tmodel【该领域传输模型的包路径】 service【存放该领域的⾮存储模型如:⽤于传输的临时模型】 utils【工具类】 XXModule【该类是Demo模块的定义】 pamirs-demo-core service【接口实现类】 init【模块初始化⼯作的包路径】 manager 【manager是 service的⼀些公共逻辑,不会定义为独⽴的function的类】 pamirs-demo-view(可选) action【模型对外交互的⾏为的包路径】 项目中模块间依赖 禁止出现api模块依赖core模块的情况,api模块只允许依赖api模块; 根据当前项目结构进行模块划分,避免循环依赖; 规划项目模块 项目阶段,代码开发前,业务架构师需充分的理解需求和蓝图,对系统进行业务域, 功能域的划分;例如:对一个电商系统: 提高系统的可维护性:通过将系统拆分为不同的业务域,每个业务域都有清晰的边界和职责,可以独立开发、测试和维护; 提升开发效率:业务域划分可以使开发团队更加专注于自己负责的业务,减少不必要的沟通和协调,提升开发效率; 促进团队合作:通过业务域划分,每个团队可以负责一个或多个业务域,团队成员之间可以有更高效的合作和协同。 支持系统的扩展和演化:业务域划分可以使系统更加灵活和可扩展。当需要新增一个新的业务功能或调整现有的业务逻辑时,只需要修改对应的业务域,而不需要对整个系统进行改动。 项目文档管理 项目文档管理对于项目的实施,项目进度管理,项目后期维护等都是至关重要的。系统详细的产品文档,测试文档,运维文档,开发文档,项目管理文档等。 协同合作:团队成员可以共享和访问项目文档,促进协同合作和信息共享,避免信息孤岛和重复工作。 知识管理:项目中所获得的知识,对项目的成功和后续的知识积累至关重要。通过良好的文档管理,可以确保项目知识的保存和传承,提高组织的知识管理能力。 问题解决:项目文档中记录了项目的需求、决策、问题和解决方案等信息。当出现问题或需要做决策时,可以通过查阅文档来获取相关信息,加快问题解决的速度,并减少错误和重复。 项目追踪:通过文档管理,可以跟踪项目的进展和状态。可以记录项目的里程碑、任务分配、进度更新等信息,帮助团队了解项目的整体情况,及时发现和解决问题。 知识共享:好的文档管理可以促进知识共享和传播。通过将项目文档进行分类、索引和存档,可以使团队成员更容易找到所需的信息,并从中学习和借鉴经验,提高工作效率和质量。 数据库和事务 多表联合查询 减少需要join的操作出现 用多次查询替代 索引相关 核心业务访问DB的Sql 要命中或者覆盖索引,保存核心业务的响应时间; 控制单表的索引数量,注意联合索引 数据一致性:乐观锁控制,unique�等 事务代码示例 事务相关注意点参考【Oinone如何支持构建分布式项目】:https://doc.oinone.top/kai-fa-shi-jian/5572.html

    2024年2月20日
    1.5K00

Leave a Reply

Please Login to Comment