# 流程事件开发

监听流程事件执行相关业务逻辑是一个较为复杂的功能,1.8.12之前的版本只支持本地开发场景,1.8.12以及之后的版本在线开发和本地开发都支持。

# 事件类型

流程在流转过程中会产生事件,包括流程事件和环节事件。

  1. 流程事件(全局)
    • 发起流程

    • 完成流程

  2. 环节事件(全局 & 单个环节)
    • 进入环节

    • 创建任务

    • 完成任务

    • 离开环节

全局环节事件会为每个环节增加默认环节事件,如果单独为某个环节设置了环节事件,则会覆盖全局环节事件。

# 系统配置(1.8.12以及之后的版本)

事件是基于 Rabbit MQ 中间件进行通信的。我们需要添加如下配置:

  • # 本地开发

# application.yml
spring:
  cloud:
    stream:
      default-binder: rabbit
  # 流程服务所在 MQ
  rabbitmq:
    host: changeit
    port: changeit
    username: changeit
    password: changeit
  • # 在线开发

在项目配置->环境配置中,点击新建环境,配置如下

mq-config

# 系统配置(1.8.12之前的版本)

# 1.添加MQ配置

只支持本地开发场景,事件是基于 Rabbit MQ 中间件进行通信的。我们需要添加如下配置:

# application.yml
spring:
  cloud:
    stream:
      bindings:
        workflowClientChannel:
          destination: ${oauth2.client-id} # 通讯的chanel默认情况下和 client-id 保持一致
          group: integration
          contentType: "application/json"
  # 流程服务所在 MQ
  rabbitmq:
    host: changeit
    port: changeit
    username: changeit
    password: changeit

# 2.添加注解

WebApplication.java 中添加注解 @EnableWorkflowConnector

@EnableWorkflowConnector
public class WebApplication {
    ...
}

# 事件处理器

事件处理器是指监听到事件后用什么方式处理,这里支持两种:

  • 函数实现:对应设计器中的函数
  • Java实现:对应设计器中的默认

# 函数实现

# 1.创建编排函数

如不了解编排函数,请先查看业务逻辑编排章节。

我们创建一个查询实体详情的编排函数用作演示(业务系统根据自己的业务场景创建各自的编排函数)

在编排函数中可以使用jq表达式获取上下文变量,例如上图通过${.context.businessKey}获取业务ID。

以下是上下文参数样例:

{
	"context": {
		"inBoundVariables": {
			"code": {														// 事件类型编码
				"type": "string",
				"value": "onCompleted"
			},
			"processStatus": {												// 流程状态
				"type": "string",
				"value": "COMPLETED"
			},
			"processInstance": {											// 流程实例详情
                "type": "map",
                "value": {
                    "id": "459493e5-328c-11ef-8dff-8ab4c0be40c6",
                    "name": "测试合同 ",
                    "processDefinitionId": "process_contract:42:210ff991-328c-11ef-8dff-8ab4c0be40c6",
                    "processDefinitionKey": "process_contract",
                    "initiator": "eZGHAryQLmpd8sZXXnFpnZ",
                    "startDate": "2024-06-25T00:45:51.595+0000",
                    "businessKey": "f4506e9d-65a4-4b31-96a8-679f0e178235",
                    "status": "COMPLETED",
                    "processDefinitionVersion": 42
                }
			},
			"funcCode": {													// 编排函数的编码
				"type": "string",
				"value": "server.liuchengshijian"
			}
		},
		"processInstanceId": "459493e5-328c-11ef-8dff-8ab4c0be40c6",		// 流程实例ID
		"businessKey": "f4506e9d-65a4-4b31-96a8-679f0e178235",				// 发起流程时传入的业务ID
		"connectorType": "Ieeh3W4LvOAHDQHBMMC5lD.OyF4wA"
    ......
    ......
	},
	"requestInfo": {
		"accessToken": "token string",
		"userId": "UiyzmjfFa2okhkxxSzjq5j",
		"userName": "管理员"
	}
}

# 2.添加事件监听

事件注册和实现完成后,所有属于该应用的流程就都可以使用该事件了。

  • 全局事件:在流程设计器中,点击空白区域,就可以添加全局流程事件和全局环节事件
  • 环节事件:选中某个流程环节,就可以单独给这个环节添加环节级别的事件

# Java实现

# 1.注册事件

采用Java实现方式,需要先到流程服务控制台,找到对应的应用,在应用的事件管理中注册事件,如:

  • destination:消息所在通道的名称,该值一般为应用的clientId,同时需要与application.yml文件中的值保持一致
  • code:该事件的唯一标识,与后续实现的代码里的isHandle方法中的code一致
  • 其它参数:注册时,还允许配置其它参数,额外配置的参数,应用在收到消息时,可以通过下面方式获取。
IntegrationRequest.getIntegrationContext().getInBoundVariables().get("key")

# 2.实现消息处理器

在工程里面添加一个SendSMSHandler(示例),实现 WorkflowMessageHandler 的方法。

  • isHandle()方法:应用收到消息后,该处理器是否响应这条消息
  • handle()方法:当isHandle返回true时,执行该响应
package com.lowcode.webapp;

import fly.core.util.JSON;
import net.bingosoft.workflow.client.commons.IntegrationRequestHelper;
import net.bingosoft.workflow.client.connectors.WorkflowMessageHandler;
import org.activiti.cloud.api.process.model.IntegrationRequest;
import org.activiti.cloud.api.process.model.IntegrationResult;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

@Component
public class SendSMSHandler implements WorkflowMessageHandler {

    @Override
    public void handle(IntegrationRequest event, Message<IntegrationResult> outMessage) {
        System.out.println("SMS Handler, 调用通知流程发起者,消息体: " + JSON.encode(event));
    }

    @Override
    public boolean isHandle(IntegrationRequest event) {
        //该事件的唯一标识,事件注册时,需要使用到该值
        String codeInMessage= IntegrationRequestHelper.getCode(event);
        if(codeInMessage.equals("send_sms")){
            return true;
        }
        return false;
    }
}

# 3.添加事件监听

  • 添加事件方式与前文描述基本一致,只是在事件处理器中选择默认,再从下方出现的选择框中选择之前创建的编排函数。
顶部