3.4.3.3 SPI机制-扩展点

扩展点结合拦截器的设计,oinone可以点、线、面一体化管理Function

扩展点用于扩展函数逻辑。扩展点类似于SPI机制(Service Provider Interface),是一种服务发现机制。这一机制为函数逻辑的扩展提供了可能。

一、构建第一个扩展点

自定义扩展点(举例)

在我们日常开发中,随着对业务理解的深入,往往还在一些逻辑中会预留扩展点,以便日后应对不同需求时可以灵活替换某一小块逻辑。

在3.3.4【模型的继承】一文中的PetCatItemQueryService,是独立新增函数只作公共逻辑单元。现在我们给它的实现类增加一个扩展点。在PetCatItemQueryServiceImpl的queryPage方法中原本会先查询PetCatType列表,我们这里假设这个逻辑随着业务发展未来会发生变化,我们可以预先预留【查询萌猫类型扩展点】

Step1 新增扩展点定义PetCatItemQueryCatTypeExtpoint

  1. 扩展点命名空间:在接口上用@Ext声明扩展点命名空间。会优先在本类查找@Ext,若为空则往接口向上做遍历查找,返回第一个查找到的@Ext.value注解值,使用该值再获取函数的命名空间;如果未找到,则返回扩展点全限定类名。所以我们这里扩展点命名空间为:pro.shushi.pamirs.demo.api.extpoint.PetCatItemQueryCatTypeExtpoint

  2. 扩展点技术名称:先取@ExtPoint.name,若为空则取扩展点接口方法名。所以我们这里技术名为queryCatType

package pro.shushi.pamirs.demo.api.extpoint;

import pro.shushi.pamirs.demo.api.model.PetCatType;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;

import java.util.List;

@Ext
public interface PetCatItemQueryCatTypeExtpoint {

    @ExtPoint(displayName = "查询萌猫类型扩展点")
    List<PetCatType> queryCatType();

}

图3-4-3-11 新增扩展点定义PetCatItemQueryCatTypeExtpoint

Step2 修改PetCatItemQueryServiceImpl(用Ext.run模式调用)

修改queryPage,增加扩展点的使用代码。扩展点的使用有两种方式

方法一,使用命名空间和扩展点名称调用Ext.run(namespace, fun, 参数);

方法二,使用函数式接口调用Ext.run(函数式接口, 参数);

我们这里用了第二种方式

  1. 用PetCatItemQueryCatTypeExtpoint的全限定类名作为扩展点的命名空间(namespace)

  2. 用queryCatType的方法名作为扩展点的技术名称(name)

  3. 根据namespace+name去找到匹配扩展点实现,并根据规则是否匹配,以及优先级唯一确定一个扩展点实现去执行逻辑

package pro.shushi.pamirs.demo.core.service;

……省略依赖包

@Model.model(PetCatItem.MODEL_MODEL)
@Component
public class PetCatItemAction extends DataStatusBehavior<PetCatItem> {

    @Override
    protected PetCatItem fetchData(PetCatItem data) {
        return data.queryById();
    }
    @Action(displayName = "启用")
    public PetCatItem dataStatusEnable(PetCatItem data){
        data = super.dataStatusEnable(data);
        data.updateById();
        return data;
    }

    @Function.Advanced(displayName = "查询模型数据的默认过滤条件", type = FunctionTypeEnum.QUERY, managed = true)
    @Function(openLevel = {LOCAL})
    public String queryFilters() {
        StringBuilder sqlWhereCondition = new StringBuilder();
//        List<PetCatType> typeList = new PetCatType().queryList();
        List<PetCatType> typeList = Ext.run(PetCatItemQueryCatTypeExtpoint::queryCatType, new Object[]{});
        if(!CollectionUtils.isEmpty(typeList)){
//          sqlWhereCondition.append("type_id");
            sqlWhereCondition.append(PStringUtils.fieldName2Column(LambdaUtil.fetchFieldName(PetCatItem::getTypeId)));
            sqlWhereCondition.append(StringUtils.SPACE).append(SqlConstants.IN).append(CharacterConstants.LEFT_BRACKET);
            for(PetCatType petCatType: typeList){
                sqlWhereCondition.append(petCatType.getId()).append(CharacterConstants.SEPARATOR_COMMA);
            }
            sqlWhereCondition.deleteCharAt(sqlWhereCondition.lastIndexOf(CharacterConstants.SEPARATOR_COMMA));
            sqlWhereCondition.append(StringUtils.SPACE).append(CharacterConstants.RIGHT_BRACKET);
        }
        return sqlWhereCondition.toString();
    }

    ……省略其他函数
}

图3-4-3-12 修改PetCatItemQueryServiceImpl

