Oinone如何支持构建分布式项目

分布式调用下的[强制]约束

1、[强制]分布式调用情况下base库和redis需共用;
2、[强制]如果环境有设计器,设计器的base库和redis保持一致也需与项目中的保持一致;
3、[强制]相同base库下,不同应用的相同模块的数据源需保持一致;
4、[强制]项目中需引入分布式缓存包。参考下文的分布式包依赖

分布式支持

1、分布式包依赖

1) 父pom的依赖管理中先加入pamirs-distribution的依赖

<dependency>
    <groupId>pro.shushi.pamirs</groupId>
    <artifactId>pamirs-distribution</artifactId>
    <version>${pamirs.distribution.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

2) 启动的boot工程中增加pamirs-distribution相关包

<!-- 分布式服务发布 -->
<dependency>
    <groupId>pro.shushi.pamirs.distribution</groupId>
    <artifactId>pamirs-distribution-faas</artifactId>
</dependency>
<!-- 分布式元数据缓存 -->
<dependency>
    <groupId>pro.shushi.pamirs.distribution</groupId>
    <artifactId>pamirs-distribution-session</artifactId>
</dependency>
<dependency>
    <groupId>pro.shushi.pamirs.distribution</groupId>
    <artifactId>pamirs-distribution-gateway</artifactId>
</dependency>

3)启动工程的Application中增加类注解@EnableDubbo

@EnableDubbo
public class XXXStdApplication {

    public static void main(String[] args) throws IOException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // ………………………………
        log.info("XXXX Application loading...");
    }
}

2、修改bootstrap.yml文件

注意序列化方式:serialization: pamirs

以下只是一个示例(zk为注册中心),注册中心支持zk和Nacos;
Nacos作为注册中心参考:https://doc.oinone.top/kai-fa-shi-jian/5835.html

spring:
  profiles:
    active: dev
  application:
    name: pamirs-demo
  cloud:
    service-registry:
      auto-registration:
        enabled: false
pamirs:
  default:
    environment-check: true
    tenant-check: true

---
spring:
  profiles: dev
  cloud:
    service-registry:
      auto-registration:
        enabled: false
    config:
      enabled: false
      uri: http://127.0.0.1:7001
      label: master
      profile: dev
    nacos:
      server-addr: http://127.0.0.1:8848
      discovery:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml
      config:
        enabled: false
        namespace:
        prefix: application
        file-extension: yml
dubbo:
  application:
    name: pamirs-demo
    version: 1.0.0
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: dubbo
    port: -1
    serialization: pamirs
  scan:
    base-packages: pro.shushi
  cloud:
    subscribed-services:
  metadata-report:
    disabled: true

3、模块启动的最⼩集

pamirs:
boot:
 init: true
 sync: true
 modules:
 - base
 - 业务工程的Module

