技术精要:数据导出与固化实用指南

数据被认为是企业发展和决策的重要资产。随着业务的不断发展和数据量的不断增加,企业通常需要将数据从不同的源头导出,并将其固化到产品中,以便进行进一步的分析、处理和利用。数据导出与固化的过程涉及到数据的提取、清洗、整合和存储,是确保数据长期有效性和可用性的关键步骤。

了解数据导出与固化的流程和方法对于企业具有重要意义。通过有效的数据导出和固化,企业可以更好地管理和利用数据资源,提升决策的准确性和效率,实现业务的持续发展和创新。本次讨论将重点探讨数据导出与固化的流程和关键步骤,帮助参与者深入了解如何将数据从导出到产品中,为企业数据管理和应用提供有力支持。

1. 数据导出与固化:将数据从导出到产品中的流程

1.1. pom依赖:

<dependency>
 <groupId>pro.shushi.pamirs.metadata.manager</groupId>
 <artifactId>pamirs-metadata-manager</artifactId>
</dependency>

1.2 将第⼆步下载后的⽂件放⼊项⽬中(注意⽂件放置的位置)。放置⼯程的resources

下⾯。例如:
技术精要:数据导出与固化实用指南

1.3 项⽬启动过程中,将⽂件中的数据导⼊(通常放在core模型的init包下

⾯)。⽰例代码:

