当前位置: 首页 > news >正文

PF4J+SpringBoot

plugin-common

pom.xml相关配置

<groupId>pub.qingyun</groupId>
<artifactId>plugin-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>插件配置类</description><dependency><groupId>org.pf4j</groupId><artifactId>pf4j</artifactId><version>3.12.0</version>
</dependency><!--插件打包时使用的Maven插件,插件ID:Plugin-Id,使用mvn clean package 打出*jar-with-dependencies.jar的插件包-->
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><configuration><archive><manifest><addClasspath>true</addClasspath></manifest><manifestEntries><Plugin-Id>common-impl</Plugin-Id><Plugin-Version>0.0.1</Plugin-Version></manifestEntries></archive><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins>
</build>

插件服务接口

pub.qingyun.service.IExtensionHandler

public interface IExtensionHandler extends Runnable, ExtensionPoint {String execute(String param);
}

实现类

import org.pf4j.Extension;
import pub.qingyun.service.IExtensionHandler;@Extension
public class TestExtensionHandler implements IExtensionHandler {@Overridepublic void run() {System.out.println("TestExtensionHandler run...");}@Overridepublic String execute(String param) {System.out.println("TestExtensionHandler.execute...param=" + param);return param;}
}

plugin-spring-boot

pom.xml相关配置

<groupId>pub.qingyun</groupId>
<artifactId>plugin-spring-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>plugin-spring-boot</name>
<description>plugin-spring-boot</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>pub.qingyun</groupId><artifactId>plugin-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>...
</dependencies>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

spring-boot

@Configuration
public class PluginConfig {// 插件目录,对应插件jar包/zip@Value("${pf4j.pluginPath}")private String pf4jPluginPath;@Beanpublic PluginManager initPluginManager() {Path pluginPath = Paths.get(pf4jPluginPath);PluginManager pluginManager = new JarPluginManager(pluginPath);//加载所有插件pluginManager.loadPlugins();//开启所有插件pluginManager.startPlugins();//启动指定插件
//        pluginManager.startPlugin("demo-plugin");//卸载插件
//        pluginManager.unloadPlugin("demo-plugin");return pluginManager;}
}

控制层实现