4、业务模型间的依赖关系

  1. 服务调用方(即Client端),在启动yml中modules不安装服务提供方的Module
  2. 服务调用方(即Client端),项目的pom中只依赖服务提供方的API(即模型和API的定义)
  3. 服务调用方(即Client端),项目模块定义(即模型Module定义),dependencies中增加服务提供方的Modeule. 如下面示例代码中的FileModule
    @Module(
        name = DemoModule.MODULE_NAME,
        displayName = "oinoneDemo工程",
        version = "1.0.0",
        dependencies = {ModuleConstants.MODULE_BASE, CommonModule.MODULE_MODULE, 
                FileModule.MODULE_MODULE, SecondModule.MODULE_MODULE/**服务提供方的模块定义*/
        }
    )
  4. 服务调用方(即Client端),启动类的ComponentScan需要配置服务提供方API定义所在的包. 如下面示例中的:pro.shushi.pamirs.second
    @ComponentScan(
        basePackages = {"pro.shushi.pamirs.meta",
                "pro.shushi.pamirs.framework",
                "pro.shushi.pamirs",
                "pro.shushi.pamirs.demo",
                "pro.shushi.pamirs.second" /**服务提供方API定义所在的包*/
        },
        excludeFilters = {
                @ComponentScan.Filter(
                        type = FilterType.ASSIGNABLE_TYPE,
                        value = {RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
                                RedisClusterConfig.class}
                )
        })
    @Slf4j
    @EnableTransactionManagement
    @EnableAsync
    @EnableDubbo
    @MapperScan(value = "pro.shushi.pamirs", annotationClass = Mapper.class)
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, FreeMarkerAutoConfiguration.class})
    public class DemoApplication {

5、模块启动顺序

服务提供方的模块需先启动。原因:模块在启动过程中,会校验依赖模块是否存在。

6、Dubbo日志相关

关闭Dubbo元数据上报

dubbo:  
    metadata-report:
            disabled: true

关闭元数据上报,还有错误日志打印出来的话,可以在log中配置

logging:
      level:
        root: info
        pro.shushi.pamirs.framework.connectors.data.mapper.PamirsMapper: info
        pro.shushi.pamirs.framework.connectors.data.mapper.GenericMapper: info # mybatis sql日志
        RocketmqClient: error
        # Dubbo相关的日志
        org.apache.dubbo.registry.zookeeper.ZookeeperRegistry: error
        org.apache.dubbo.registry.integration.RegistryDirectory: error
        org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl: off
        org.apache.dubbo.metadata.store.zookeeper.ZookeeperMetadataReport: off
        org.apache.dubbo.metadata.store.nacos.NacosMetadataReport: off

更详细的教程参考:https://shushi.yuque.com/yoxz76/oio3/deaa1p

分布式支持-事务相关

1、分布式事务解决方案

完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务,分布式事务就是为了保证不同资源服务器的数据一致性。典型的分布式事务场景:
1、跨库事务, 补充具体场景
2、微服务拆分带来的跨内部服务;
3、微服务拆分带来的跨外部服务;

2、事务策略

采用微服务架构,需考虑分布式事务问题(即平台各子系统之间的数据一致性)。
1)对于单个系统/模型内部, 比如:库存中心、账户中心等,采用强事务的方式。比如:在扣减库存的时候,库存日志和库存数列的变化在一个事务中,保证两个表的数据同时成功或者失败。
强事务管理采用编码式,Oinone事务管理兼容Spring的事务管理方式;
2)为了提高系统的可用性、可扩展性和性能,对于某些关键业务和数据一致性要求特别高的场景,采用强一致性外,其他的场景建议采用最终一致性的方案;
对于分布式事务采用最终数据一致性,借助可靠消息和 Job 等方式来实现。

2.1 基于MQ的事务消息

Oinone如何支持构建分布式项目

采用最终一致性方案,基于MQ的事务消息的方式。
事务消息的逻辑由发送端 Producer进行保证(消费端无需考虑)。基于MQ事务消息的实现步骤:
1)首先,发送一个事务消息,MQ将消息状态标记为Prepared,注意此时这条消息消费者是无法消费到的。
2)接着,执行业务代码逻辑,可能是一个本地数据库事务操作
3)确认发送消息,这个时候,MQ将消息状态标记为可消费,这个时候消费者,才能真正的保证消费到这条数据。

2.2 基于JOB的补偿

定期校对:业务活动的被动方,根据定时策略,向业务活动主动方查询(主动方提供查询接口),恢复丢失的业务消息。

2.3 数据一致性

  • 对RPC超时和重试机制设计的检查,是否会带来重复数据
  • 对数据幂等、去重机制的设计是否有考虑到
  • 对事务、数据(最终)一致性设计是否有考虑到
  • 数据缓存时,当数据发生变化时,是否有相应的机制保证缓存数据的一致性和有效性

Oinone构建分布式项目一些注意点

参考文档:https://doc.oinone.top/kai-fa-shi-jian/6475.html

Oinone社区 作者:shao原创文章,如若转载,请注明出处:https://doc.oinone.top/kai-fa-shi-jian/5572.html

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

(0)
shaoshao
上一篇 2024年2月20日 pm6:37
下一篇 2024年2月20日 pm6:46

