一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
前言
前阵子因为工作的缘故,需要开发到一些插件式的功能,于是有了这一篇文字《 浅尝Java动态加载Jar包(一)》。本来想更新多一篇动态生成Spring Bean相关的文章,结果评论区有大佬推荐了一个Java插件式相关的框架,使用起来感觉确实很方便,于是便把原先的计划无情的抛弃掉了~~~~
项目工程结构
├── rule 规则父模块
├── rule-api 规则定义接口
├── rule-plugins 规则插件Jar
└── rule-service 规则服务
复制代码
事前准备
俗话说工欲利其事,必先利其器!这里我们根据上面的结构先将项目地基建立起来。
rule模块
新建一个工程,在其下面建立三个子工程,同事pom.xml
中引入我们的主角pf4j.
<dependencies>
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
复制代码
rule-api模块
rule-api,该模块用来同一插件模块的规范,其中定义一个接口,所有的插件均需要实现该接口,重写对应方法实现具体的逻辑。
步骤:
- 定义一个接口,继承
ExtensionPoint
接口 - 打包,提供给其它模块
/**
* 规则接口
*
* @author unidentifiable
* @date 2022/4/7 14:36
*/
public interface RuleApi extends ExtensionPoint {
/**
* 规则实现方法
*
* @param param 入参
* @return String
* @author unidentifiable
* @date 2022/4/7 14:37
*/
String ruleImplementationMethod(String param);
}
复制代码
接口定义完成之后,打包提供给其它模块引用即可。
rule-plugins
rule-plugins,插件模块,该模块需要实现rule-api定义的接口,实现具体逻辑后将其打包成jar
包即可。 步骤:
pom
文件引入rule-api- 实现
RuleApi
接口,实现具体规则方法 - 在类上加上注解 @Extension,申明该类是一个扩展的插件类
- 打成
Jar
包,这里需要注意的是打包时需要定义好Plugin-id
和Plugin-Version
<dependencies>
<dependency>
<groupId>com.unidentifiable</groupId>
<artifactId>rule-api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifestEntries>
<Plugin-Id>rule-plugin</Plugin-Id>
<Plugin-Version>1.0</Plugin-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
复制代码
/**
* 规则具体的实现
*
* @author unidentifiable
* @date 2022/4/7
*/
@Extension
public class RulePlugin implements RuleApi{
/**
* 规则实现
*
* @param param 入参
* @return String
* @author unidentifiable
* @date 2022/4/7 14:44
*/
@Override
public String ruleImplementationMethod(String param) {
return "(" + System.currentTimeMillis() + ")接收到参数:{" + param + "}";
}
}
复制代码
rule-service
rule-service,业务模块,接收到请求后,加载前面写好的Jar
包,执行处理逻辑。
步骤:
pom
文件引入rule-api- 加载所需的插件
- 执行方法
- 返回结果
<dependencies>
<dependency>
<groupId>com.unidentifiable</groupId>
<artifactId>rule-api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
复制代码
/**
* @author unidentifiable
* @date 2022/4/7
*/
public class RuleService {
public static void main(String[] args) {
// 插件ID
String plugin = "rule-plugin";
// 创建插件管理对象
JarPluginManager pluginManager = new JarPluginManager();
// 加载插件包
pluginManager.loadPlugin(Paths.get("F:\demo\rule\rule-plugins\target\rule-plugins-1.0.jar"));
// 启动指定的插件及其依赖项
pluginManager.startPlugin(plugin);
// 得到插件中定义的扩展类集合
List<RuleApi> extensions = pluginManager.getExtensions(RuleApi.class);
for (RuleApi ruleApi : extensions) {
// 执行方法
System.out.println(ruleApi.ruleImplementationMethod("测试插件"));
}
// 停用插件
pluginManager.stopPlugin(plugin);
// 卸载插件包
pluginManager.unloadPlugin(plugin);
}
}
复制代码
效果
基础的功能到这里就基本实现了,在图片中我们可以看到加载的效果,控制台中打印出来了扩展类实现的逻辑。
插件包扩展
上面加载插件包后,得到的是一个集合,那么这里就表示该插件包可以有多个扩展类。那么我们是否可以通过类名来区分开不同的逻辑呢?试试看吧~
rule-plugins
在原先的基础上,新增多一个扩展类。
/**
* 规则具体的实现
*
* @author unidentifiable
* @date 2022/4/7
*/
@Extension
public class RulePlugin2 implements RuleApi{
/**
* 规则实现
*
* @param param 入参
* @return String
* @author unidentifiable
* @date 2022/4/7 14:44
*/
@Override
public String ruleImplementationMethod(String param) {
return "*****这里是新增的扩展类*****";
}
}
复制代码
将其重写打包后,再通过rule-service试试效果吧!
通过结果可以看到,确实所有扩展的类都执行了其相关逻辑。
其它
pf4j还有许多其它的功能,例如生命周期,spring
支持等等,由于摸鱼时间有限,今天只能先说到这,挖个坑。对这个框架感兴趣的小伙伴也可以了解下其它的功能~~~