Step3 新增扩展点实现PetCatItemQueryCatTypeExtpointOne

  1. 扩展点命名空间要与扩展点定义一致,用@Ext(PetCatItemQueryCatTypeExtpoint.class)

  2. @ExtPoint.Implement声明这是在@Ext声明的命名空间下,且技术名为queryCatType的扩展点实现

package pro.shushi.pamirs.demo.core.extpoint;

import pro.shushi.pamirs.demo.api.extpoint.PetCatItemQueryCatTypeExtpoint;
import pro.shushi.pamirs.demo.api.model.PetCatType;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;
import pro.shushi.pamirs.meta.api.session.PamirsSession;

import java.util.List;

@Ext(PetCatItemQueryCatTypeExtpoint.class)
public class PetCatItemQueryCatTypeExtpointOne implements PetCatItemQueryCatTypeExtpoint {

    @Override
    @ExtPoint.Implement(displayName = "查询萌猫类型扩展点的默认实现")
    public List<PetCatType> queryCatType() {
        PamirsSession.getMessageHub().info("走的是第一个扩展点");
        List<PetCatType> typeList = new PetCatType().queryList();
        return typeList;
    }
}

图3-4-3-13 新增扩展点实现PetCatItemQueryCatTypeExtpointOne

Step4 重启看效果

  1. 萌猫商品-列表页面的逻辑没有变化正常,说明typeList从扩展点中是取到了

image.png

图3-4-3-14 示例效果

  1. 用Insomnia直接发起GraphQL请求,返回结果里可以明确知道这是扩展点实现【PetCatItemQueryCatTypeExtpointOne】执行的结果

image.png

图3-4-3-15 示例效果

Step5 自行测试扩展点的优先级

附上第二个扩展点实现的代码,快去试试吧

package pro.shushi.pamirs.demo.core.extpoint;

import pro.shushi.pamirs.demo.api.extpoint.PetCatItemQueryCatTypeExtpoint;
import pro.shushi.pamirs.demo.api.model.PetCatType;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;
import pro.shushi.pamirs.meta.api.session.PamirsSession;

import java.util.List;

@Ext(PetCatItemQueryCatTypeExtpoint.class)
public class PetCatItemQueryCatTypeExtpointTwo implements PetCatItemQueryCatTypeExtpoint {

    @Override
    @ExtPoint.Implement(priority = 95,displayName = "查询萌猫类型扩展点的实现,优先级取胜")
    public List<PetCatType> queryCatType() {
        PamirsSession.getMessageHub().info("走的是第二个扩展点");
        List<PetCatType> typeList = new PetCatType().queryList();
        return typeList;
    }
}

图3-4-3-16 测试扩展点的优先级(第二个扩展点实现代码)

默认扩展点(举例)

由前端直接发起调用oinone后端Function(能被前端直接发起的Function前提是namespace挂在模型上),当前端通过GraphQL发起对函数的请求是,oinone都会默认执行三个内置扩展点分别是前置扩展点、覆盖扩展点和后置扩展点。

默认扩展点与函数的关联关系

扩展点扩展的函数与扩展点通过扩展点的命名空间和技术名称关联。扩展点与所扩展函数的命名空间一致。前置扩展点、重载扩展点和后置扩展点的技术名称的规则是所扩展函数的函数编码fun加上“Before”、“Override”和“After”后缀;方法体内调用扩展点直接使用接口调用,所以技术名称可以任意定义,只需要在同一命名空间下唯一即可。

我们在3.3.4【模型继承】一文中关于多表继承的内容有提到过通过实现扩展点来保证子模型与父模型数据同步。此次列子中我们来替换下PetShop的sayHello函数

Step1 新增扩展点定义PetShopSayhelloOverrideExtpoint

package pro.shushi.pamirs.demo.api.extpoint;

import pro.shushi.pamirs.demo.api.model.PetShop;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;

@Ext(PetShop.class)
public interface PetShopSayhelloOverrideExtpoint {

    @ExtPoint(displayName = "覆盖PetShop的sayHello执行逻辑")
    public PetShop sayHelloOverride(PetShop shop);

}

图3-4-3-17 新增扩展点定义PetShopSayhelloOverrideExtpoint

Step2 新增扩展点实现PetShopSayhelloOverrideExtpointImpl

package pro.shushi.pamirs.demo.core.extpoint;

import pro.shushi.pamirs.demo.api.extpoint.PetShopSayhelloOverrideExtpoint;
import pro.shushi.pamirs.demo.api.model.PetShop;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;
import pro.shushi.pamirs.meta.api.session.PamirsSession;

