# 1、平台SPI集成
BPM的SPI扩展能力继承的是V8平台统一的SPI扩展能力,基础应用包已经导入,第三方按照V8统一的SPI编写工程制作jar包,并在BPM的nacos配置中添加加载即可。
# 1.1、SPI集成jar包步骤
【1】创建独立的本地java项目。 【2】第三方需要引用bpm-facade接口包。 【3】实现bpm-facade中定义的关键接口
| 接口名称 | 接口说明 |
|---|---|
| com.seeyon.bpm.api.ext.activity.ActivityBehaviorFactory | 自定义节点加载的工厂类,主要负责自定义节点行为、json文件等关键信息加载 |
| com.seeyon.bpm.api.ext.activity.ActivityBehavior | 定义自定义节点在运行态的实际执行动作,例如获取运行时数据,修改表单数据等 |
【4】定义自定义节点对应的json配置文件。 【5】依据V8平台统一的SPI集成机制,在工程目录创建resources/META-INF/spring.factories文件,并将实现的com.seeyon.bpm.api.ext.activity.ActivityBehaviorFactory=xxxx实现类加入到该文件。 【5】通过maven或者其他构建工具,对该独立功能制作成jar包。
# 2、详细实例
本实例以添加一个简单节点,并将其显示在流程设计的选项中,以及最终在流程运行态获取流程实例运行时数据
# 2.1、制作集成jar包
# 2.1.1、创建独立工程
这里我们创建一个简单的maven工程,项目名称叫demo-activity

# 2.1.2、添加相关依赖
添加bpm-facade依赖,这里需要注意集成到目标bpm服务的版本,我们这里采用3.18.0-DEV-SNAPSHOT为例,在pom.xml中添加依赖,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>demo-activity</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.seeyon</groupId>
<artifactId>bpm-facade</artifactId>
<version>3.18.0-DEV-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
# 2.1.3、实现相关接口

