plugin-common
pom.xml相关配置
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
java
public interface IExtensionHandler extends Runnable, ExtensionPoint {
String execute(String param);
}
实现类
java
import org.pf4j.Extension;
import pub.qingyun.service.IExtensionHandler;
@Extension
public class TestExtensionHandler implements IExtensionHandler {
@Override
public void run() {
System.out.println("TestExtensionHandler run...");
}
@Override
public String execute(String param) {
System.out.println("TestExtensionHandler.execute...param=" + param);
return param;
}
}
plugin-spring-boot
pom.xml相关配置
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
java
@Configuration
public class PluginConfig {
// 插件目录,对应插件jar包/zip
@Value("${pf4j.pluginPath}")
private String pf4jPluginPath;
@Bean
public 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;
}
}
控制层实现
java
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 {
@Resource
private 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");
}
}