4、第一个Hello World插件:创建Maven模块、实现基础接口、打包与部署
好,咱们正式开始动手了。
前面几章讲了插件架构、核心接口,说实话都是理论。这一章,咱们真刀真枪地写一个插件出来。我管它叫 HelloWorldPlugin,功能很简单——收到设备上报的数据后,在日志里打印一句 "Hello World"。
别小看这个例子。它麻雀虽小,五脏俱全。你跑通了这个流程,后面写任何业务插件都只是换逻辑而已。
4.1 创建Maven模块
ThingsBoard 本身是用 Maven 管理的多模块项目。我个人习惯,插件代码不要直接塞进主工程里,而是单独建一个模块,方便后续独立维护和升级。
在 ThingsBoard 源码根目录下,创建一个新的 Maven 模块:
thingsboard/
├── application/
├── common/
├── dao/
├── ...
└── extensions/ ← 新建这个目录
└── hello-world/ ← 我们的插件模块
└── pom.xml
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>
<parent>
<groupId>org.thingsboard</groupId>
<artifactId>thingsboard</artifactId>
<version>3.5.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>hello-world-plugin</artifactId>
<packaging>jar</packaging>
<name>Hello World Plugin</name>
<dependencies>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>rule-engine-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
4.2 实现基础接口
插件要干活,至少得实现两个接口:RuleNode 和 RuleNodeConfiguration。说白了,一个告诉框架「我是什么」,一个告诉框架「我怎么配置」。
先写节点类:
@RuleNode(
name = "Hello World",
description = "打印 Hello World 日志",
nodeDescription = "收到消息后打印一条问候语",
configClazz = HelloWorldConfiguration.class,
relationTypes = {"Success", "Failure"}
)
public class HelloWorldNode implements RuleNode {
@Override
public void init(RuleNodeConfiguration configuration) {
// 初始化逻辑,比如读取配置
System.out.println("HelloWorldNode 初始化完成");
}
@Override
public void onMsg(RuleContext ctx, RuleNodeMsg msg) {
try {
// 核心逻辑:打印 Hello World
String deviceName = msg.getMetadata().getValue("deviceName");
System.out.println("Hello World from device: " + deviceName);
// 告诉框架,处理成功
ctx.tellSuccess(msg);
} catch (Exception e) {
// 出错了,走 Failure 分支
ctx.tellFailure(msg, e);
}
}
@Override
public void destroy() {
// 清理资源
System.out.println("HelloWorldNode 销毁");
}
}
再写配置类:
public class HelloWorldConfiguration implements RuleNodeConfiguration {
private String greeting = "Hello";
public String getGreeting() {
return greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
onMsg 方法里一定要调用 ctx.tellSuccess 或 ctx.tellFailure。我曾经见过有人忘了调,结果消息卡在节点里,整个规则链都堵死了。
4.3 打包与部署
代码写完了,接下来就是打包。在 hello-world 目录下执行:
mvn clean package -DskipTests
打包完成后,在 target/ 目录下会生成 hello-world-plugin-3.5.0.jar。
部署分两步:
- 复制 jar 包 到 ThingsBoard 的
extensions/目录下。 - 重启 ThingsBoard 服务,让框架加载新插件。
重启后,在规则链编辑器中,你应该能在节点列表里找到「Hello World」这个节点。拖出来,连上线,保存,然后发一条设备数据试试。
@RuleNode 注解里的 configClazz 写错了类名。这两个坑我都踩过,排查起来很费时间。
4.4 验证与调试
部署成功后,打开 ThingsBoard 的日志文件(一般在 logs/thingsboard.log),你应该能看到类似这样的输出:
2024-01-15 10:23:45.123 INFO [rule-engine] HelloWorldNode 初始化完成
2024-01-15 10:23:45.456 INFO [rule-engine] Hello World from device: 温度传感器A
如果没看到,别慌。先确认规则链是否真的触发了,再检查设备数据是否到达了该节点。我一般会在 onMsg 方法里加一行 System.out.println("收到消息: " + msg.getData()),先确认消息进来了,再排查后续逻辑。
| 步骤 | 操作 | 预期结果 |
|---|---|---|
| 1 | 创建 Maven 模块 | 项目结构完整,pom.xml 无报错 |
| 2 | 实现 RuleNode 接口 | 编译通过,无语法错误 |
| 3 | 打包 | 生成 jar 包,大小在 10KB 左右 |
| 4 | 部署并重启 | 日志显示初始化成功 |
| 5 | 发送测试数据 | 日志打印 Hello World |
嗯,到这里,你的第一个 ThingsBoard 插件就跑通了。虽然功能简单,但整个流程——从创建模块、实现接口、打包部署到验证——你已经完整走了一遍。后面再写复杂的插件,无非是多加几个配置项、多处理几种消息类型而已。
下一章,我会带你写一个真正能用的插件:从 MQTT 主题中提取数据,转换成 ThingsBoard 能识别的格式。到时候你会看到,插件开发的核心其实就两件事——接住消息,然后处理它。