项目中工作流引入和流程触发

目录

1. 使用工作流需要依赖的包和设置
2. 触发方式
2.1 自动触发方式
2.2 触发方式

1.使用工作流需要依赖的包和设置

1.1 工作流需要依赖的模块

需在pom.xml中增加workflow、sql-record和trigger相关模块的依赖

  • workflow:工作流运行核心模块
  • sql-record:监听流程发布以后对应模型的增删改监听
  • trigger:异步任务调度模块
<dependency>
    <groupId>pro.shushi.pamirs.workflow</groupId>
    <artifactId>pamirs-workflow-api</artifactId>
</dependency>
<dependency>
    <groupId>pro.shushi.pamirs.workflow</groupId>
    <artifactId>pamirs-workflow-core</artifactId>
</dependency>

<dependency>
    <groupId>pro.shushi.pamirs.core</groupId>
    <artifactId>pamirs-sql-record-core</artifactId>
</dependency>

<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>

在application.yml中增加对应模块的依赖以及sql-record路径以及其他相关设置

pamirs:
...

  record:
    sql:
      #改成自己路径
      store: /opt/pamirs/logs
...

  boot:
    init: true
    sync: true
    modules:
...
      - sql_record
      - trigger
      - workflow
...

  sharding:
    define:
      data-sources:
        ds:
          pamirs
      models:
        "[trigger.PamirsSchedule]":
          tables: 0..13

  event:
    enabled: true
    schedule:
      enabled: true
      # ownSign区分不同应用
      ownSign: demo
    rocket-mq:
      # enabled 为 false情况不用配置
      namesrv-addr: 192.168.6.2:19876
    trigger:
      auto-trigger: true

2.触发方式

2.1自动触发方式

在流程设计器中设置触发方式,如果设置了代码触发方式则不会自动触发

2.2代码调用方式触发

2.2.1.再流程设计器中触发设置中,设置为是否人工触发设置为是

数式Oinone低代码-代码方式调用触发工作流

2.2.2.查询数据库获取该流程的编码

数式Oinone低代码-代码方式调用触发工作流

2.2.3.在代码中调用

/**
     * 触发⼯作流实例
     */
    private Boolean startWorkflow(WorkflowD workflowD, IdModel modelData) {
        WorkflowDefinition workflowDefinition = new WorkflowDefinition().queryOneByWrapper(
                Pops.<WorkflowDefinition>lambdaQuery()
                        .from(WorkflowDefinition.MODEL_MODEL)
                        .eq(WorkflowDefinition::getWorkflowCode, workflowD.getCode())
                        .eq(WorkflowDefinition::getActive, 1)
        );
        if (null == workflowDefinition) {
            // 流程没有运⾏实例
            return Boolean.FALSE;
        }
        String model = Models.api().getModel(modelData);

        //⼯作流上下⽂
        WorkflowDataContext wdc = new WorkflowDataContext();
        wdc.setDataType(WorkflowVariationTypeEnum.ADD);
        wdc.setModel(model);
        wdc.setWorkflowDefinitionDefinition(workflowDefinition.parseContent());
        wdc.setWorkflowDefinition(workflowDefinition);
        wdc.setWorkflowDefinitionId(workflowDefinition.getId());
        IdModel copyData = KryoUtils.get().copy(modelData);
        // ⼿动触发创建的动作流,将操作⼈设置为当前⽤户,作为流程的发起⼈
        copyData.setCreateUid(PamirsSession.getUserId());
        copyData.setWriteUid(PamirsSession.getUserId());
        String jsonData = JsonUtils.toJSONString(copyData.get_d());
        //触发⼯作流 新增时触发-onCreateManual 更新时触发-onUpdateManual
        Fun.run(WorkflowModelTriggerFunction.FUN_NAMESPACE, "onCreateManual", wdc, msgId, jsonData);
        return Boolean.TRUE;
    }

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

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

