本文档介绍如何通过ExcelParsePlugin
示例来开发一个自定义插件。该插件演示了如何解析Excel文件并处理其中的数据。
插件必须继承BaseTaskPlugin
基类并使用@Extension
注解标记。如示例中的:
@Setter
@Extension
@JsonSchemaDefinition(
title = "Excel解析节点",
description = "解析Excel文件并以列表形式输出数据,支持指定表头行"
)
public class ExcelParsePlugin extends BaseTaskPlugin {
// 插件内容
}
使用@JsonSchemaProperty
注解定义插件的配置属性:
@JsonSchemaProperty(
title = "Excel文件链接",
description = "需要解析的Excel文件URL链接",
required = true,
example = "https://example.com/sample.xlsx"
)
private String excelUrl;
@JsonSchemaProperty(
title = "表头行号",
description = "指定表头所在的行号(从1开始计数),该行之前的数据将被忽略",
required = true,
example = "2"
)
private Integer headerRowIndex;
@JsonSchemaProperty(
title = "工作表名称",
description = "指定要解析的工作表名称,不指定则默认解析第一个工作表",
required = false,
example = "Sheet1"
)
private String sheetName;
每个属性可以配置:
title
: 属性的显示名称description
: 属性的详细描述required
: 是否必填example
: 示例值
为插件定义规范的输出模型,例如我们的示例中定义了两个类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelParseResult {
/**
* 解析状态信息
*/
private String message;
/**
* 表头列表
*/
private List<String> headers;
/**
* 数据列表,每一行是一个Map,键为表头,值为单元格内容
*/
private List<Map<String, Object>> dataList;
/**
* 格式化后的数据项列表
*/
private List<ExcelItem> items;
/**
* 构造函数
* @param message 状态信息
*/
public ExcelParseResult(String message) {
this.message = message;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelItem {
/**
* 序号
*/
private Integer serialNumber;
/**
* 采购日期
*/
private String purchaseDate;
/**
* 物品名称
*/
private String itemName;
// 更多字段...
}
覆盖getName()
方法定义插件唯一标识:
@Override
public String getName() {
return "task-dynamic-excel-parse";
}
使用@Execute
注解定义插件的执行方法:
@Execute(
description = "执行Excel解析操作",
outputClass = ExcelParseResult.class
)
public ExcelParseResult run() {
try {
// 1. 下载Excel文件
URL url = new URL(excelUrl);
try (InputStream inputStream = url.openStream()) {
// 2. 创建工作簿
Workbook workbook = new XSSFWorkbook(inputStream);
// 3. 获取工作表
Sheet sheet = getTargetSheet(workbook);
// 4. 解析表头和数据
List<String> headers = parseHeaders(sheet);
List<Map<String, Object>> dataList = parseData(sheet, headers);
// 5. 转换为结构化对象
List<ExcelItem> items = convertToExcelItems(dataList);
// 6. 记录日志并返回结果
executeLogs.add(Log.success("成功解析Excel文件,共解析" + dataList.size() + "行数据"));
ExcelParseResult result = new ExcelParseResult();
result.setMessage("解析成功");
result.setHeaders(headers);
result.setDataList(dataList);
result.setItems(items);
return result;
}
} catch (Exception e) {
executeLogs.add(Log.failure("解析Excel文件失败: " + e.getMessage()));
return new ExcelParseResult("解析Excel文件失败: " + e.getMessage());
}
}
插件中可以使用executeLogs
记录执行日志:
executeLogs.add(Log.success("成功解析Excel文件,共解析" + dataList.size() + "行数据"));
// 或
executeLogs.add(Log.failure("解析Excel文件失败: " + e.getMessage()));
确保插件能够优雅地处理各种异常情况:
try {
// 业务逻辑
} catch (Exception e) {
// 记录错误日志
executeLogs.add(Log.failure("发生错误: " + e.getMessage()));
// 返回错误结果
return new ExcelParseResult("发生错误: " + e.getMessage());
}
一个完整的插件项目通常包含以下结构:
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── company/
│ │ └── plugin/
│ │ ├── MyPlugin.java // 主插件类
│ │ ├── service/ // 服务层
│ │ │ └── BusinessService.java
│ │ └── vo/ // 值对象
│ │ ├── InputModel.java // 输入模型
│ │ └── ResultModel.java // 结果模型
│ └── resources/
│ └── META-INF/
│ └── extensions.idx // 插件扩展点索引
└── test/ // 单元测试
└── java/
└── com/
└── company/
└── plugin/
└── MyPluginTest.java
本项目已配置GitHub Actions用于自动构建,配置文件位于.github/workflows/maven-build.yml
。每当代码推送到主分支或创建Pull Request时,会自动触发构建流程:
name: Maven构建
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
workflow_dispatch: # 允许手动触发
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v2
- name: 设置JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: 使用Maven构建
run: mvn -B package --file pom.xml
- name: 上传构建产物
uses: actions/upload-artifact@v2
with:
name: plugin-jar
path: target/*.jar
retention-days: 5
- 将代码推送到GitHub仓库
- GitHub Actions会自动执行构建
- 构建完成后,可在Actions页面下载构建产物
- 将下载的JAR包部署到您的插件平台
您也可以在GitHub仓库的Actions页面手动触发构建流程:
- 进入您的GitHub仓库
- 点击"Actions"选项卡
- 选择"Maven构建"工作流
- 点击"Run workflow"按钮
- 选择分支并确认运行
- 编译插件项目
- 将编译后的JAR包放入平台的插件目录
- 重启服务或触发插件热加载
- 在工作流编辑器中使用该插件
ExcelParsePlugin
示例实现了以下功能:
- 从URL下载Excel文件
- 根据配置选择工作表
- 解析表头和数据行
- 处理不同类型的单元格值(文本、数字、日期等)
- 将解析结果转换为结构化对象
- 记录执行日志并返回结果
private Sheet getTargetSheet(Workbook workbook) {
if (sheetName != null && !sheetName.trim().isEmpty()) {
Sheet sheet = workbook.getSheet(sheetName);
if (sheet == null) {
executeLogs.add(Log.failure("找不到名为 '" + sheetName + "' 的工作表"));
throw new RuntimeException("找不到名为 '" + sheetName + "' 的工作表");
}
return sheet;
} else {
return workbook.getSheetAt(0);
}
}
private Object getCellValue(Cell cell) {
if (cell == null) return null;
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getLocalDateTimeCellValue().toLocalDate();
} else {
double value = cell.getNumericCellValue();
// 如果是整数,返回整数类型
if (value == Math.floor(value)) {
return (long) value;
}
return value;
}
// 其他类型处理...
}
}
- 为插件提供清晰的描述和属性说明
- 处理各种异常情况,确保插件稳定性
- 提供合适的日志记录,方便排查问题
- 返回结构化数据,便于后续节点处理
- 遵循单一职责原则,每个插件只做一件事
- 添加必要的注释说明复杂逻辑
- 代码模块化,将业务逻辑拆分为多个方法
- 使用VO类规范化数据结构
- 配置自动化构建和测试,确保代码质量
- 插件无法加载:检查插件类上是否添加了
@Extension
注解 - 属性无法配置:检查
@JsonSchemaProperty
注解配置是否正确 - 执行失败:查看日志,确保异常处理正确
- 返回值不正确:确保
@Execute
注解中指定了正确的outputClass
- 自动构建失败:检查GitHub Actions日志,确认Maven配置和依赖是否正确