@@ -24,24 +24,44 @@ smart-mqtt 企业版的几乎每项特性都是一个插件,并且插件与插
2424
2525插件,在 smart-mqtt 中的侵入性是非常低的。如果结合代码的话,你应该能在几分钟内完全掌握它的精髓。
2626
27- ![ 插件启动流程] ( ./img/plugin_start.png )
27+ ``` mermaid
28+ sequenceDiagram
29+ participant Broker as Broker启动器
30+ participant SL as ServiceLoader
31+ participant Plugins as 插件集合
32+ participant P as 具体插件
33+
34+ Broker->>SL: 加载 classpath 中的所有插件
35+ SL->>Plugins: 发现并注册插件实例
36+ loop 按优先级排序
37+ Broker->>Plugins: 获取插件列表
38+ Plugins-->>Broker: 返回排序后的插件
39+ end
40+ loop 依次安装
41+ Broker->>P: 调用 install(context)
42+ P->>P: 执行 initPlugin()<br/>插件初始化逻辑
43+ P-->>Broker: 安装完成
44+ end
45+ Broker->>Broker: 启动 Broker 服务
46+ ```
2847
2948上图为 smart-mqtt 服务启动的完整流程,插件处于其中间环节。插件的启动分为两个步骤:
3049
31501 . 通过 ` ServiceLoader ` 的方式加载 ` classpath ` 内的所有插件实例
32512 . 按插件的优先级进行排序,再执行 ` install ` 方法安装启用插件
3352
3453``` java
35- private void loadAndInstallPlugins() {
36- for (Plugin plugin : ServiceLoader . load(Plugin . class, Providers . class. getClassLoader())) {
37- LOGGER . info (" load plugin: " + plugin. pluginName());
54+ private void loadAndInstallPlugins() throws Throwable {
55+ for (Plugin plugin : ServiceLoader . load(Plugin . class, BrokerContextImpl . class. getClassLoader())) {
56+ System . out . println (" load plugin: " + plugin. pluginName());
3857 plugins. add(plugin);
3958 }
4059 // 安装插件
41- plugins. stream(). sorted(Comparator . comparingInt(Plugin :: order)). forEach(plugin - > {
42- LOGGER . info(" install plugin: " + plugin. pluginName());
60+ plugins. sort(Comparator . comparingInt(Plugin :: order));
61+ for (Plugin plugin : plugins) {
62+ System . out. println(" install plugin: " + plugin. pluginName());
4363 plugin. install(this );
44- });
64+ }
4565}
4666```
4767
@@ -53,9 +73,23 @@ private void loadAndInstallPlugins() {
5373
5474卸载插件,是 smart-mqtt Broker 停止服务的一个必经过程,以此保证服务的优雅退出和资源的充分释放。
5575
56- ![ 插件退出流程] ( ./img/plugin_stop.png )
76+ ``` mermaid
77+ sequenceDiagram
78+ participant Broker as Broker容器
79+ participant Plugins as 插件列表
80+ participant P as 具体插件
81+
82+ Broker->>Broker: 停止接收新连接
83+ loop 逆序遍历卸载
84+ Broker->>P: 调用 uninstall()
85+ P->>P: 执行 destroyPlugin()<br/>资源释放逻辑
86+ P-->>Broker: 卸载完成
87+ end
88+ Broker->>Plugins: clear()
89+ Broker->>Broker: 销毁 Broker 服务
90+ ```
5791
58- 实现的代码也仅仅只有2行 :
92+ 实现的代码如下 :
5993
6094``` java
6195plugins. forEach(Plugin :: uninstall);
@@ -79,7 +113,7 @@ plugins.clear();
79113 <dependency >
80114 <groupId >org.smartboot.mqtt</groupId >
81115 <artifactId >smart-mqtt-broker</artifactId >
82- <version >1.4 .0</version >
116+ <version >1.5 .0</version >
83117 </dependency >
84118</dependencies >
85119
@@ -109,7 +143,7 @@ plugins.clear();
109143 <transformers >
110144 <!-- 采用追加的方式 -->
111145 <transformer implementation =" org.apache.maven.plugins.shade.resource.AppendingTransformer" >
112- <resource >META-INF/services/org .smartboot.mqtt.broker. plugin.Plugin</resource >
146+ <resource >META-INF/services/tech .smartboot.mqtt.plugin.spec .Plugin</resource >
113147 </transformer >
114148 </transformers >
115149 </configuration >
@@ -126,7 +160,7 @@ plugins.clear();
126160
127161### 3. 编写插件代码
128162
129- 在 ` resources/META-INF/services ` 目录下创建名为 ` org .smartboot.mqtt.broker. plugin.Plugin` 的文件,内容为插件实现类的全限定名。
163+ 在 ` resources/META-INF/services ` 目录下创建名为 ` tech .smartboot.mqtt.plugin.spec .Plugin` 的文件,内容为插件实现类的全限定名。
130164
131165```
132166tech.smartboot.mqtt.plugin.demo.DemoPlugin
@@ -137,30 +171,41 @@ tech.smartboot.mqtt.plugin.demo.DemoPlugin
137171``` java
138172package tech.smartboot.mqtt.plugin.demo ;
139173
140- import org.smartboot.mqtt.broker.BrokerContext ;
141- import org.smartboot.mqtt.broker.plugin.Plugin ;
174+ import tech.smartboot.mqtt.plugin.spec.BrokerContext ;
175+ import tech.smartboot.mqtt.plugin.spec.Options ;
176+ import tech.smartboot.mqtt.plugin.spec.Plugin ;
142177
143178public class DemoPlugin extends Plugin {
144-
179+
145180 @Override
146- public void install (BrokerContext brokerContext ) {
147- System . out. println(" DemoPlugin installed !" );
181+ protected void initPlugin (BrokerContext brokerContext ) throws Throwable {
182+ System . out. println(" DemoPlugin initialized !" );
148183 // 在这里编写插件初始化逻辑
149184 // 例如:订阅事件、注册服务、启动线程等
150185 }
151-
186+
152187 @Override
153- public void uninstall () {
154- System . out. println(" DemoPlugin uninstalled !" );
188+ protected void destroyPlugin () {
189+ System . out. println(" DemoPlugin destroyed !" );
155190 // 在这里编写插件卸载逻辑
156191 // 例如:释放资源、停止线程等
157192 }
158-
193+
159194 @Override
160195 public String pluginName () {
161196 return " DemoPlugin" ;
162197 }
163-
198+
199+ @Override
200+ public String getVersion () {
201+ return " 1.0.0" ;
202+ }
203+
204+ @Override
205+ public String getVendor () {
206+ return " Your Company" ;
207+ }
208+
164209 @Override
165210 public int order () {
166211 // 插件加载顺序,值越小优先级越高
@@ -169,6 +214,12 @@ public class DemoPlugin extends Plugin {
169214}
170215```
171216
217+ :::tip[ 提示]
218+ - ` install() ` 和 ` uninstall() ` 方法是 ` final ` 的,子类不能重写。
219+ - 需要在 ` initPlugin() ` 中编写初始化逻辑,在 ` destroyPlugin() ` 中编写资源释放逻辑。
220+ - ` getVersion() ` 和 ` getVendor() ` 是抽象方法,必须实现。
221+ :::
222+
172223### 4. 打包与部署
173224
174225运行 ` mvn clean package ` 打包插件,将生成的 jar 文件放入 smart-mqtt 的 ` plugins ` 目录下,重启服务即可生效。
@@ -181,7 +232,7 @@ public class DemoPlugin extends Plugin {
181232
182233``` java
183234@Override
184- public void install (BrokerContext brokerContext) {
235+ protected void initPlugin (BrokerContext brokerContext) {
185236 brokerContext. getProviders(). setAuthenticationValidator((client, username, password) - > {
186237 // 自定义认证逻辑
187238 return " admin" . equals(username) && " 123456" . equals(password);
@@ -195,7 +246,7 @@ public void install(BrokerContext brokerContext) {
195246
196247``` java
197248@Override
198- public void install (BrokerContext brokerContext) {
249+ protected void initPlugin (BrokerContext brokerContext) {
199250 // 订阅消息接收事件
200251 brokerContext. getEventBus(). subscribe(EventType . RECEIVE_PUBLISH_MESSAGE , event - > {
201252 MqttPublishMessage message = event. getObject();
@@ -210,7 +261,7 @@ public void install(BrokerContext brokerContext) {
210261
211262``` java
212263@Override
213- public void install (BrokerContext brokerContext) {
264+ protected void initPlugin (BrokerContext brokerContext) {
214265 // 定时上报指标
215266 ScheduledExecutorService scheduler = Executors . newSingleThreadScheduledExecutor();
216267 scheduler. scheduleAtFixedRate(() - > {
@@ -219,13 +270,39 @@ public void install(BrokerContext brokerContext) {
219270}
220271```
221272
273+ ## 插件配置
274+
275+ 插件支持通过 ` plugin.yaml ` 文件进行配置,放置在插件的存储目录中。
276+
277+ ``` java
278+ @Override
279+ protected void initPlugin(BrokerContext brokerContext) throws Throwable {
280+ // 加载插件配置
281+ PluginConfig config = loadPluginConfig(PluginConfig . class);
282+ if (config != null ) {
283+ System . out. println(" Server URL: " + config. getServerUrl());
284+ }
285+ }
286+ ```
287+
288+ 配置类定义:
289+
290+ ``` java
291+ public class PluginConfig {
292+ private String serverUrl;
293+ private int timeout;
294+ // getter/setter
295+ }
296+ ```
297+
222298## 最佳实践
223299
2243001 . ** 插件职责单一** :每个插件只负责一个明确的功能
2253012 . ** 正确处理异常** :插件中的异常不应影响 Broker 的正常运行
226- 3 . ** 资源及时释放** :在 ` uninstall ` 方法中释放所有资源
302+ 3 . ** 资源及时释放** :在 ` destroyPlugin() ` 方法中释放所有资源
2273034 . ** 配置外部化** :将可变参数提取到配置文件中
2283045 . ** 日志规范** :使用统一的日志框架,避免直接打印到控制台
305+ 6 . ** 版本管理** :合理实现 ` getVersion() ` 方法,便于插件版本追踪
229306
230307## 参考插件
231308
@@ -235,5 +312,7 @@ smart-mqtt 官方提供了多个参考插件:
235312- ** redis-bridge-plugin** :MQTT 消息与 Redis 集成
236313- ** websocket-plugin** :WebSocket 连接支持
237314- ** memory-session-plugin** :内存会话状态管理
315+ - ** cluster-plugin** :集群功能支持
316+ - ** enterprise-plugin** :企业版功能插件
238317
239- 你可以在 [ Gitee 仓库] ( https://gitee.com/smartboot/smart-mqtt/tree/master/plugins ) 查看这些插件的源码。
318+ 你可以在 [ Gitee 仓库] ( https://gitee.com/smartboot/smart-mqtt/tree/master/plugins ) 查看这些插件的源码。
0 commit comments