package pro.shushi.pamirs.sys.setting.enmu;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import 
org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import 
pro.shushi.pamirs.boot.common.api.command.AppLifecycleCom
mand;
import 
pro.shushi.pamirs.boot.common.api.init.LifecycleCompleted
AllInit;
import 
pro.shushi.pamirs.boot.common.extend.MetaDataEditor;
import pro.shushi.pamirs.core.common.InitializationUtil;
import 
pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.dto.meta.Meta;
import 
pro.shushi.pamirs.meta.domain.module.ModuleDefinition;
import 
pro.shushi.pamirs.metadata.manager.core.helper.DesignerIn
stallHelper;
import 
pro.shushi.pamirs.metadata.manager.core.helper.WidgetInst
allHelper;
import java.util.List;
import java.util.Map;
@Slf4j
@Component
public class DemoAppMetaInstall implements 
MetaDataEditor, LifecycleCompletedAllInit {
 @Autowired
 private ApplicationContext applicationContext;
 @Override
 public void edit(AppLifecycleCommand command, 
Map<String, Meta> metaMap) {
 if (!doImport()) {
 return;
 }
 log.info("[设计器业务元数据导⼊]");
 InitializationUtil bizInitializationUtil = 
InitializationUtil.get(metaMap, DemoModule.MODULE_MODULE/
***改成⾃⼰的Module*/, DemoModule.MODULE_NAME/***改成⾃⼰的
Module*/);

DesignerInstallHelper.mateInitialization(bizInitializatio
nUtil, "install/meta.json");
 log.info("[⾃定义组件元数据导⼊]");
// 写法1: 将组件元数据导⼊到⻚⾯设计器. 只有在安装设计器的
服务中执⾏才有效果
 WidgetInstallHelper.mateInitialization(metaMap, 
"install/widget.json");
// 写法2: 与写法1相同效果
 InitializationUtil uiInitializationUtil = 
InitializationUtil.get(metaMap, "ui_designer", 
"uiDesigner");
 if (uiInitializationUtil != null) {

DesignerInstallHelper.mateInitialization(uiInitialization
Util, "install/widget.json");
 }
// 写法3: 业务⼯程和设计器分布式部署,且希望通过业务⼯程导⼊
⾃定义组件元数据. 业务模块需要依赖⻚⾯设计器模块,然后指定业务模块导
⼊

DesignerInstallHelper.mateInitialization(bizInitializatio
nUtil, "install/widget.json");
 }
 @Override
 public void process(AppLifecycleCommand command, 
Map<String, ModuleDefinition> runModuleMap) {
 if (!doImport()) {
 return;
 }
 log.info("[设计器业务数据导⼊]");
// ⽀持远程调⽤,但是执⾏的⽣命周期必须是
LifecycleCompletedAllInit或之后. 本地如果安装了设计器,则没有要
求
 DesignerInstallHelper.bizInitialization("install/
meta.json");
 log.info("[⾃定义组件业务数据导⼊]");
// 当开发环境和导⼊环境的⽂件服务不互通时, 可通过指定js和
css的⽂件压缩包,⾃动上传到导⼊环境,并替换导⼊组件数据中的⽂件url
// WidgetInstallHelper.bizInitialization("install/
widget.json", "install/widget.zip");
 WidgetInstallHelper.bizInitialization("install/
widget.json");
 return;
 }
 private boolean doImport() {
 // ⾃定义导⼊判断. 避免⽤于设计的开发环境执⾏导⼊逻辑
 String[] envs = 
applicationContext.getEnvironment().getActiveProfiles();
 List<String> envList = Lists.newArrayList(envs);
 return CollectionUtils.isNotEmpty(envList) && 
(envList.contains("prod"));
 }
}

2. 设计器数据导出

简介
通过调⽤导出接口,将设计器的设计数据与运动数据打包导出到⽂件中。
提供了download/export两类接⼜。
export
导出到OSS。导出的⽂件会上传到⽂件服务,通过返回的url下载导出⽂件。
请求⽰例:

mutation {
    uiDesignerExportReqMutation {
        export(
            data: { module: "gemini_core", fileName: "meta", moduleBasics: true }
        ) {
            jsonUrl
        }
    }
}

响应⽰例:

{
          "data":  {
                    "uiDesignerExportReqMutation":  {
                              "export":  {
                                        "jsonUrl":  "https://xxx/meta.json"
                              }
                    }
          },
          "errors":  [

          ],
          "extensions":  {

          }
}

download
直接返回导出数据。适⽤于通过浏览器直接下载⽂件。
请求⽰例:

mutation {
    uiDesignerExportReqMutation {
        download(
            data: { module: "gemini_core", fileName: "meta", moduleBasics: true }
        ) {
            jsonUrl
        }
    }
}

如何构造url
protocol :// hostname[:port] / path ?
query=URLEncode(GraphQL)
例:

http://127.0.0.1:8080/pamirs/base?
query=mutation%20%7B%0A%09uiDesignerExportReqMutation%20%
7B%0A%09%09download(%0A%09%09%09data%3A%20%7B%20module%3A
%20%22gemini_core%22%2C%20fileName%3A%20%22meta%22%2C%20m
oduleBasics%3A%20true%20%7D%0A%09%09)%20%7B%0A%09%09%09js
onUrl%0A%09%09%7D%0A%09%7D%0A%7D

在浏览器中访问构造后的url,可直接下载⽂件
接口列表

2.1 模型设计器

指定模块导出

#生成json
query {
    modelMetaDataExporterQuery {
        export(query: { module: "模块编码" }) {
            module
            url
        }
    }
}
#生成json文件下载
query {
    modelMetaDataExporterQuery {
        download(query: { module: "模块编码" }) {
            module
            url
        }
    }
}

module参数:指定导出的模块编码
url返回结果:export⽅式导出的⽂件url

2.2 页⾯设计器-导出页⾯

2.2.1 指定模块导出

#生成json
mutation {
    uiDesignerExportReqMutation {
        export(
            data: { module: "gemini_core", fileName: "meta", moduleBasics: true }
        ) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    uiDesignerExportReqMutation {
        download(
            data: { module: "gemini_core", fileName: "meta", moduleBasics: true }
        ) {
            jsonUrl
        }
    }
}

module参数:模块编码
fileName参数:指定⽣成的json⽂件名称
moduleBasics参数:指定是否只导出模块基础数据,如果为true,只导出内置布局、模
块菜单、菜单关联的动作。 如果为false,还会导出模块内的所有页⾯,以及页⾯关联
的动作元数据、页⾯设计数据 等等。 默认值为false。

2.2.2 指定菜单导出

#生成json
mutation {
    uiDesignerExportReqMutation {
        export(
            data: {
                menu: { name: "uiMenu0000000000048001" }
                fileName: "meta"
                relationViews: true
            }
        ) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    uiDesignerExportReqMutation {
        download(
            data: {
                menu: { name: "uiMenu0000000000048001" }
                fileName: "meta"
                relationViews: true
            }
        ) {
            jsonUrl
        }
    }
}

menu参数:菜单对象,指定菜单的name。只会导出该菜单及其绑定页⾯,不会递归查
询⼦菜单
fileName参数:指定⽣成的json⽂件名称
relationViews参数:指定是否导出关联页⾯,默认为false,只导出菜单关联的页⾯。如
果为true,还会导出该页⾯通过跳转动作关联的⾃定义页⾯。

2.2.3 指定页⾯导出

#生成json
mutation {
    uiDesignerExportReqMutation {
        export(
            data: {
                view: {
                    name: "xx_TABLE_0000000000119001"
                    model: "ui.designer.TestUiDesigner"
                }
                fileName: "meta"
                relationViews: true
            }
        ) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    uiDesignerExportReqMutation {
        download(
            data: {
                view: {
                    name: "xx_TABLE_0000000000119001"
                    model: "ui.designer.TestUiDesigner"
                }
                fileName: "meta"
                relationViews: true
            }
        ) {
            jsonUrl
        }
    }
}

view参数:视图对象,指定视图的name和model
fileName参数:指定⽣成的json⽂件名称
relationViews参数:指定是否导出关联页⾯,默认为false,只导出菜单关联的页⾯。如
果为true,还会导出该页⾯通过跳转动作关联的⾃定义页⾯。

2.3 导出组件

2.3.1 导出全部组件数据

#生成json
mutation {
    uiDesignerExportReqMutation {
        exportWidget(data: { fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    uiDesignerExportReqMutation {
        downloadWidget(data: { fileName: "meta" }) {
            jsonUrl
        }
    }
}

fileName参数:指定⽣成的json⽂件名称
注意:⾃定义组件的元数据归属于页⾯设计器(ui_designer) 因此导⼊元数据的模块
(module)并不是业务模块。组件导⼊建议使⽤
pro.shushi.pamirs.metadata.manager.core.helper.WidgetInstallHelper

2.3.2 导出全部组件⽂件

当开发环境,和导⼊环境的oss不互通时,可通过⼀下⽅法导出⾃定义组件的css和
js⽂件压缩包,在导⼊时⽀持指定zip⽂件上传到oss,并替换导⼊组件数据中的css和js
⽂件路径。

#生成json
mutation {
    uiDesignerExportReqMutation {
        exportWidgetFile(data: { fileName: "widget" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    uiDesignerExportReqMutation {
        downloadWidgetFile(data: { fileName: "widget" }) {
            jsonUrl
        }
    }
}

2.4 流程设计器

2.4.1 指定模块导出

参数说明:

  • module参数:模块编码

接口示例:

#生成json
mutation {
    workflowDesignerExportReqMutation {
        export(data: { module: "resource", fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    workflowDesignerExportReqMutation {
        download(data: { module: "resource", fileName: "meta" }) {
            jsonUrl
        }
    }
}

2.4.2 指定流程编码导出

参数说明:

  • workflowCode参数:流程编码

接口示例:

#生成json
mutation {
    workflowDesignerExportReqMutation {
        export(data: { workflowCode: "WF0000000000132500", fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    workflowDesignerExportReqMutation {
        download(data: { workflowCode: "WF0000000000132500", fileName: "meta" }) {
            jsonUrl
        }
    }
}

2.4 数据可视化

2.4.1全部导出

接口示例:

#生成json
mutation {
    dataDesignerExportReqMutation {
        export(data: { fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    dataDesignerExportReqMutation {
        download(data: { fileName: "meta" }) {
            jsonUrl
        }
    }
}

2.4.2 指定图表导出

参数说明:

  • chartCode参数:图表编码

接口示例:

#生成json
mutation {
    dataDesignerExportReqMutation {
        export(data: { chartCode: "CT00000000002000", fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    dataDesignerExportReqMutation {
        download(data: { chartCode: "CT00000000002000", fileName: "meta" }) {
            jsonUrl
        }
    }
}

2.4.3指定报表导出

参数说明:

  • reportCode参数:报表编码

接口示例:

#生成json
mutation {
    dataDesignerExportReqMutation {
        export(data: { reportCode: "RP00001000", fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    dataDesignerExportReqMutation {
        download(data: { reportCode: "RP00001000", fileName: "meta" }) {
            jsonUrl
        }
    }
}

2.4.4 指定业务⼤屏导出

参数说明:

  • screenCode参数:业务⼤屏

接口示例:

#生成json
mutation {
    dataDesignerExportReqMutation {
        export(data: { screenCode: "DS00001000", fileName: "meta" }) {
            jsonUrl
        }
    }
}
#生成json文件下载
mutation {
    dataDesignerExportReqMutation {
        download(data: { screenCode: "DS00001000", fileName: "meta" }) {
            jsonUrl
        }
    }
}

以上方式通过有效的数据导出和固化,企业可以建立可靠的数据基础设施,支持数据驱动的决策和业务发展。

Oinone社区 作者:数式-海波原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/5785.html

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

(2)
数式-海波的头像数式-海波数式管理员
上一篇 2024年2月26日 pm5:47
下一篇 2024年2月28日 pm3:11

相关推荐

  • 工作流审核撤回/回退/拒绝钩子使用

    目录 1. 流程撤回、拒绝和回退调用自定义函数1.1 工作流【撤销】回调钩子1.2 撤销【回退】回调钩子1.3 工作流【拒绝】回调钩子1.4 回调钩子在业务系统中的调用示例2. 自定义审批方式、自定义审批节点名称 1.流程撤回、拒绝和回退调用自定义函数 1.1工作流【撤销】回调钩子 使用方式:把该方法放置到XXX模型的Action下面,或@Fun(XXX.MODEL_MODEL)触发方式:当流程实例被撤销时调用入口:pro.shushi.pamirs.workflow.app.core.service.impl.WorkflowInstanceServiceImpl#undoInstance /** * XXX为当前流程触发方式为模型触发时对应的触发模型、 * 对应返回不影响流程上下文 * @param data 入参为触发时的业务数据,数据的JsonString * @return */ @Function public XXX recall(String data) { // TODO: 根据实际的业务逻辑把data转换为对象 WorkRecord workRecord = JsonUtils.parseObject(data, new TypeReference<WorkRecord>(){}); // TODO: 增加自定义业务逻辑 return new XXX(); } 1.2撤销【回退】回调钩子 使用方式:把该方法放置到XXX模型的Action下面,或@Fun(XXX.MODEL_MODEL)触发方式:流程待办进行回退操作时调用入口:pro.shushi.pamirs.workflow.app.core.service.operator.ApprovalFallbackOperatorService /** * XXX为当前流程触发方式为模型触发时对应的触发模型 * 对应返回不影响流程上下文 * @param data 入参为触发时的业务数据,数据的JsonString * @return */ @Function public XXX fallBack(String data) { // TODO: 根据实际的业务逻辑把data转换为对象 WorkRecord workRecord = JsonUtils.parseObject(data, new TypeReference<WorkRecord>(){}); // TODO: 增加自定义业务逻辑 return new XXX(); } 1.3工作流【拒绝】回调钩子 使用方式:把该方法放置到XXX模型的Action下面,或@Fun(XXX.MODEL_MODEL)触发方式:流程待办进行拒绝操作时调用入口:pro.shushi.pamirs.workflow.app.core.service.operator.ApprovalFallbackOperatorService /** * XXX为当前流程触发方式为模型触发时对应的触发模型 * 对应返回不影响流程上下文 * @param data 入参为触发时的业务数据,数据的JsonString * @return */ @Function public XXX reject(String data) { // TODO: 根据实际的业务逻辑把data转换为对象 WorkRecord workRecord = JsonUtils.parseObject(data, new TypeReference<WorkRecord>(){}); // TODO: 增加自定义业务逻辑 return new XXX(); } 1.4回调钩子在业务系统中的调用示例 @Function(summary = "发起的流程撤销时会自动调用此方法") @Function.Advanced(displayName = "撤销流程") public PurchaseProjectProxy recall(String data) { Object tempObj = BeanDefinitionUtils.findFirst(ClientDataConverter.class).out(PurchaseProjectProxy.MODEL_MODEL, JsonUtils.parseMap(data)); PurchaseProjectProxy proxy = BeanDefinitionUtils.getBean(ClientDataConverter.class) .<PurchaseProjectProxy>in(new ModelComputeContext(), PurchaseProjectProxy.MODEL_MODEL, tempObj); PurchaseProject purchaseProject = service.recall(ArgUtils.convert(PurchaseProjectProxy.MODEL_MODEL, PurchaseProject.MODEL_MODEL, proxy)); return ArgUtils.convert(PurchaseProject.MODEL_MODEL, PurchaseProjectProxy.MODEL_MODEL, purchaseProject); } 2.自定义审批方式、自定义审批节点名称 【注意】 流程自定义函数需指定:category = FunctionCategoryEnum.CUSTOM_DESIGNER @Model.model(审批模型.MODEL_MODEL) @Component public class 审批模型Action { /** * 自定义审批方式 * @param json json为业务数据,可用JsonUtils转换 * @return 返回参数: * COUNTERSIGN_ONEAGREE_ONEREJUST 或签(一名审批人同意或拒绝即可) * COUNTERSIGN_ALLAGREE_ONEREJUST 会签(需所有审批人同意才为同意,一名审批人拒绝即为拒绝)…

    2023年11月15日
    88300
  • DsHint(指定数据源)和BatchSizeHint(指定批次数量)

    概述和使用场景 DsHintApi ,强制指定数据源, BatchSizeHintApi ,强制指定查询批量数量 API定义 DsHintApi public static DsHintApi model(String model/**模型编码*/) { // 具体实现 } public DsHintApi(Object dsKey/***数据源名称*/) { // 具体实现 } BatchSizeHintApi public static BatchSizeHintApi use(Integer batchSize) { // 具体实现 } 使用示例 1、【注意】代码中使用 try-with-resources语法; 否则可能会出现数据源错乱 2、DsHintApi使用示例包裹在try里面的所有查询都会强制使用指定的数据源 // 使用方式1: try (DsHintApi dsHintApi = DsHintApi.model(PetItem.MODEL_MODEL)) { List<PetItem> items = demoItemDAO.customSqlDemoItem(); PetShopProxy data2 = data.queryById(); data2.fieldQuery(PetShopProxy::getPetTalents); } // 使用方式2: try (DsHintApi dsHintApi = DsHintApi.use("数据源名称")) { List<PetItem> items = demoItemDAO.customSqlDemoItem(); PetShopProxy data2 = data.queryById(); data2.fieldQuery(PetShopProxy::getPetTalents); } 3、BatchSizeHintApi使用示例包裹在try里面的所有查询都会按照指定的batchSize进行查询 // 查询指定每次查询500跳 try (BatchSizeHintApi batchSizeHintApi = BatchSizeHintApi.use(500)) { PetShopProxy data2 = data.queryById(); data2.fieldQuery(PetShopProxy::getPetTalents); } // 查询指定不分页(batchSize=-1)查询。 请注意,你必须在明确不需要分页查询的情况下使用;如果数据量超大不分页可能会卡死。默认不指定分页数的情况下下平台会进行分页查询 try (BatchSizeHintApi batchSizeHintApi = BatchSizeHintApi.use(-1)) { PetShopProxy data2 = data.queryById(); data2.fieldQuery(PetShopProxy::getPetTalents); }

    2024年5月18日
    97900
  • Dubbo配置详解

    概述 Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。 Oinone平台默认使用dubbo-v2.7.22版本,本文以该版本为例进行描述。 基本概念 Dubbo在注册provider/consumer时使用Netty作为RPC调用的核心服务,其具备客户端/服务端(C/S)的基本特性。即:provider作为服务端,consumer作为客户端。 客户端通过服务中心发现有服务可被调用时,将通过服务中心提供的服务端调用信息,连接服务端并发起请求,从而实现远程调用。 服务注册(绑定Host/Port) JAVA程序启动时,需要将provider的信息注册到服务中心,并在当前环境为Netty服务开启Host/Port监听,以实现服务注册功能。 在下文中,我们通过绑定Host/Port表示Netty服务的访问地址,通过注册Host/Port表示客户端的访问地址。 使用yaml配置绑定Host/Port PS:该配置可在多种环境中通用,改变部署方式无需修改此配置。 dubbo: protocol: name: dubbo # host: 0.0.0.0 port: -1 假设当前环境的可用IP为192.168.1.100 以上配置将使得Netty服务默认绑定在0.0.0.0:20880地址,服务注册地址为192.168.1.100:20880 客户端将通过192.168.1.100:20880调用服务端服务 若发生20880端口占用,则自动向后查找可用端口。如20881、20882等等 若当前可用端口为20881,则以上配置将使得Netty服务默认绑定在0.0.0.0:20881地址,服务注册地址为192.168.1.100:20881 使用环境变量配置注册Host/Port 当服务端被放置在容器环境中时,由于容器环境的特殊性,其内部的网络配置相对于宿主机而言是独立的。因此为保证客户端可以正常调用服务端,还需在容器中配置环境变量,以确保客户端可以通过指定的注册Host/Port进行访问。 以下示例为体现无法使用20880端口的情况,将宿主机可访问端口从20880改为20881。 DUBBO_IP_TO_REGISTRY=192.168.1.100 DUBBO_PORT_TO_REGISTRY=20881 假设当前宿主机环境的可用IP为192.168.1.100 以上配置将使得Netty服务默认绑定在0.0.0.0:20881地址,服务注册地址为192.168.1.100:20881 客户端将通过192.168.1.100:20881调用服务端服务 使用docker/docker-compose启动 需添加端口映射,将20881端口映射至宿主机20881端口。(此处容器内的端口发生变化,若需要了解具体原因,可参考题外话章节) docker-run IP=192.168.1.100 docker run -d –name designer-allinone-full \ -e DUBBO_IP_TO_REGISTRY=$IP \ -e DUBBO_PORT_TO_REGISTRY=20881 \ -p 20881:20881 \ docker-compose services: backend: container_name: designer-backend image: harbor.oinone.top/oinone/designer-backend-v5.0 restart: always environment: DUBBO_IP_TO_REGISTRY: 192.168.1.100 DUBBO_PORT_TO_REGISTRY: 20881 ports: – 20881:20881 # dubbo端口 使用kubernetes启动 工作负载(Deployment) kind: Deployment apiVersion: apps/v1 spec: replicas: 1 template: spec: containers: – name: designer-backend image: harbor.oinone.top/oinone/designer-backend-v5.0 ports: – name: dubbo containerPort: 20881 protocol: TCP env: – name: DUBBO_IP_TO_REGISTRY value: "192.168.1.100" – name: DUBBO_PORT_TO_REGISTRY value: "20881" 服务(Services) kind: Service apiVersion: v1 spec: type: NodePort ports: – name: dubbo protocol: TCP port: 20881 targetPort: dubbo nodePort: 20881 PS:此处的targetPort为对应Deployment#spec. template.spec.containers.ports.name配置的端口名称。若未配置,可使用20881直接指定对应容器的端口号。 使用kubernetes其他暴露服务方式 在Kubernetes中部署服务,有多种配置方式均可用暴露服务。上述配置仅用于通过Service/NodePort将20881端口暴露至宿主机,其他服务可用通过任意Kubernetes节点IP进行调用。 若其他服务也在Kubernetes中进行部署,则可以通过Service/Service方式进行调用。将DUBBO_IP_TO_REGISTRY配置为${serviceName}.${namespace}即可。 若其他服务无法直接访问Kubernetes的master服务,则可以通过Ingress/Service方式进行调用。将DUBBO_IP_TO_REGISTRY配置为Ingress可解析域名即可。 Dubbo调用链路图解 PS: Consumer的绑定Host/Port是其作为Provider使用的,下面所有图解仅演示单向的调用链路。 名词解释 Provider: 服务提供者(JVM) Physical Machine Provider: 服务提供者所在物理机 Provider Container: 服务提供者所在容器 Kubernetes Service: Kubernetes Service资源类型 Consumer: 服务消费者(JVM) Registration Center: 注册中心;可以是zookeeper、nacos等。 bind: 服务绑定Host/Port到指定ip:port。 registry: 服务注册;注册Host/Port到注册中心的信息。 discovery: 服务发现;注册Host/Port到消费者的信息。 invoke: 服务调用;消费者通过注册中心提供的提供者信息向提供者发起服务调用。 forward: 网络转发;通常在容器环境需要进行必要的网络转发,以使得服务调用可以到达服务提供者。 物理机/物理机调用链路 “` mermaidsequenceDiagram participant p as Provider<br>(bind 0.0.0.0:20880)participant m as Physical Machine Provider<br>(bind 192.168.1.100:20881)participant…

    2024年8月10日
    97000
  • 引入搜索(增强模型Channel)常见问题解决办法

    总体描述 引入Oinone的搜索(即Channel模块)后,因错误的配置、缺少配置或者少引入一些Jar包,会出现一些报错。 问题1:启动报类JCTree找不到 具体现象 启动过程可能会出现报错:java.lang.NoClassDefFoundError: com/sun/tools/javac/tree/JCTree$JCExpression 产生原因 引入Channel模块后,启动过程中会扫描Class包找寻Enhance的注解,Pamirs底层有使用到jdk的tools中的类, com/sun/tools/javac/tree/JCTree$JCExpression 特定版本的jdk可能会缺少tools.jar导致启动失败 具体报错 at org.springframework.boot.loader.Launcher.launch(Launcher.java:107) [pamirs-venus-boot.jar:na] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [pamirs-venus-boot.jar:na] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) [pamirs-venus-boot.jar:na] Caused by: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: com/sun/tools/javac/tree/JCTree$JCExpression at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357) ~[na:1.8.0_381] at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908) ~[na:1.8.0_381] at pro.shushi.pamirs.boot.common.initial.PamirsBootMainInitial.init(PamirsBootMainInitial.java:66) ~[pamirs-boot-api-4.6.10.jar!/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_381] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_381] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_381] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_381] at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:305) ~[spring-context-5.2.12.RELEASE.jar!/:5.2.12.RELEASE] … 20 common frames omitted Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javac/tree/JCTree$JCExpression at java.lang.Class.forName0(Native Method) ~[na:1.8.0_381] at java.lang.Class.forName(Class.java:264) ~[na:1.8.0_381] at pro.shushi.pamirs.meta.util.ClassUtils.getClasses(ClassUtils.java:157) ~[pamirs-meta-model-4.6.8.jar!/:na] at pro.shushi.pamirs.meta.util.ClassUtils.getClassesByPacks(ClassUtils.java:73) ~[pamirs-meta-model-4.6.8.jar!/:na] at pro.shushi.pamirs.channel.core.manager.EnhanceModelScanner.enhanceModel(EnhanceModelScanner.java:51) ~[pamirs-channel-core-4.6.15.jar!/:na] at pro.shushi.pamirs.channel.core.init.ChannelSystemBootAfterInit.init(ChannelSystemBootAfterInit.java:31) 解决办法 方式一【推荐】、配置channel的扫描路径 pamirs: channel: packages: – com.pamirs.ic 方式二、使用Oracle版本的jdk,确保jdk的lib目录,tools.jar有com/sun/tools/javac/tree/JCTree对应的类 问题2:启动报类JsonProvider找不到 具体报错 如果启动报错信息如下: Caused by: java.lang.NoClassDefFoundError: jakarta/json/spi/JsonProvider at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_181] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_181] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_181] at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_181] 产生原因 项目中只引入了pamirs-channel-core,但未引入elasticsearch相关的包 解决办法 <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>8.4.1</version> </dependency> <dependency> <groupId>jakarta.json</groupId> <artifactId>jakarta.json-api</artifactId> <version>2.1.1</version> </dependency> 其他参考: Oinone引入搜索引擎步骤:https://doc.oinone.top/backend/7235.html

    2024年5月17日
    83200
  • 如何通过自定义支持excel导出的动态表头

    介绍 本文需要阅读过前置文档如何自定义Excel导出功能,动态表头的功能在前置文档的基础上做的进一步扩展,本文未提到的部分都参考这个前置文档。 在日常的业务开发中,我们在导出的场景会遇到需要设置动态表头的场景,比如统计商品在最近1个月的销量,固定表头列为商品的名称等基础信息,动态表头列为最近一个月的日期,在导出的时候设置每个日期的销量,本文将通过此业务场景提供示例代码。 1.自定义导出任务模型 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.file.api.model.ExcelExportTask; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(DemoItemDynamicExcelExportTask.MODEL_MODEL) @Model(displayName = "商品-Excel动态表头导出任务") public class DemoItemDynamicExcelExportTask extends ExcelExportTask { public static final String MODEL_MODEL = "demo.DemoItemDynamicExcelExportTask"; } 2.自定义导出任务处理数据的扩展点 package pro.shushi.pamirs.demo.core.excel.exportdemo.extPoint; import org.springframework.stereotype.Component; import pro.shushi.pamirs.core.common.FetchUtil; import pro.shushi.pamirs.core.common.cache.MemoryIterableSearchCache; import pro.shushi.pamirs.demo.api.model.DemoItem; import pro.shushi.pamirs.file.api.config.FileConstant; import pro.shushi.pamirs.file.api.context.ExcelDefinitionContext; import pro.shushi.pamirs.file.api.enmu.ExcelTemplateTypeEnum; import pro.shushi.pamirs.file.api.entity.EasyExcelCellDefinition; import pro.shushi.pamirs.file.api.extpoint.impl.ExcelExportSameQueryPageTemplate; import pro.shushi.pamirs.file.api.model.ExcelExportTask; import pro.shushi.pamirs.file.api.model.ExcelWorkbookDefinition; import pro.shushi.pamirs.file.api.util.ExcelFixedHeadHelper; import pro.shushi.pamirs.file.api.util.ExcelHelper; import pro.shushi.pamirs.file.api.util.ExcelTemplateInit; import pro.shushi.pamirs.framework.common.entry.TreeNode; import pro.shushi.pamirs.meta.annotation.ExtPoint; import pro.shushi.pamirs.meta.api.CommonApiFactory; import pro.shushi.pamirs.meta.api.core.orm.ReadApi; import pro.shushi.pamirs.meta.api.core.orm.systems.relation.RelationReadApi; import pro.shushi.pamirs.meta.api.dto.config.ModelConfig; import pro.shushi.pamirs.meta.api.dto.config.ModelFieldConfig; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.meta.enmu.TtypeEnum; import pro.shushi.pamirs.meta.util.FieldUtils; import java.util.*; @Component public class DemoItemDynamicExportExtPoint extends ExcelExportSameQueryPageTemplate<DemoItem> implements ExcelTemplateInit { public static final String TEMPLATE_NAME ="商品动态导出"; @Override public List<ExcelWorkbookDefinition> generator() { ExcelFixedHeadHelper excelFixedHeadHelper = ExcelHelper.fixedHeader(DemoItem.MODEL_MODEL,TEMPLATE_NAME) .createBlock(TEMPLATE_NAME, DemoItem.MODEL_MODEL) .setType(ExcelTemplateTypeEnum.EXPORT); return Collections.singletonList(excelFixedHeadHelper.build()); } public static void buildHeader(ExcelFixedHeadHelper excelFixedHeadHelper) { excelFixedHeadHelper.addColumn("name","名称") .addColumn("cateName","类目") .addColumn("searchFrom","搜索来源") .addColumn("description","描述") .addColumn("itemPrice","单价") .addColumn("inventoryQuantity","库存"); } @Override @ExtPoint.Implement(expression = "context.model == \"" + DemoItem.MODEL_MODEL+"\" && context.name == \"" +TEMPLATE_NAME+"\"" ) public List<Object> fetchExportData(ExcelExportTask exportTask, ExcelDefinitionContext context) { List<Object> result = super.fetchExportData(exportTask,context); Object block = result.get(0); if (block instanceof ArrayList) { ((List<Object>) block).forEach(o -> { if (o instanceof DemoItem) { DemoItem item = (DemoItem) o; // TODO 设置动态表头部分字段的值 item.get_d().put("2024-09-10", "1111"); item.get_d().put("2024-09-11", "2222"); }…

    2024年9月11日
    1.1K00

Leave a Reply

登录后才能评论