package pub.qingyun.controller;import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginManager;
import org.pf4j.PluginState;
import org.pf4j.PluginWrapper;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import pub.qingyun.service.impl.TestExtensionHandler;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** @author CQY* @version 1.0* @date 2024/7/17 14:19**/
@Slf4j
@RestController
public class PluginController {@Resourceprivate PluginManager pluginManager;/*** 打印所有插件信息** @return List<Map < String, Object>>*/@GetMapping(value = "/printAllPlugin")public ResponseEntity<List<Map<String, Object>>> printAllPlugin() {List<PluginWrapper> plugins = pluginManager.getPlugins();List<Map<String, Object>> collect = plugins.stream().map((item) -> {Map<String, Object> map = new HashMap<>();map.put("pluginId", item.getPluginId());map.put("pluginDescription", item.getDescriptor());map.put("pluginPath", item.getPluginPath());map.put("pluginState", item.getPluginState());map.put("pluginClassLoader", item.getPluginClassLoader());return map;}).collect(Collectors.toList());return ResponseEntity.ok(collect);}/*** 启动插件** @param pluginId 插件id* @return PluginState*/@GetMapping(value = "/startPluginById")public ResponseEntity<String> startPluginById(String pluginId) {PluginState pluginState = pluginManager.startPlugin(pluginId);return ResponseEntity.ok(pluginState.toString());}/*** 停止插件** @param pluginId 插件id* @return PluginState*/@GetMapping(value = "/stopPluginById")public ResponseEntity<String> stopPluginById(String pluginId) {PluginState pluginState = pluginManager.stopPlugin(pluginId);return ResponseEntity.ok(pluginState.toString());}/*** 禁用插件** @param pluginId 插件id* @return boolean true表示成功*/@GetMapping(value = "/disablePluginById")public ResponseEntity<Boolean> disablePluginById(String pluginId) {boolean result = pluginManager.disablePlugin(pluginId);return ResponseEntity.ok(result);}/*** 启用插件** @param pluginId 插件id* @return boolean true表示成功*/@GetMapping(value = "/enablePluginById")public ResponseEntity<Boolean> enablePluginById(String pluginId) {boolean result = pluginManager.enablePlugin(pluginId);return ResponseEntity.ok(result);}/*** 卸载插件** @param pluginId 插件id* @return boolean true表示成功*/@GetMapping(value = "/unloadPluginById")public ResponseEntity<Boolean> unloadPluginById(String pluginId) {boolean result = pluginManager.unloadPlugin(pluginId);return ResponseEntity.ok(result);}/*** 加载插件** @return String*/@GetMapping(value = "/loadPlugins")public ResponseEntity<String> loadPlugins() {pluginManager.loadPlugins();//开启所有插件pluginManager.startPlugins();return ResponseEntity.ok("SUCCESS");}/*** 执行插件中的扩展点** @param pluginId 插件id* @return String 执行结果*/@GetMapping(value = "/executePluginExtensionHandlerById")public ResponseEntity<String> executePluginExtensionHandlerById(String pluginId) {List<Class<?>> extensionClasses = pluginManager.getExtensionClasses(pluginId);for (Class<?> extensionClass : extensionClasses) {if (extensionClass.getName().equals("pub.qingyun.service.impl.TestExtensionHandler")) {try {Class<?> clz = Class.forName("pub.qingyun.service.impl.TestExtensionHandler", true, Thread.currentThread().getContextClassLoader());TestExtensionHandler extensionHandler = (TestExtensionHandler) clz.newInstance();String execute = extensionHandler.execute("hello");extensionHandler.run();} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {throw new RuntimeException(e);}}}return ResponseEntity.ok("SUCCESS");}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Vscode中Github copilot插件无法使用(出现感叹号)解决方案
  • Vite的WebSocket
  • python的tkinter、socket库开发tcp的客户端和服务端
  • 智慧博物馆的“眼睛”:视频智能监控技术守护文物安全与智能化管理
  • 详细解析Kafaka Streams中各个DSL操作符的用法
  • Hive第三天
  • 单例模式 饿汉式和懒汉式的区别
  • 推荐一款处理TCP数据的架构--EasyTcp4Net
  • JavaScript:移除元素
  • 基于STM32设计的智能门锁(微信小程序+手机APP等多种方式开锁)(188)
  • yarn的安装和配置以及更新总结,npm的对照使用差异
  • 2024最新Cloudways主机使用教程(含最新Cloudways折扣码)
  • adb命令操作手机各种开关
  • 题解:小S与机房里的电脑 Computer_C++算法竞赛_贪心_二分答案_模拟_数据结构
  • 分布式IO系统2通道串口通信模块M602x
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • Apache的基本使用
  • ECMAScript入门(七)--Module语法
  • extjs4学习之配置
  • jquery cookie
  • JS变量作用域
  • Odoo domain写法及运用
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • Service Worker
  • Shell编程
  • Vue.js-Day01
  • Web Storage相关
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 离散点最小(凸)包围边界查找
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 入口文件开始,分析Vue源码实现
  • 深度学习中的信息论知识详解
  • 温故知新之javascript面向对象
  • 原生Ajax
  • 数据库巡检项
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • # 达梦数据库知识点
  • #162 (Div. 2)
  • #Linux(帮助手册)
  • #在 README.md 中生成项目目录结构
  • $nextTick的使用场景介绍
  • (leetcode学习)236. 二叉树的最近公共祖先
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (二)丶RabbitMQ的六大核心
  • (二十六)Java 数据结构
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转)树状数组
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .Net7 环境安装配置