# 具体代码如下:
import com.seeyon.bpm.api.ext.activity.ActivityBehavior;
import com.seeyon.bpm.api.ext.activity.ActivityBehaviorFactory;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class DemoSpiActivityBehaviorFactoryImpl implements ActivityBehaviorFactory {
/**
* 用来缓存每个自定义节点的行为实例
*/
private Map<String, List<ActivityBehavior>> behaviors = new HashMap<String, List<ActivityBehavior>>();
/**
*
* 获取某个自定义节点的所有行为列表
*
* @param configId 节点配置ID,这个配置ID就是描述自定义节点配置信息的json文件中定义的configId
* @return 返回当前扩展程序定义的所有与configId相关的ActivityBehavior行为实例ID
*/
public List<ActivityBehavior> getActivityBehaviors(String configId) {
if("demospiactivity".equals(configId)){
List<ActivityBehavior> list = new ArrayList<ActivityBehavior>();
list.add(new DemoSPIActivityBehavior());
return list;
}
return null;
}
/**
*
* 获取某个自定义节点参数配置的json文件信息
*
* @param configId 节点配置ID,这个配置ID就是描述自定义节点配置信息的json文件中定义的configId
* @return 以字符串形式返回定义的json文件内容
*/
public String getActivityConfiguration(String configId) {
InputStream stream = DemoSpiActivityBehaviorFactoryImpl.class.getClassLoader().getResourceAsStream("config/DemoSpiActivity.json");
String message = "";
try{
message = IOUtils.toString(stream, "UTF-8");
}catch (IOException e) {
}
return message;
}
/**
* 获取当前软件包定义了那些自定义节点信息
* @return 返回一个列表,这个列表包含了所以该软件包定义的自定义节点的configId
*/
public Set<String> supportActivities() {
Set<String> set = new HashSet<String>();
set.add("demospiactivity");
return set;
}
}
# com.seeyon.bpm.api.ext.activity.ActivityBehaviorFactory接口说明
| 方法名称 | 方法用途说明 |
|---|---|
| getActivityBehaviors | 根据自定义节点ID,获取某个自定义节点的所有行为列表 |
| getActivityConfiguration | 获取某个自定义节点参数配置的json文件信息 |
| supportActivities | 获取当前软件包定义了那些自定义节点信息 |
import com.seeyon.bpm.api.ext.activity.ActivityBehavior;
import com.seeyon.bpm.api.ext.activity.ActivityBehaviorChain;
import com.seeyon.bpm.api.ext.activity.BpmSupportOperation;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DemoSPIActivityBehavior implements ActivityBehavior {
public String getConfigId() {
return "demospiactivity";
}
/**
*
* @param bpmSupportOperation BPM引擎交互接口
* @param activityBehaviorChain 行为执行链
* @return true需要向下穿透,fase不需要
*/
public boolean preMatch(BpmSupportOperation bpmSupportOperation, ActivityBehaviorChain activityBehaviorChain) {
log.error("这里是预提交:{}", bpmSupportOperation.getCaseId());
return true;
}
/**
*
* @param bpmSupportOperation BPM引擎交互接口
* @param activityBehaviorChain 行为执行链
* @return true表示节点有人处理,false表示接待没有人处理
*/
public boolean onActivityReady(BpmSupportOperation bpmSupportOperation, ActivityBehaviorChain activityBehaviorChain) {
log.error("这里节点激活了:{}", bpmSupportOperation.getCaseId());
return false;
}
public boolean onActivityFinish(BpmSupportOperation bpmSupportOperation, ActivityBehaviorChain activityBehaviorChain) {
log.error("这里节点处理完了:{}", bpmSupportOperation.getCaseId());
return false;
}
public boolean onActivityCanceled(BpmSupportOperation bpmSupportOperation, ActivityBehaviorChain activityBehaviorChain) {
log.error("这里节点撤销、回退、取回:{}", bpmSupportOperation.getCaseId());
return false;
}
public boolean validateActivityAction(BpmSupportOperation bpmSupportOperation, ActivityBehaviorChain activityBehaviorChain) {
log.error("保留方法,不实现:{}", bpmSupportOperation.getCaseId());
return false;
}
public int compareTo(Object o) {
return 0;
}
}
# com.seeyon.bpm.api.ext.activity.ActivityBehavior接口说明
| 方法名称 | 方法用途说明 |
|---|---|
| getConfigId | 行为实现类对应的自定义节点ID,这里这个ID需要跟第一步中DemoActivity.json定义的ID匹配,并且需要与com.seeyon.bpm.api.ext.activity.ActivityBehavior.getConfigId返回值匹配 |
| preMatch | 流程流转前,预提交的处理方法,一般做一些人员匹配等逻辑,用以onActivityReady节点激活的时候使用 |
| onActivityReady | 当节点激活的时候,会调用该方法,用以修改节点状态、生成待办等逻辑 |
| onActivityFinish | 节点完成,准备激活下一个节点调用的方法 |
| onActivityCanceled | 节点取消是调用的方法,录入撤销、回退、取回会调用 |
| validateActivityAction | 该方法是保留方法,三方扩展不做实现 |
其中,接口方法中的com.seeyon.bpm.api.ext.activity.ActivityBehaviorChain类型参数,暂时不用,我们需要重点关注的是com.seeyon.bpm.api.ext.activity.BpmSupportOperation这个类型的入参,其中定义了自定义节点可以访问的数据以及可以操作的数据,说明如下:
#####数据获取接口:
| 接口名称 | 说明 |
|---|---|
| getConfigId | 获取当前交互接口操作的节点类型Id |
| getParameters | 获取当前当前流程操作的流程列表 |
| getConfigurationValue | 获取自定义节点,在流程设计态时,由设计人员设置的所有节点自定义参数值 |
| getAllConfigurationValues | 获取自定义节点,在流程设计态时,由设计人员设置的所有自定义节点参数值 |
| getCaseId | 获取当前流程实例ID |
| getActivityId | 获取当前操作的节点ID |
| getActivityPolicyId | 获取当前节点操作权限ID |
| getAppName | 流程类别标识:协同、表单、公文、信息报送(政务扩展)等(可根据业务模块扩展) |
| getTemplateId | 获取模板ID |
| getFormRecordId | 获取表单记录ID |
| getRootEntityName | 获取流程的根实体ID |
| getApplicationName | 获取应用名称 |
| getSubject | 获取当前流程标题 |
| getStartUserId | 获取当前用户ID |
| getCurrentUserId | 获取流程发起者用户ID |
#####数据修改接口:
| 接口名称 | 说明 |
|---|---|
| setParameter | 设置一个流程参数,其中输入参数为(String name, Object value),name为参数名称,value为参数值 |
# 2.1.4、定义自定义节点json文件
这里我们在resources目录下面创建一个config文件夹,并在其中创建一个DemoSpiActivity.json的json文件
#####文件位置:
#####其内容如下:
{
"configId": "demospiactivity",
"ruleName": "SPIDEMO节点",
"icon": "levelapproval",
"addNodePage": {
"componentType": "NodeProperty"
},
"settings": [{
"children": [{
"name": "name",
"caption": "名称",
"componentType": "Input"
}]
}]
}
# 其中json定义中的相关参数说明// todo 这里的JSON文件描述,需要全量的描述 :
| 参数 | 名称 | 说明 | 备注 |
|---|---|---|---|
| configId | 配置ID | 节点配置唯一标识 | 整个系统用于唯一标识一个自定义节点定义的ID,不能重复,如果重复系统启动会提示报错 |
| ruleName | 节点名称 | 节点在设计器中显示的名称 | 名称定义支持国际化,需要在bpm内部的i18n文件中实现定义,外部扩展包暂不支持自定义 |
| icon | 节点图标 | 节点在设计器中的显示图标 | 【待优化】该icon需要在bpm内部前端预先定义 |
| addNodePage | 设置页面弹窗 | 直接填写NodeProperty | 直接填写NodeProperty |
| settings | 节点属性列表 | 定义节点的部分参数信息 | 如:节点名称、节点code、或者一些其他的自定义属性 |
| settings[n].children | 节点第n个属性设置 | 节点第n个属性设置 | 定义每个属性的详细配置 |
| settings[n].children[m].name | 属性名称 | 属性的参数名称,用于取值 | 属性的参数名称,用于取值 |
| settings[n].children[m].caption | 属性的显示名称 | 属性显示在设置页面的名称 | 属性显示在设置页面的名称 |
| settings[n].children[m].componentType | 属性组件类型 | 该组件类型由BPM预先内置,不能自定义 | 如:文本框(Input)、节点参与者(SelectNodeHandlerNew)、单选(Select)等 |
# 2.1.5、定义SPI描述文件
基于V8平台统一的SPI集成机制,我们在工程resources目录下面创建META-INF目录,并创建文件spring.factories。
#####文件位置:
#####内容如下:
com.seeyon.bpm.api.ext.activity.ActivityBehaviorFactory=com.seeyon.bpm.domain.model.business.behavior.demo.DemoSpiActivityBehaviorFactoryImpl
# 2.1.6、将工程打包

# 2.2、开始集成
依据V8平台SPI统一集成规则,可以将2.1中制作的jar上传到maven仓库,或者oss,亦或者直接上传到bpm容器进行本地集成,然后配置bpm的nacos文件,配置形式如下: application.yaml
seeyon:
spi:
enable: true # 是否启用
spi-plugins:
- maven:com.seeyon,xxx-spi-providers,1.0.0 # 定义SPI接口实现的jar包maven GAV坐标,格式:maven:group,artifactId,version
- file:/var/spi/demo-order/xxx.jar # 定义SPI接口实现的jar包的存放路径,格式:file:jar包的文件路径(window路径目录之间也是用/连接)
# 2.3、设计态验证集成效果&运行态验证
配置2.2步骤后,我们可以到bpm后台设计态中,"SPIDEMO节点"会自动添加到"人工节点"列表下面,效果如下:

# 设计态配置流程图:

# 发布应用后运行态发送
后台日志:
发送后,待办查看流程图:
至此,我们完成了一个简单的自定义节点的开发工作。