@Ext(PetShop.class)
public class PetShopSayhelloOverrideExtpointImpl implements PetShopSayhelloOverrideExtpoint {

    @ExtPoint.Implement(displayName = "覆盖PetShop的sayHello执行逻辑")
    public PetShop sayHelloOverride(PetShop shop){
        PamirsSession.getMessageHub().info("OverrideExtpoint Hello:"+shop.getShopName());
        return shop;
    }
}

图3-4-3-18 新增扩展点实现PetShopSayhelloOverrideExtpointImp

Step3 确保PetShop的sayHello函数存在

详见3.4.1【构建第一个Function】一文

Step4 重启查看效果

image.png

图3-4-3-19 示例效果

二、总结

oinone用默认扩展点为Function提供三种默认扩展点,并通过自定义扩展点在Function逻辑内部任意插入扩展点,让Function作为oinone的逻辑管理单元的可管理性大大提升。同时结合拦截器的设计,oinone可以点、线、面一体化管理Function

注:默认扩展点,不是由前端发起而是后端编程调用,默认不会生效,如果要生效请参考4.1.9【函数之元位指令】的一文

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9248.html

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

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日
Next 2024年5月23日

相关推荐

  • 开放平台

    1. 开放介绍 开放平台是将 Oinone 平台内的能力向外开放,如开放商品信息查询接口、发货单查询接口等。 包括开放接口、三方应用管理。 2. 开放接口 管理开放接口信息,基本操作包括:新增、编辑、停用/启用。 2.1. 新增接口 定义API名称,选择业务域、关联模型,方法支持GET/POST/PUT/DELETE,配置接口参数、响应结果等信息。 2.2. 编辑接口 编辑需要填写的内容同新增,不做赘述。 2.3. 停用/启用 新增后为已启用,停用后,API将无法访问,请慎重使用;针对停用的API进行启用。 3. 应用管理 管理开放接口集成的外部应用,基本操作包括:新增、查看密钥、授权调整、停用/启用。 3.1. 新增应用 新增应用时,输入应用名称,选择数据传输加密算法AES密钥或RSA公钥,勾选授权的API接口。 3.2. 停用/启用 新增后为已启用,停用后,应用将无法访问授权的接口,请慎重使用;针对停用的应用可进行启用。 3.3. 查看密钥 点击【查看密钥】,弹窗展示当前 API Secret,支持复制。 3.4. 授权调整 指调整当前应用的授权的API 范围。

    2024年6月20日
    2.4K00
  • 文件

    文件应用下包含“导入/导出模版、导入任务、导出任务”三个菜单。其中导入/导出任务菜单比较常用。 导入/导出模版 当前版本会为租户的表格视图自动创建导出模版,此处可进行编辑、查看详情的操作。 导入任务 导入任务可以下载导入文档,点击详情可以查看该条记录的导入结果,任务信息分组中可以查看错误信息。 导出任务 和导入任务一致,导出任务菜单中可以下载导出文档,点击详情可以查看该条记录的导出结果,任务信息分组中可以查看错误信息。

    2024年6月20日
    1.4K00
  • 4.2.8 自定义组件与设计器结合(新)

    界面设计器组件管理页面添加组件 进入组件的元件管理页面 点击“添加元件” 设计元件的属性 这里以是否“显示清除按钮”作为自定义属性从左侧拖入到中间设计区域,然后发布 点击“返回组件” 鼠标悬浮到卡片的更多按钮的图标,弹出下拉弹出“低无一体”的按钮 在弹窗内点击“生成SDK”的按钮 生成完成后,点击“下载模板工程” 解压模板工程kunlun-sdk.zip 解压后先查看README.MD,了解一下工程运行要点,可以先运行 npm i 安装依赖 再看kunlun-plugin目录下已经有生成好的组件对应的ts和vue文件 下面在vue文件内增加自定义代码,可以运行 npm run dev 在开发模式下调试看效果 <template> <div class="my-form-string-input"> <oio-input :value="realValue" @update:value="change" > <template #prepend>MyPrepend</template> </oio-input> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; import { OioInput } from '@kunlun/vue-ui-antd'; export default defineComponent({ name: 'customField1', components: { OioInput }, props: { value: { type: String }, change: { type: Function }, }, setup(props) { const realValue = ref<string | null | undefined>(props.value); return { realValue }; } }); </script> <style lang="scss"> .my-form-string-input { border: 1px solid red; } </style> 确定改好代码后运行 npm run build,生成上传所需的js和css文件 可以看到 kunlun-plugin目录下多出了dist目录,我们需要的是 kunlun-plugin.umd.js 和 kunlun-plugin.css 这2个文件 再次回到组件的“低无一体”管理弹窗页面,上传上面生成的js和css文件,并点击“确定”保存,到这里我们的组件就新增完成了。 下面我们再到页面设计器的页面中使用上面设计的组件(这里的表单页面是提前准备好的,这里就不介绍如何新建表单页面了) 将左侧组件库拉直最底部,可以看到刚刚新建的组件,将其拖至中间设计区域,我们可以看到自定义组件的展示结果跟刚刚的代码是对应上的(ps: 如果样式未生效,请刷新页面查看,因为刚刚上传的js和css文件在页面初始加载的时候才会导入进来,刚刚上传的动作未导入新上传的代码文件),再次点击设计区域中的自定义组件,可以看到右侧属性设置面板也出现了元件设计时拖入的属性。 最后再去运行时的页面查看效果,与代码逻辑一致!

    2024年5月23日
    1.5K00
  • 4.1.25 框架之搜索引擎

    一、使用场景 在碰到大数据量并且需要全文检索的场景,我们在分布式架构中基本会架设ElasticSearch来作为一个常规解决方案。在oinone体系中增强模型就是应对这类场景,其背后也是整合了ElasticSearch。 二、整体介绍 oinone与es整合设计图 图4-1-25-1 Oinone与es整合设计图 基础环境安装 Canal安装 详见4.1.10【函数之触发与定时】一文 修改Canal配置并重启 新增Canal的实例【destinaion: pamirs】,监听分表模型的binlog【filter: demo.demo_core_sharding_model……】用于增量同步 pamirs: middleware: data-source: jdbc-url: jdbc:mysql://localhost:3306/canal_tsdb?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=false&useSSL=false&requireSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: oinone canal: ip: 127.0.0.1 port: 1111 metricsPort: 1112 zkClusters: – 127.0.0.1:2181 destinations: – destinaion: pamirschangedata name: pamirschangedata desc: pamirschangedata slaveId: 1235 filter: demo\.demo_core_pet_talent dbUserName: root dbPassword: oinone memoryStorageBufferSize: 65536 topic: CHANGE_DATA_EVENT_TOPIC dynamicTopic: false dbs: – { address: 127.0.0.1, port: 3306 } – destinaion: pamirs id: 1234 name: pamirs desc: pamirs slaveId: 1234 filter: demo\.demo_core_sharding_model_0,demo\.demo_core_sharding_model_1,demo\.demo_core_sharding_model_2,demo\.demo_core_sharding_model_3,demo\.demo_core_sharding_model_4,demo\.demo_core_sharding_model_5,demo\.demo_core_sharding_model_6,demo\.demo_core_sharding_model_7 dbUserName: root dbPassword: oinone memoryStorageBufferSize: 65536 topic: BINLOG_EVENT_TOPIC dynamicTopic: false dbs: – { address: 127.0.0.1, port: 3306 } tsdb: enable: true jdbcUrl: "jdbc:mysql://127.0.0.1:3306/canal_tsdb" userName: root password: oinone mq: rocketmq rocketmq: namesrv: 127.0.0.1:9876 retryTimesWhenSendFailed: 5 dubbo: application: name: canal-server version: 1.0.0 registry: address: zookeeper://127.0.0.1:2181 protocol: name: dubbo port: 20881 scan: base-packages: pro.shushi server: address: 0.0.0.0 port: 10010 sessionTimeout: 3600 图4-1-25-2 修改Canal配置并重启 ES安装 下载安装包官方下载地址,也可以直接下载elasticsearch-8.4.1-darwin-x86_64.tar.gz.txt(361.7 MB),下载后去除后缀.txt,然后解压文件 替换安装目录/config下的[elasticsearch.yml](elasticsearch)(1 KB),主要是文件中追加了三个配置 xpack.security.enabled: false xpack.security.http.ssl.enabled: false xpack.security.transport.ssl.enabled: false 图4-1-25-3 elasticsearc.yml追加三个配置 启动 a. 导入环境变量(ES运行时需要JDK18及以上版本JDK运行环境, ES安装包中包含了一个JDK18版本) # export JAVA_HOME=/Users/oinone/Documents/oinone/es/elasticsearch-8.4.1/jdk.app/Contents/Home/ export JAVA_HOME=ES解压安装目录/jdk.app/Contents/Home/ 图4-1-25-4 导入环境变量 b. 运行ES ## nohup /Users/oinone/Documents/oinone/es/elasticsearch-8.4.1/bin/elasticsearch >> $TMPDIR/elastic.log 2>&1 & nohup ES安装目录/bin/elasticsearch >> $TMPDIR/elastic.log 2>&1 & 图4-1-25-5 运行ES 停止ES lsof…

    2024年5月23日
    1.6K00

Leave a Reply

Please Login to Comment