相关推荐

  • 【后端】项目开发后端知识要点地图

    大类 明细 文档链接 平台基础 如何开发Action,理解前后端协议 如何开发Action,理解前后端协议 CDN配置及文件操作相关 OSS(CDN)配置和文件系统的一些操作 MINIO无公网访问地址下OSS的配置 MINIO无公网访问地址下OSS的配置 分库分表与自定义分表规则 分库分表与自定义分表规则 Oinone引入搜索引擎(增强模型) Oinone引入搜索引擎(增强模型) 引入搜索/增强模型Channel)常见问题解决办法 引入搜索(增强模型Channel)常见问题解决办法 框架之MessageHub(信息提示) 框架之MessageHub(信息提示) DsHint和BatchSizeHint的使用 DsHint(指定数据源)和BatchSizeHint(查询批次数量) Oinone连接外部数据源方案 Oinone连接外部数据源方案 如何自定义SQL(Mapper)语句 如何自定义SQL(Mapper)语句 IWrapper、QueryWrapper和LambdaQueryWrapper使用 IWrapper、QueryWrapper和LambdaQueryWrapper使用 如何在代码中使用自增ID、手动方式获取CODE 如何在代码中使用自增ID、手动方式获取CODE 函数之触发与定时配置和示例 函数之触发与定时配置和示例 函数之异步执行 函数之异步执行 查询时自定义排序字段和排序规则 查询时自定义排序字段和排序规则 非存储字段搜索 非存储字段搜索,适应灵活的搜索场景 枚举/二进制枚举/多值枚举 如何使用位运算的数据字典 全局首页及应用首页配置方法(homepage) 全局首页及应用首页配置方法(homepage) 缓存连接由Jedis切换为Lettuce 缓存连接由Jedis切换为Lettuce GraphQL请求:后端接口实现逻辑解析 GraphQL请求:后端接口实现逻辑解析 Nacos支持 Nacos作为注册中心 Oinone项目引入Nacos作为注册中心 Nacos作为配置中心 Oinone项目引入Nacos作为配置中心 Nacos做为注册中心调用SpringCloud服务 Nacos做为注册中心调用SpringCloud服务 分布式相关 如何构建分布式项目 Oinone如何支持构建分布式项目 构建分布式项目一些要点(dubbo日志关闭等) Oinone构建分布式项目一些注意点 信创支持 后端部署使用达梦数据库 【达梦】后端使用达梦数据库 后端部署使用PostgreSQL数据库 【PostgreSQL】后端使用PostgreSQL数据库 后端部署使用OpenGauss数据库 【OpenGauss】后端使用OpenGauss数据库 后端部署使用MSSQL数据库(SQLServer) 【MSSQL】后端部署使用MSSQL数据库(SQLServer) 东方通Web和Tomcat部署Oinone项目 东方通Web和Tomcat部署Oinone项目 常见扩展 如何增加用户中心的菜单 如何增加用户中心的菜单 导入导出 如何批量导入 如何批量导入 如何支持多Excel多个Sheet导入功能 如何支持多Excel多个Sheet导入功能 如何自定义Excel导入功能 如何自定义Excel导入功能 如何自定义Excel导出功能 如何自定义Excel导出功能 如何自定义表达式 如何自定义表达式 登录扩展 对接外部SSO Oinone登录扩展:对接SSO(4.7.8及之后的版本) 自定义占位符 自定义RSQL占位符及在权限中使用 自定义RSQL占位符(placeholder)及在权限中使用 自定义数据权限拦截处理 自定义数据权限拦截处理 设计器公共 后端无代码设计器Jar包启动方法 后端无代码设计器Jar包启动方法 界面设计器 页面跳转时增加跳转参数 页面跳转时增加跳转参数 界面设计器的导入导出 界面设计器的导入导出 流程设计器 项目中工作流引入和流程触发 项目中工作流引入和流程触发 流程扩展自定义函数示例代码汇总 工作流-流程扩展自定义函数示例代码汇总 工作流-流程代办等页面自定义 工作流-流程代办等页面自定义 审核撤回/回退/拒绝钩子使用 工作流审核撤回/回退/拒绝钩子使用 流程设计器的导入导出 流程设计器的导入导出 如何添加工作流运行时依赖 如何添加工作流运行时依赖 数据可视化 项目中图表设计器引入 数据可视化-项目中数据可视化的实现引入 自定义图表模版 数据可视化中图表的低无一体 图表设计器数据获取示例 数据可视化-数据可视化数据获取示例 如何添加数据可视化运行时依赖 如何添加数据可视化运行时依赖 图表设计器的设计数据导入导出 图表设计器的设计数据导入导出

    2024年5月21日
    00
  • 集成开放-开放接口如何鉴权加密

    使用前提 已经阅读过文档【oinone 7天从入门到精通】的6.2章节-集成平台 已经依赖了内置模块集成平台eip boot启动工程pom.xml新增jar依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-eip2-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-eip2-view</artifactId> </dependency> 配置文件application.yml新增启动依赖模块 pamirs: boot: modules: – eip eip: open-api: enabled: true route: # 开放接口访问IP,开放外网可以配置为0.0.0.0 host: 127.0.0.1 # 开放接口访问端口 port: 8094 # 认证Token加密的AES密钥 aes-key: NxDZUddmvdu3QQpd5jIww2skNx6U0w0uOAXj3NUCLu8= 一、新增开放接口示例代码 开放接口类定义 package pro.shushi.pamirs.demo.api.open; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; @Fun(TestOpenApiModelService.FUN_NAMESPACE) public interface TestOpenApiModelService { String FUN_NAMESPACE = "demo.open.TestOpenApiModelService"; @Function TestOpenApiModel queryById(Long id); } 开放接口实现类 package pro.shushi.pamirs.demo.core.open; import org.apache.camel.ExtendedExchange; import org.springframework.stereotype.Component; import pro.shushi.pamirs.core.common.SuperMap; import pro.shushi.pamirs.demo.api.open.TestEipConfig; import pro.shushi.pamirs.demo.api.open.TestOpenApiModel; import pro.shushi.pamirs.demo.api.open.TestOpenApiModelService; import pro.shushi.pamirs.demo.api.open.TestOpenApiResponse; import pro.shushi.pamirs.eip.api.IEipContext; import pro.shushi.pamirs.eip.api.annotation.Open; import pro.shushi.pamirs.eip.api.constant.EipFunctionConstant; import pro.shushi.pamirs.eip.api.enmu.EipExpEnumerate; import pro.shushi.pamirs.eip.api.entity.openapi.OpenEipResult; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.common.exception.PamirsException; import java.util.Optional; @Fun(TestOpenApiModelService.FUN_NAMESPACE) @Component public class TestOpenApiModelServiceImpl implements TestOpenApiModelService { @Override @Function public TestOpenApiModel queryById(Long id) { return new TestOpenApiModel().queryById(id); } @Function @Open @Open.Advanced( authenticationProcessorFun = EipFunctionConstant.DEFAULT_AUTHENTICATION_PROCESSOR_FUN, authenticationProcessorNamespace = EipFunctionConstant.FUNCTION_NAMESPACE ) public OpenEipResult<TestOpenApiResponse> queryById4Open(IEipContext<SuperMap> context , ExtendedExchange exchange) { String id = Optional.ofNullable(String.valueOf(context.getInterfaceContext().getIteration("id"))).orElse(""); TestOpenApiModel temp = queryById(Long.valueOf(id)); TestOpenApiResponse response = new TestOpenApiResponse(); if(temp != null ) { response.setAge(temp.getAge()); response.setId(temp.getId()); response.setName(temp.getName()); }else{ response.setAge(1); response.setId(1L); response.setName("oinone eip test"); } OpenEipResult<TestOpenApiResponse> result = new OpenEipResult<TestOpenApiResponse>(response); return result; } @Function @Open(config = TestEipConfig.class,path = "error") @Open.Advanced( httpMethod = "post", authenticationProcessorFun = EipFunctionConstant.DEFAULT_AUTHENTICATION_PROCESSOR_FUN, authenticationProcessorNamespace…

    2024年7月25日
    00
  • Nacos做为注册中心:如何调用其他系统的SpringCloud服务?

    Oinone项目引入Nacos作为注册中心,调用外部的SpringCloud服务 Nacos可以做为注册中心,提供给Dubbo和SpringCloud等微服务框架使用。 目前Oinone的底层使用的是Dubbo进行微服务的默认协议调用,但是我们项目如果存在需要调用其他系统提供的SpringCloud服务,Oinone其实并没有限制大家去这么写代码。 可以参考Nacos或SpringCloud的官方文档,只要不存在Jar包冲突等场景,很多的扩展其实大家都可以使用。 注意!!!Nacos、SpringCloud、SpringCloudAlibaba是有依赖版本严格要求的:点击查看 具体示例: 一、项目中增加依赖 主pom引入兼容的版本: <dependencyManagement> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.7.RELEASE</version> <!– 目前兼容的版本 –> <type>pom</type> <scope>import</scope> </dependency> </dependencyManagement> 使用模块的pom引入依赖: <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 二、 配置 application.yml spring: cloud: nacos: discovery: server-addr: localhost:8848 username: nacos password: nacos 三、启动类添加注解 @EnableDiscoveryClient @EnableFeignClients public class NacosConsumerApplication { public static void main(String[] args) { SpringApplication.run(NacosConsumerApplication.class, args); } } 四、验证 创建 Feign Client 接口 import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "nacos-demo") // 指定目标服务的名称 public interface ProviderClient { @GetMapping("/hello") String hello(); } 创建 Controller 调用 Feign Client @RestController public class ConsumerController { private final ProviderClient providerClient; public ConsumerController(ProviderClient providerClient) { this.providerClient = providerClient; } @GetMapping("/hello") public String hello() { return providerClient.hello(); } } 在浏览器中访问 http://localhost:8082/hello你应该会看到服务提供者返回的响应。

    2024年6月4日
    00
  • OSS(CDN)配置和文件系统的一些操作

    目前Oinone支持的OSS类型 类型 服务 OSS 阿里云OSS UPYUN 又拍云 MINIO MinIO HUAWEI_OBS 华为云OBS LOCAL 本地NGINX文件存储 TENCENT_COS 腾讯云COS OSS通用yaml配置 cdn: oss: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: others: [key]: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: PS:others中使用自定义key来指定OSS服务进行文件上传/下载功能。上传/下载必须匹配,否则无法正常使用。 OSS配置示例 阿里云OSS cdn: oss: name: 阿里云 type: OSS bucket: pamirs(根据实际情况修改) uploadUrl: oss-cn-hangzhou.aliyuncs.com downloadUrl: oss-cn-hangzhou.aliyuncs.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true imageResizeParameter: referer: 华为云OBS cdn: oss: name: 华为云 type: HUAWEI_OBS bucket: pamirs(根据实际情况修改) uploadUrl: obs.cn-east-2.myhuaweicloud.com downloadUrl: obs.cn-east-2.myhuaweicloud.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true allowedOrigin: http://192.168.95.31:8888,https://xxxx.xxxxx.com referer: 华为云OBS需要在启动工程增加以下依赖 <okhttp3.version>4.9.3</okhttp3.version> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>${okhttp3.version}</version> </dependency> 注意事项华为云OBS的防盗链配置,仅允许携带特定referer的才可以,而excel导入后端处理的逻辑匿名读的时候是不带referer的,所以会被拒绝 MINIO 文件系统,mino的配置: cdn: oss: name: minio type: MINIO bucket: pamirs(根据实际情况修改) uploadUrl: http://192.168.243.6:32190(根据实际情况修改) downloadUrl: http://192.168.243.6:9000(根据实际情况修改) accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: MINIO无公网访问地址下OSS的配置方式: https://doc.oinone.top/yun-wei-shi-jian/7112.html 又拍云 cdn: oss: name: 又拍云 type: UPYUN…

    后端 2023年11月1日
    00
  • 使用Mapper方式进行联表查询

    有些业务场景需要查询两张表的数据,这时候就需要用到联表查询。下面将介绍两种方式进行联表查询。 场景:A模型页面,查询条件中包含B模型字段 模型A @Model.model(YesOne.MODEL_MODEL) @Model(displayName = "YesOne", summary = "YesOne") public class YesOne extends IdModel { public static final String MODEL_MODEL = "top.YesOne"; @Field.Integer @Field(displayName = "YesId") private Long yesId; @Field.String @Field(displayName = "名字") private String name; @Field.String @Field(displayName = "科目名字") private String professionalName; @Field(displayName = "关联YesTwo") @Field.many2one @Field.Relation(relationFields = {"yesId"},referenceFields = {"id"}) private YesTwo yesTwo; } 模型B @Model.model(YesTwo.MODEL_MODEL) @Model(displayName = "YesTwo", summary = "YesTwo") public class YesTwo extends IdModel { public static final String MODEL_MODEL = "top.YesTwo"; @Field.Integer @Field(displayName = "科目id") private Long professionalId; @Field.String @Field(displayName = "科目名字") private String professionalName; } 1. 使用in的方式查询 通过B模型的查询条件查询出符合条件的所有数据ID,再根据这个ID去A模型里面查询出所需的数据。 @Function.Advanced(displayName = "查询列表", type = FunctionTypeEnum.QUERY, category = FunctionCategoryEnum.QUERY_PAGE, managed = true) @Function(openLevel = {FunctionOpenEnum.LOCAL, FunctionOpenEnum.REMOTE, FunctionOpenEnum.API}) public Pagination<YesOne> queryPage(Pagination<YesOne> page, IWrapper<YesOne> queryWrapper) { String professionalName = (String) queryWrapper.getQueryData().get("professionalName"); if (StringUtils.isNotBlank(professionalName)) { List<Long> yesTwoId = new YesTwo().queryList(Pops.<YesTwo>lambdaQuery() .from(YesTwo.MODEL_MODEL) .eq(YesTwo::getProfessionalName, professionalName)) .stream().map(YesTwo::getId) .collect(Collectors.toList()); LambdaQueryWrapper<YesOne> wq = Pops.<YesOne>lambdaQuery().from(YesOne.MODEL_MODEL); if (CollectionUtils.isNotEmpty(yesTwoId)) { wq.in(YesOne::getYesId, yesTwoId); } return new YesOne().queryPage(page, wq); } return new YesOne().queryPage(page, queryWrapper); } 2. 使用mapper的方式查询 利用sql的方式去直接查询出结果。使用联表查询的方式查询 @Autowired private YesOneQueryMapper yesOneQueryMapper; @Function.Advanced(displayName = "查询列表", type = FunctionTypeEnum.QUERY, category = FunctionCategoryEnum.QUERY_PAGE, managed = true) @Function(openLevel = {FunctionOpenEnum.LOCAL,…

    2024年9月27日
    00

Leave a Reply

登录后才能评论