Getting Started with Java Plug-in Microframework [pf4j]

Get into the habit of writing together! This is the 7th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

foreword

A while ago, because of work, I needed to develop some plug-in functions, so I came up with this article " Tasting Java Dynamically Loading Jar Packages (1) ". I originally wanted to update an article related to dynamically generating Spring Beans . As a result, a big guy in the comment area recommended a Java plug-in related framework, which was really convenient to use, so I ruthlessly abandoned the original plan~~ ~~

Project engineering structure

├── rule 规则父模块
    ├── rule-api 规则定义接口
    ├── rule-plugins 规则插件Jar
    └── rule-service 规则服务
复制代码

a

As the saying goes, if a worker wants to benefit his work, he must first sharpen his tools! Here we first establish the project foundation according to the above structure.

rule module

Create a new project, create three sub-projects under it, pom.xmland introduce our protagonist pf4j .

<dependencies>
    <dependency>
        <groupId>org.pf4j</groupId>
        <artifactId>pf4j</artifactId>
        <version>3.0.1</version>
    </dependency>
</dependencies>
复制代码

image.png

rule-api module

rule-api , this module is used for the specification of the same plug-in module, which defines an interface, all plug-ins need to implement this interface, and rewrite the corresponding method to achieve specific logic.

image.png

step:

  1. Define an interface, inherit the ExtensionPointinterface
  2. packaged and provided to other modules
/**
 * 规则接口
 *
 * @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);
}
复制代码

After the interface definition is completed, it can be packaged and provided to other modules for reference.

rule-plugins

rule-plugins , plug-in module, this module needs to implement the interface defined by rule-api , and package it into a package after implementing the specific logic jar. image.pngstep:

  1. pomFile import rule-api
  2. Implement the RuleApiinterface to implement specific rules and methods
  3. Add the annotation @Extension to the class to declare that the class is an extended plugin class
  4. Packed into a Jarpackage, it should be noted here that you need to define Plugin-idandPlugin-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 , the business module, after receiving the request, loads the previously written Jarpackage and executes the processing logic.

image.png

step:

  1. pomFile import rule-api
  2. Load the required plugins
  3. execution method
  4. return result
<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);
    }
}
复制代码

Effect

The basic functions are basically realized here. In the picture, we can see the effect of loading, and the logic implemented by the extension class is printed out in the console.

image.png

Plugin package extension

After loading the plug-in package above, what is obtained is a collection, then it means that the plug-in package can have multiple extension classes. So can we distinguish different logics by class name? Try it out~

rule-plugins

On the original basis, an additional extension class is added.

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 "*****这里是新增的扩展类*****";
    }
}
复制代码

After rewriting and packaging it, try the effect through rule-service !

image.png

As can be seen from the results, indeed all the extended classes have executed their related logic.

other

pf4j has many other functions, such as life cycle, springsupport, etc. Due to the limited time for fishing, I can only talk about this today and dig a hole. Small partners who are interested in this framework can also learn about other functions~~~

Guess you like

Origin juejin.im/post/7083758092269617183