Java插件微框架【pf4j】入门

一起养成写作习惯!这是我参与「掘金日新计划 · 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>
复制代码

image.png

rule-api模块

rule-api,该模块用来同一插件模块的规范,其中定义一个接口,所有的插件均需要实现该接口,重写对应方法实现具体的逻辑。

image.png

步骤:

  1. 定义一个接口,继承ExtensionPoint接口
  2. 打包,提供给其它模块
/**
 * 规则接口
 *
 * @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包即可。 image.png 步骤:

  1. pom文件引入rule-api
  2. 实现 RuleApi 接口,实现具体规则方法
  3. 在类上加上注解 @Extension,申明该类是一个扩展的插件类
  4. 打成Jar包,这里需要注意的是打包时需要定义好Plugin-idPlugin-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包,执行处理逻辑。

image.png

步骤:

  1. pom文件引入rule-api
  2. 加载所需的插件
  3. 执行方法
  4. 返回结果
<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);
    }
}
复制代码

效果

基础的功能到这里就基本实现了,在图片中我们可以看到加载的效果,控制台中打印出来了扩展类实现的逻辑。

image.png

插件包扩展

上面加载插件包后,得到的是一个集合,那么这里就表示该插件包可以有多个扩展类。那么我们是否可以通过类名来区分开不同的逻辑呢?试试看吧~

rule-plugins

在原先的基础上,新增多一个扩展类。

image.png

/**
 * 规则具体的实现
 *
 * @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试试效果吧!

image.png

通过结果可以看到,确实所有扩展的类都执行了其相关逻辑。

其它

pf4j还有许多其它的功能,例如生命周期,spring支持等等,由于摸鱼时间有限,今天只能先说到这,挖个坑。对这个框架感兴趣的小伙伴也可以了解下其它的功能~~~

猜你喜欢

转载自juejin.im/post/7083758092269617183