0

我正在编写一个 Spring Boot API 应用程序,它必须具有插件架构。下面是一个典型的旅程:

  1. 我的应用程序可以执行任务(接受一些输入并返回输出)
  2. 我有一个TaskExecutor用一些方法调用的接口(例如execute(Object... inputArgs):)
  3. 我的应用程序的用户编写了一个插件来处理特定任务(用户只需实现该TaskExecutor.execute(Object... args)方法以满足任务的要求)。该插件被打包为.jar
  4. 我的应用程序中有一个名为Install new Plugin的屏幕,用户可以在其中上传.jar包含插件的文件。例如,用户上传了一个名为的新插件并定义了一个名为Send Emailsend-email-plugin-1.0.jar的新任务类型。
  5. 上传后,系统会将 jar 加载到其类路径中。
  6. 每当用户创建一个类型为Send Email的新任务并运行它时,就会调用TaskExecutorin 的实现。send-email-plugin-1.0.jar

我想满足以下要求:

  1. 插件应该在运行时加载
  2. 它应该.jar按需卸载/更新(当有新文件时)
  3. 我必须能够对其进行沙箱处理并允许/限制对主机上某些资源的访问。
  4. 宿主应用程序不需要beans从插件访问任何内容 - 我们可以将插件视为无弹簧部件(因为没有更好的术语)

我浏览过有关OSGiPF4j和其他的文章,但似乎无法完全理解它们——它们对于我的用例来说看起来很复杂(我不确定)

到目前为止我已经尝试过:

作为一段非常基本的代码,我尝试做这样的事情(假设我将用户上传的 jar 文件存储在文件系统的某个位置)。

@SuppressWarnings({ "rawtypes", "resource" })
    // pluginName: name of the plugin (or the JAR file)
    // entryPointClass: full name of the implementation class of TaskExecutor within this plugin. For ex: com.myorg.plugins.EmailTaskExecutorImpl
    public synchronized TaskExecutor loadAdapter(String pluginName, String entryPointClass) {
        try {
            URL jarUrl = getJarAsURL(pluginName);
            
            ClassLoader systemClassLoader = TaskExecutor.class.getClassLoader();
            ClassLoader customLoader = new URLClassLoader(new URL[] {jarUrl}, systemClassLoader);
            Class pluginEntryPoint = customLoader.loadClass(entryPointClass);
            Object pluginEntryPointObject = pluginEntryPoint.newInstance();
            return (TaskExecutor) pluginEntryPointObject;
        } catch (MalformedURLException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            log.error("Error loading JAR for {}", pluginName, e);
            return null;
        }
    }

它能够在运行时加载插件并执行作业。但是,显然它不会执行以下操作:

  • 不处理更新(如果我想将插件升级到 2.0 版怎么办?)
  • 它不是沙盒的。拥有对服务器的完全访问权限。我怎样才能防止这种情况?
  • 我必须考虑的任何线程安全/漏洞?

请有人指出我正确的方向。

谢谢,斯里拉姆

4

0 回答 0