Like (3)
数式-海波's avatar数式-海波数式管理员
Previous 2023年11月7日 am11:35
Next 2023年11月7日 pm2:28

相关推荐

  • OSS(CDN)配置和文件系统的一些操作

    目前Oinone支持的OSS类型 类型 服务 OSS 阿里云OSS UPYUN 又拍云 MINIO MinIO HUAWEI_OBS 华为云OBS LOCAL 本地NGINX文件存储 TENCENT_COS 腾讯云COS CTYUN_ZOS 天翼云ZOS 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: 又拍云…

    后端 2023年11月1日
    2.2K00
  • 如何使用位运算的数据字典

    场景举例 日常有很多项目,数据库中都有表示“多选状态标识”的字段。在这里用我们项目中的一个例子进行说明一下: 示例一: 表示某个商家是否支持多种会员卡打折(如有金卡、银卡、其他卡等),项目中的以往的做法是:在每条商家记录中为每种会员卡建立一个标志位字段。如图: 用多字段来表示“多选标识”存在一定的缺点:首先这种设置方式很明显不符合数据库设计第一范式,增加了数据冗余和存储空间。再者,当业务发生变化时,不利于灵活调整。比如,增加了一种新的会员卡类型时,需要在数据表中增加一个新的字段,以适应需求的变化。  – 改进设计:标签位flag设计二进制的“位”本来就有表示状态的作用。可以用各个位来分别表示不同种类的会员卡打折支持:这样,“MEMBERCARD”字段仍采用整型。当某个商家支持金卡打折时,则保存“1(0001)”,支持银卡时,则保存“2(0010)”,两种都支持,则保存“3(0011)”。其他类似。表结构如图: 我们在编写SQL语句时,只需要通过“位”的与运算,就能简单的查询出想要数据。通过这样的处理方式既节省存储空间,查询时又简单方便。 //查询支持金卡打折的商家信息:   select * from factory where MEMBERCARD & b'0001'; // 或者:   select * from factory where MEMBERCARD & 1;    // 查询支持银卡打折的商家信息:   select * from factory where MEMBERCARD & b'0010'; // 或者:   select * from factory where MEMBERCARD & 2; 二进制( 位运算)枚举 可以通过@Dict注解设置数据字典的bit属性或者实现BitEnum接口来标识该枚举值为2的次幂。二进制枚举最大的区别在于值的序列化和反序列化方式是不一样的。 位运算的枚举定义示例 import pro.shushi.pamirs.meta.annotation.Dict; import pro.shushi.pamirs.meta.common.enmu.BitEnum; @Dict(dictionary = ClientTypeEnum.DICTIONARY, displayName = "客户端类型枚举", summary = "客户端类型枚举") public enum ClientTypeEnum implements BitEnum { PC(1L, "PC端", "PC端"), MOBILE(1L << 1, "移动端", "移动端"), ; public static final String DICTIONARY = "base.ClientTypeEnum"; private final Long value; private final String displayName; private final String help; ClientTypeEnum(Long value, String displayName, String help) { this.value = value; this.displayName = displayName; this.help = help; } @Override public Long value() { return value; } @Override public String displayName() { return displayName; } @Override public String help() { return help; } } 使用方法示例 API: addTo 和 removeFrom List<ClientTypeEnum> clientTypes = module.getClientTypes(); // addTo ClientTypeEnum.PC.addTo(clientTypes); // removeFrom ClientTypeEnum.PC.removeFrom(clientTypes); 在查询条件中的使用 List<Menu> moduleMenus = new Menu().queryListByWrapper(menuPage, LoaderUtils.authQuery(wrapper).eq(Menu::getClientTypes, ClientTypeEnum.PC));

    2023年11月24日
    2.3K00
  • 项目中排除掉特定的Hook和扩展点

    总体介绍 在共库共Redis的情况下,某些场景存在需要过滤掉特定Hook和扩展点(extpoint)的情况。本文介绍排除掉的配置方法 1. Oinone如何排除特定的Hook 配置: pamirs: framework: hook: excludes: – 排除的扩展点列表 示例: pamirs: framework: hook: excludes: – pro.shushi.pamirs.timezone.hook.TimezoneHookBefore – pro.shushi.pamirs.timezone.hook.TimezoneHookAfter – pro.shushi.pamirs.timezone.hook.TimezoneSessionInitHook – pro.shushi.pamirs.translate.hook.TranslateAfterHook 2. Oinone如何排除特定的扩展点 配置 pamirs: framework: extpoint: excludes: – 排除的扩展点列表 示例: pamirs: framework: extpoint: excludes: – pro.shushi.pamirs.demo.core.extpoint.PetCatTypeExtPoint

    2024年5月13日
    2.0K00
  • 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日
    2.9K00
  • Oinone远程调用链路源码分析

    前提 源码分析版本是 5.1.x版本 概要 在服务启动时,获取注解REMOTE的函数,通过dubbo的泛化调用发布。在调用函数时,通过dubbo泛化调用获取结果。 注册服务者 在spring 启动方法installOrLoad中初始化 寻找定义REMOTE的方法 组装dubbo的服务配置 组装服务对象实现引用,内容如下,用于注册 调用前置处理 放信息到SessionApi 函数调用链追踪,放到本地TransmittableThreadLocal 从redis中获取到的数据进行反序列化并存在到本地的线程里 Trace信息,放一份在sessionApi中 和ThreadLocal 调用函数执行 返回数据转成特定格式 通过线程组调用dubbo的ServiceConfig.export 服务发布 时序图 源码分析 根据条件判断,确定向dubbo进行服务发布RemoteServiceLoader public void publishService(List<FunctionDefinition> functionList,Map<String,Runnable> isPublished) { // 因为泛化接口只能控制到namespace,控制粒度不能到fun级别,这里进行去重处理 Map<String, Function> genericNamespaceMap = new HashMap<>(); for (FunctionDefinition functionDefinition : functionList) { Function function = new Function(functionDefinition) try { //定义REMOTE, 才给予远程调用 if (FunctionOpenEnum.REMOTE.in(function.getOpen()) && !ClassUtils.isInterface(function.getClazz())) { genericNamespaceMap.putIfAbsent(RegistryUtils.getRegistryInterface(function), function); } } catch (PamirsException e) { } } // 发布远程服务 for (String namespace : genericNamespaceMap.keySet()) { Function function = genericNamespaceMap.get(namespace); if(isPublished.get(RegistryUtils.getRegistryInterface(function)) == null){ // 发布,注册远程函数服务,底层使用dubbo的泛化调用 Runnable registryTask = () -> remoteRegistry.registryService(function); isPublished.put(RegistryUtils.getRegistryInterface(function),registryTask); }else{ } } } 构造ServiceConfig方法,设置成泛化调用,进行发布export()DefaultRemoteRegistryComponent public void registryGenericService(String interfaceName, List<MethodConfig> methods, String group, String version, Integer timeout, Integer retries) { …. try { ServiceConfig<GenericService> service = new ServiceConfig<>(); // 服务接口名 service.setInterface(interfaceName); // 服务对象实现引用 service.setRef(genericService(interfaceName)); if (null != methods) { service.setMethods(methods); } // 声明为泛化接口 service.setGeneric(Boolean.TRUE.toString()); // 基础元数据 constructService(group, version, timeout, retries, service); service.export(); } catch (Exception e) { ….. } } // 服务对象实现引用 private GenericService genericService(String interfaceName) { return (method, parameterTypes, args) -> { PamirsSession.clear(); Function function = Objects.requireNonNull(PamirsSession.getContext()).getFunction(RegistryUtils.getFunctionNamespace(method), RegistryUtils.getFunctionFun(method)); if (log.isDebugEnabled()) { log.debug("interfaceName: " + interfaceName + ",…

    2024年9月4日
    1.9K00

Leave a Reply

Please Login to Comment